source: rtems/cpukit/libfs/src/imfs/imfs_load_tar.c @ 1996aee7

4.104.114.84.95
Last change on this file since 1996aee7 was 1996aee7, checked in by Ralf Corsepius <ralf.corsepius@…>, on Feb 7, 2005 at 1:25:14 PM

2005-02-07 Ralf Corsepius <ralf.corsepius@…>

  • libfs/src/imfs/imfs.h, libfs/src/imfs/imfs_load_tar.c, libmisc/untar/untar.c, libmisc/untar/untar.h: Various generalizations and fixes.
  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * $Id$
3 */
4
5#if HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9/**************************************************************************
10 * This file implements the "mount" procedure for tar-based IMFS
11 * extensions.  The TAR is not actually mounted under the IMFS.
12 * Directories from the TAR file are created as usual in the IMFS.
13 * File entries are created as IMFS_LINEAR_FILE nodes with their nods
14 * pointing to addresses in the TAR image.
15 *************************************************************************/
16
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <fcntl.h>
20
21#include <string.h>
22
23#include <rtems.h>
24#include <rtems/libio_.h>
25#include <rtems/chain.h>
26#include <rtems/imfs.h>
27#include <rtems/untar.h>
28
29/**************************************************************************
30 * TAR file format:
31 *
32 *   Offset   Length   Contents
33 *     0    100 bytes  File name ('\0' terminated, 99 maxmum length)
34 *   100      8 bytes  File mode (in octal ascii)
35 *   108      8 bytes  User ID (in octal ascii)
36 *   116      8 bytes  Group ID (in octal ascii)
37 *   124     12 bytes  File size (s) (in octal ascii)
38 *   136     12 bytes  Modify time (in octal ascii)
39 *   148      8 bytes  Header checksum (in octal ascii)
40 *   156      1 bytes  Link flag
41 *   157    100 bytes  Linkname ('\0' terminated, 99 maxmum length)
42 *   257      8 bytes  Magic ("ustar  \0")
43 *   265     32 bytes  User name ('\0' terminated, 31 maxmum length)
44 *   297     32 bytes  Group name ('\0' terminated, 31 maxmum length)
45 *   329      8 bytes  Major device ID (in octal ascii)
46 *   337      8 bytes  Minor device ID (in octal ascii)
47 *   345    167 bytes  Padding
48 *   512   (s+p)bytes  File contents (s+p) := (((s) + 511) & ~511),
49 *                     round up to 512 bytes
50 *
51 *   Checksum:
52 *   int i, sum;
53 *   char* header = tar_header_pointer;
54 *   sum = 0;
55 *   for(i = 0; i < 512; i++)
56 *       sum += 0xFF & header[i];
57 *************************************************************************/
58
59#define MAX_NAME_FIELD_SIZE      99
60
61#define MIN(a,b)   ((a)>(b)?(b):(a))
62
63/**************************************************************************
64 * rtems_tarfs_load
65 *
66 * Here we create the mountpoint directory and load the tarfs at
67 * that node.  Once the IMFS has been mounted, we work through the
68 * tar image and perform as follows:
69 *  - For directories, simply call mkdir().  The IMFS creates nodes as
70 *    needed.
71 *  - For files, we make our own calls to IMFS eval_for_make and
72 *    create_node.
73 *************************************************************************/
74int
75rtems_tarfs_load(char *mountpoint,
76                 char *tar_image,
77                 size_t tar_size)
78{
79   rtems_filesystem_location_info_t root_loc;
80   rtems_filesystem_location_info_t loc;
81   const char     *hdr_ptr;
82   char            filename[100];
83   char            full_filename[256];
84   int             hdr_chksum;
85   unsigned char   linkflag;
86   unsigned long   file_size;
87   unsigned long   file_mode;
88   int             offset;
89   unsigned long   nblocks;
90   IMFS_jnode_t    *node;
91   int             status;
92
93
94   status = rtems_filesystem_evaluate_path(mountpoint, 0, &root_loc, 0);
95   if (status != 0)
96      return(-1);
97
98   if (root_loc.ops != &IMFS_ops)
99      return(-1);
100
101   /***********************************************************************
102    * Create an IMFS node structure pointing to tar image memory.
103    **********************************************************************/
104   offset = 0;
105   while (1)
106   {
107      if (offset + 512 > tar_size)
108         break;
109
110      /******************************************************************
111       * Read a header.
112       ******************************************************************/
113      hdr_ptr = &tar_image[offset];
114      offset += 512;
115      if (strncmp(&hdr_ptr[257], "ustar  ", 7))
116         break;
117
118      strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
119      filename[MAX_NAME_FIELD_SIZE] = '\0';
120
121      linkflag   = hdr_ptr[156];
122      file_mode  = _rtems_octal2ulong(&hdr_ptr[100], 8);
123      file_size  = _rtems_octal2ulong(&hdr_ptr[124], 12);
124      hdr_chksum = _rtems_octal2ulong(&hdr_ptr[148], 8);
125
126      if (_rtems_tar_header_checksum(hdr_ptr) != hdr_chksum)
127         break;
128
129      /******************************************************************
130       * Generate an IMFS node depending on the file type.
131       * - For directories, just create directories as usual.  IMFS
132       *   will take care of the rest.
133       * - For files, create a file node with special tarfs properties.
134       *****************************************************************/
135      if (linkflag == DIRTYPE)
136      {
137         strcpy(full_filename, mountpoint);
138         if (full_filename[strlen(full_filename)-1] != '/')
139            strcat(full_filename, "/");
140         strcat(full_filename, filename);
141         mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
142      }
143      /******************************************************************
144       * Create a LINEAR_FILE node if no user write permission.
145       *****************************************************************/
146      else if ((linkflag == REGTYPE) &&
147               ((file_mode & 0200) == 0000))
148      {
149         const char  *name;
150
151         loc = root_loc;
152         if (IMFS_evaluate_for_make(filename, &loc, &name) == 0)
153         {
154            node = IMFS_create_node(&loc,
155                                    IMFS_LINEAR_FILE, (char *)name,
156                                    (S_IRUSR | S_IRGRP | S_IROTH) | S_IFREG,
157                                    NULL);
158            node->info.linearfile.size   = file_size;
159            node->info.linearfile.direct = &tar_image[offset];
160         }
161
162         nblocks = (((file_size) + 511) & ~511) / 512;
163         offset += 512 * nblocks;
164      }
165      /******************************************************************
166       * Create a regular MEMORY_FILE if write permission exists.
167       *****************************************************************/
168      else if ((linkflag == REGTYPE) &&
169               ((file_mode & 0200) == 0200))
170      {
171         int fd;
172         int n, left, ptr;
173
174         strcpy(full_filename, mountpoint);
175         if (full_filename[strlen(full_filename)-1] != '/')
176            strcat(full_filename, "/");
177         strcat(full_filename, filename);
178
179         fd = creat(full_filename, S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP);
180         if (fd != -1)
181         {
182            left = file_size;
183            ptr  = offset;
184            while ((n = write(fd, &tar_image[ptr], left)) > 0)
185            {
186               left -= n;
187               ptr += n;
188            }
189            close(fd);
190         }
191
192         nblocks = (((file_size) + 511) & ~511) / 512;
193         offset += 512 * nblocks;
194      }
195   }
196
197   return(status);
198}
199
Note: See TracBrowser for help on using the repository browser.