source: rtems/c/src/libfs/src/imfs/imfs_load_tar.c @ d1941587

4.104.114.84.95
Last change on this file since d1941587 was d1941587, checked in by Joel Sherrill <joel.sherrill@…>, on 01/12/01 at 13:44:12

2001-01-12 Jake Janovetz <janovetz@…>

  • src/imfs/imfs.h, src/imfs/imfs_creat.c, src/imfs/imfs_debug.c, src/imfs/imfs_eval.c, src/imfs/imfs_fchmod.c, src/imfs/imfs_handlers_memfile.c, src/imfs/imfs_init.c, src/imfs/imfs_initsupp.c, src/imfs/imfs_stat.c, src/imfs/memfile.c, src/imfs/miniimfs_init.c: Final developmental update to "tarfs". When rtems_tarfs_load() is called, it checks the permissions on each file. If there is write permission, it just creates a standard file using "creat()" and therefore, uses the IMFS MEMORY_FILE. If there is no write permission, it creates a LINEAR_FILE node with the appropriate properties. If the permission is ever changed to writeable, IMFS_fchmod converts it to a regular memory file.
  • Property mode set to 100644
File size: 8.3 KB
Line 
1/**************************************************************************
2 * This file implements the "mount" procedure for tar-based IMFS
3 * extensions.  The TAR is not actually mounted under the IMFS.
4 * Directories from the TAR file are created as usual in the IMFS.
5 * File entries are created as IMFS_LINEAR_FILE nodes with their nods
6 * pointing to addresses in the TAR image.
7 *************************************************************************/
8
9#include <rtems.h>
10#include <rtems/libio_.h>
11#include <string.h>
12#include <chain.h>
13#include <imfs.h>
14
15
16/**************************************************************************
17 * TAR file format:
18 *
19 *   Offset   Length   Contents
20 *     0    100 bytes  File name ('\0' terminated, 99 maxmum length)
21 *   100      8 bytes  File mode (in octal ascii)
22 *   108      8 bytes  User ID (in octal ascii)
23 *   116      8 bytes  Group ID (in octal ascii)
24 *   124     12 bytes  File size (s) (in octal ascii)
25 *   136     12 bytes  Modify time (in octal ascii)
26 *   148      8 bytes  Header checksum (in octal ascii)
27 *   156      1 bytes  Link flag
28 *   157    100 bytes  Linkname ('\0' terminated, 99 maxmum length)
29 *   257      8 bytes  Magic ("ustar  \0")
30 *   265     32 bytes  User name ('\0' terminated, 31 maxmum length)
31 *   297     32 bytes  Group name ('\0' terminated, 31 maxmum length)
32 *   329      8 bytes  Major device ID (in octal ascii)
33 *   337      8 bytes  Minor device ID (in octal ascii)
34 *   345    167 bytes  Padding
35 *   512   (s+p)bytes  File contents (s+p) := (((s) + 511) & ~511),
36 *                     round up to 512 bytes
37 *
38 *   Checksum:
39 *   int i, sum;
40 *   char* header = tar_header_pointer;
41 *   sum = 0;
42 *   for(i = 0; i < 512; i++)
43 *       sum += 0xFF & header[i];
44 *************************************************************************/
45
46#define LF_OLDNORMAL  '\0'     /* Normal disk file, Unix compatible */
47#define LF_NORMAL     '0'      /* Normal disk file                  */
48#define LF_LINK       '1'      /* Link to previously dumped file    */
49#define LF_SYMLINK    '2'      /* Symbolic link                     */
50#define LF_CHR        '3'      /* Character special file            */
51#define LF_BLK        '4'      /* Block special file                */
52#define LF_DIR        '5'      /* Directory                         */
53#define LF_FIFO       '6'      /* FIFO special file                 */
54#define LF_CONFIG     '7'      /* Contiguous file                   */
55
56#define MAX_NAME_FIELD_SIZE      99
57
58#define MIN(a,b)   ((a)>(b)?(b):(a))
59
60
61/**************************************************************************
62 * This converts octal ASCII number representations into an
63 * unsigned long.  Only support 32-bit numbers for now.
64 *************************************************************************/
65static unsigned long
66octal2ulong(char *octascii, int len)
67{
68   int           i;
69   unsigned long num;
70   unsigned long mult;
71
72   num = 0;
73   mult = 1;
74   for (i=len-1; i>=0; i--)
75   {
76      if ((octascii[i] < '0') || (octascii[i] > '9'))
77         continue;
78
79      num  += mult*((unsigned long)(octascii[i] - '0'));
80      mult *= 8;
81   }
82   return(num);
83}
84
85
86/************************************************************************
87 * Compute the TAR checksum and check with the value in
88 * the archive.  The checksum is computed over the entire
89 * header, but the checksum field is substituted with blanks.
90 ************************************************************************/
91static int
92compute_tar_header_checksum(char *bufr)
93{
94   int  i, sum;
95
96
97   sum = 0;
98   for (i=0; i<512; i++)
99   {
100      if ((i >= 148) && (i < 156))
101         sum += 0xff & ' ';
102      else
103         sum += 0xff & bufr[i];
104   }
105   return(sum);
106}
107
108
109/**************************************************************************
110 * rtems_tarfs_load
111 *
112 * Here we create the mountpoint directory and load the tarfs at
113 * that node.  Once the IMFS has been mounted, we work through the
114 * tar image and perform as follows:
115 *  - For directories, simply call mkdir().  The IMFS creates nodes as
116 *    needed.
117 *  - For files, we make our own calls to IMFS eval_for_make and
118 *    create_node.
119 *************************************************************************/
120int
121rtems_tarfs_load(char *mountpoint,
122                 unsigned char *tar_image,
123                 unsigned long tar_size)
124{
125   rtems_filesystem_location_info_t root_loc;
126   rtems_filesystem_location_info_t loc;
127   char            *hdr_ptr;
128   char            filename[100];
129   char            full_filename[256];
130   int             hdr_chksum;
131   unsigned char   linkflag;
132   unsigned long   file_size;
133   unsigned long   file_mode;
134   int             offset;
135   unsigned long   nblocks;
136   IMFS_jnode_t    *node;
137   int             status;
138
139
140   status = rtems_filesystem_evaluate_path(mountpoint, 0, &root_loc, 0);
141   if (status != 0)
142      return(-1);
143
144   if (root_loc.ops != &IMFS_ops)
145      return(-1);
146
147   /***********************************************************************
148    * Create an IMFS node structure pointing to tar image memory.
149    **********************************************************************/
150   offset = 0;
151   while (1)
152   {
153      if (offset + 512 > tar_size)
154         break;
155
156      /******************************************************************
157       * Read a header.
158       ******************************************************************/
159      hdr_ptr = &tar_image[offset];
160      offset += 512;
161      if (strncmp(&hdr_ptr[257], "ustar  ", 7))
162         break;
163
164      strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
165      filename[MAX_NAME_FIELD_SIZE] = '\0';
166
167      linkflag   = hdr_ptr[156];
168      file_mode  = octal2ulong(&hdr_ptr[100], 8);
169      file_size  = octal2ulong(&hdr_ptr[124], 12);
170      hdr_chksum = (int)octal2ulong(&hdr_ptr[148], 8);
171
172      if (compute_tar_header_checksum(hdr_ptr) != hdr_chksum)
173         break;
174
175      /******************************************************************
176       * Generate an IMFS node depending on the file type.
177       * - For directories, just create directories as usual.  IMFS
178       *   will take care of the rest.
179       * - For files, create a file node with special tarfs properties.
180       *****************************************************************/
181      if (linkflag == LF_DIR)
182      {
183         strcpy(full_filename, mountpoint);
184         if (full_filename[strlen(full_filename)-1] != '/')
185            strcat(full_filename, "/");
186         strcat(full_filename, filename);
187         mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
188      }
189      /******************************************************************
190       * Create a LINEAR_FILE node if no user write permission.
191       *****************************************************************/
192      else if ((linkflag == LF_NORMAL) &&
193               ((file_mode & 0200) == 0000))
194      {
195         const char  *name;
196
197         loc = root_loc;
198         if (IMFS_evaluate_for_make(filename, &loc, &name) == 0)
199         {
200            node = IMFS_create_node(&loc,
201                                    IMFS_LINEAR_FILE, (char *)name,
202                                    (S_IRUSR | S_IRGRP | S_IROTH) | S_IFREG,
203                                    NULL);
204            node->info.linearfile.size   = file_size;
205            node->info.linearfile.direct = &tar_image[offset];
206         }
207
208         nblocks = (((file_size) + 511) & ~511) / 512;
209         offset += 512 * nblocks;
210      }
211      /******************************************************************
212       * Create a regular MEMORY_FILE if write permission exists.
213       *****************************************************************/
214      else if ((linkflag == LF_NORMAL) &&
215               ((file_mode & 0200) == 0200))
216      {
217         int fd;
218         int n, left, ptr;
219
220         strcpy(full_filename, mountpoint);
221         if (full_filename[strlen(full_filename)-1] != '/')
222            strcat(full_filename, "/");
223         strcat(full_filename, filename);
224
225         fd = creat(full_filename, S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP);
226         if (fd != -1)
227         {
228            left = file_size;
229            ptr  = offset;
230            while ((n = write(fd, &tar_image[ptr], left)) > 0)
231            {
232               left -= n;
233               ptr += n;
234            }
235            close(fd);
236         }
237
238         nblocks = (((file_size) + 511) & ~511) / 512;
239         offset += 512 * nblocks;
240      }
241   }
242
243   return(status);
244}
245
Note: See TracBrowser for help on using the repository browser.