source: rtems/c/src/libfs/src/imfs/imfs_load_tar.c @ 059a3714

4.104.114.84.95
Last change on this file since 059a3714 was d6b1d73, checked in by Joel Sherrill <joel.sherrill@…>, on 01/22/01 at 14:05:14

2001-01-22 Ralf Corsepius <corsepiu@…>

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