OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libfs/] [src/] [imfs/] [imfs_load_tar.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 * imfs_load_tar.c,v 1.6 2002/01/08 12:05:36 joel Exp
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 <chain.h>
26
#include <imfs.h>
27
 
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 LF_OLDNORMAL  '\0'     /* Normal disk file, Unix compatible */
60
#define LF_NORMAL     '0'      /* Normal disk file                  */
61
#define LF_LINK       '1'      /* Link to previously dumped file    */
62
#define LF_SYMLINK    '2'      /* Symbolic link                     */
63
#define LF_CHR        '3'      /* Character special file            */
64
#define LF_BLK        '4'      /* Block special file                */
65
#define LF_DIR        '5'      /* Directory                         */
66
#define LF_FIFO       '6'      /* FIFO special file                 */
67
#define LF_CONFIG     '7'      /* Contiguous file                   */
68
 
69
#define MAX_NAME_FIELD_SIZE      99
70
 
71
#define MIN(a,b)   ((a)>(b)?(b):(a))
72
 
73
static unsigned long octal2ulong(char *octascii, int len);
74
static int compute_tar_header_checksum(char *bufr);
75
 
76
/**************************************************************************
77
 * rtems_tarfs_load
78
 *
79
 * Here we create the mountpoint directory and load the tarfs at
80
 * that node.  Once the IMFS has been mounted, we work through the
81
 * tar image and perform as follows:
82
 *  - For directories, simply call mkdir().  The IMFS creates nodes as
83
 *    needed.
84
 *  - For files, we make our own calls to IMFS eval_for_make and
85
 *    create_node.
86
 *************************************************************************/
87
int
88
rtems_tarfs_load(char *mountpoint,
89
                 unsigned char *tar_image,
90
                 unsigned long tar_size)
91
{
92
   rtems_filesystem_location_info_t root_loc;
93
   rtems_filesystem_location_info_t loc;
94
   char            *hdr_ptr;
95
   char            filename[100];
96
   char            full_filename[256];
97
   int             hdr_chksum;
98
   unsigned char   linkflag;
99
   unsigned long   file_size;
100
   unsigned long   file_mode;
101
   int             offset;
102
   unsigned long   nblocks;
103
   IMFS_jnode_t    *node;
104
   int             status;
105
 
106
 
107
   status = rtems_filesystem_evaluate_path(mountpoint, 0, &root_loc, 0);
108
   if (status != 0)
109
      return(-1);
110
 
111
   if (root_loc.ops != &IMFS_ops)
112
      return(-1);
113
 
114
   /***********************************************************************
115
    * Create an IMFS node structure pointing to tar image memory.
116
    **********************************************************************/
117
   offset = 0;
118
   while (1)
119
   {
120
      if (offset + 512 > tar_size)
121
         break;
122
 
123
      /******************************************************************
124
       * Read a header.
125
       ******************************************************************/
126
      hdr_ptr = &tar_image[offset];
127
      offset += 512;
128
      if (strncmp(&hdr_ptr[257], "ustar  ", 7))
129
         break;
130
 
131
      strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
132
      filename[MAX_NAME_FIELD_SIZE] = '\0';
133
 
134
      linkflag   = hdr_ptr[156];
135
      file_mode  = octal2ulong(&hdr_ptr[100], 8);
136
      file_size  = octal2ulong(&hdr_ptr[124], 12);
137
      hdr_chksum = (int)octal2ulong(&hdr_ptr[148], 8);
138
 
139
      if (compute_tar_header_checksum(hdr_ptr) != hdr_chksum)
140
         break;
141
 
142
      /******************************************************************
143
       * Generate an IMFS node depending on the file type.
144
       * - For directories, just create directories as usual.  IMFS
145
       *   will take care of the rest.
146
       * - For files, create a file node with special tarfs properties.
147
       *****************************************************************/
148
      if (linkflag == LF_DIR)
149
      {
150
         strcpy(full_filename, mountpoint);
151
         if (full_filename[strlen(full_filename)-1] != '/')
152
            strcat(full_filename, "/");
153
         strcat(full_filename, filename);
154
         mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
155
      }
156
      /******************************************************************
157
       * Create a LINEAR_FILE node if no user write permission.
158
       *****************************************************************/
159
      else if ((linkflag == LF_NORMAL) &&
160
               ((file_mode & 0200) == 0000))
161
      {
162
         const char  *name;
163
 
164
         loc = root_loc;
165
         if (IMFS_evaluate_for_make(filename, &loc, &name) == 0)
166
         {
167
            node = IMFS_create_node(&loc,
168
                                    IMFS_LINEAR_FILE, (char *)name,
169
                                    (S_IRUSR | S_IRGRP | S_IROTH) | S_IFREG,
170
                                    NULL);
171
            node->info.linearfile.size   = file_size;
172
            node->info.linearfile.direct = &tar_image[offset];
173
         }
174
 
175
         nblocks = (((file_size) + 511) & ~511) / 512;
176
         offset += 512 * nblocks;
177
      }
178
      /******************************************************************
179
       * Create a regular MEMORY_FILE if write permission exists.
180
       *****************************************************************/
181
      else if ((linkflag == LF_NORMAL) &&
182
               ((file_mode & 0200) == 0200))
183
      {
184
         int fd;
185
         int n, left, ptr;
186
 
187
         strcpy(full_filename, mountpoint);
188
         if (full_filename[strlen(full_filename)-1] != '/')
189
            strcat(full_filename, "/");
190
         strcat(full_filename, filename);
191
 
192
         fd = creat(full_filename, S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP);
193
         if (fd != -1)
194
         {
195
            left = file_size;
196
            ptr  = offset;
197
            while ((n = write(fd, &tar_image[ptr], left)) > 0)
198
            {
199
               left -= n;
200
               ptr += n;
201
            }
202
            close(fd);
203
         }
204
 
205
         nblocks = (((file_size) + 511) & ~511) / 512;
206
         offset += 512 * nblocks;
207
      }
208
   }
209
 
210
   return(status);
211
}
212
 
213
/**************************************************************************
214
 * This converts octal ASCII number representations into an
215
 * unsigned long.  Only support 32-bit numbers for now.
216
 *************************************************************************/
217
static unsigned long
218
octal2ulong(char *octascii, int len)
219
{
220
   int           i;
221
   unsigned long num;
222
   unsigned long mult;
223
 
224
   num = 0;
225
   mult = 1;
226
   for (i=len-1; i>=0; i--)
227
   {
228
      if (octascii[i] < '0')
229
         continue;
230
      if (octascii[i] > '9')
231
         continue;
232
 
233
      num  += mult*((unsigned long)(octascii[i] - '0'));
234
      mult *= 8;
235
   }
236
   return(num);
237
}
238
 
239
 
240
/************************************************************************
241
 * Compute the TAR checksum and check with the value in
242
 * the archive.  The checksum is computed over the entire
243
 * header, but the checksum field is substituted with blanks.
244
 ************************************************************************/
245
static int
246
compute_tar_header_checksum(char *bufr)
247
{
248
   int  i, sum;
249
 
250
 
251
   sum = 0;
252
   for (i=0; i<512; i++)
253
   {
254
      if ((i >= 148) && (i < 156))
255
         sum += 0xff & ' ';
256
      else
257
         sum += 0xff & bufr[i];
258
   }
259
   return(sum);
260
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.