source: rtems/cpukit/libfs/src/imfs/imfs_load_tar.c @ 624867b

4.104.114.84.95
Last change on this file since 624867b was 624867b, checked in by Eric Norum <WENorum@…>, on Feb 8, 2005 at 5:12:54 PM

Add copy-on-write semantics to rtems_tarfs_load().

  • Property mode set to 100644
File size: 5.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#include <rtems/tar.h>
29
30/**************************************************************************
31 * TAR file format:
32 *
33 *   Offset   Length   Contents
34 *     0    100 bytes  File name ('\0' terminated, 99 maxmum length)
35 *   100      8 bytes  File mode (in octal ascii)
36 *   108      8 bytes  User ID (in octal ascii)
37 *   116      8 bytes  Group ID (in octal ascii)
38 *   124     12 bytes  File size (s) (in octal ascii)
39 *   136     12 bytes  Modify time (in octal ascii)
40 *   148      8 bytes  Header checksum (in octal ascii)
41 *   156      1 bytes  Link flag
42 *   157    100 bytes  Linkname ('\0' terminated, 99 maxmum length)
43 *   257      8 bytes  Magic ("ustar  \0")
44 *   265     32 bytes  User name ('\0' terminated, 31 maxmum length)
45 *   297     32 bytes  Group name ('\0' terminated, 31 maxmum length)
46 *   329      8 bytes  Major device ID (in octal ascii)
47 *   337      8 bytes  Minor device ID (in octal ascii)
48 *   345    167 bytes  Padding
49 *   512   (s+p)bytes  File contents (s+p) := (((s) + 511) & ~511),
50 *                     round up to 512 bytes
51 *
52 *   Checksum:
53 *   int i, sum;
54 *   char* header = tar_header_pointer;
55 *   sum = 0;
56 *   for(i = 0; i < 512; i++)
57 *       sum += 0xFF & header[i];
58 *************************************************************************/
59
60#define MAX_NAME_FIELD_SIZE      99
61
62#define MIN(a,b)   ((a)>(b)?(b):(a))
63
64/**************************************************************************
65 * rtems_tarfs_load
66 *
67 * Here we create the mountpoint directory and load the tarfs at
68 * that node.  Once the IMFS has been mounted, we work through the
69 * tar image and perform as follows:
70 *  - For directories, simply call mkdir().  The IMFS creates nodes as
71 *    needed.
72 *  - For files, we make our own calls to IMFS eval_for_make and
73 *    create_node.
74 *************************************************************************/
75int
76rtems_tarfs_load(char *mountpoint,
77                 char *tar_image,
78                 size_t tar_size)
79{
80   rtems_filesystem_location_info_t root_loc;
81   rtems_filesystem_location_info_t loc;
82   const char     *hdr_ptr;
83   char            filename[100];
84   char            full_filename[256];
85   int             hdr_chksum;
86   unsigned char   linkflag;
87   unsigned long   file_size;
88   unsigned long   file_mode;
89   int             offset;
90   unsigned long   nblocks;
91   IMFS_jnode_t    *node;
92   int             status;
93
94
95   status = rtems_filesystem_evaluate_path(mountpoint, 0, &root_loc, 0);
96   if (status != 0)
97      return(-1);
98
99   if (root_loc.ops != &IMFS_ops)
100      return(-1);
101
102   /***********************************************************************
103    * Create an IMFS node structure pointing to tar image memory.
104    **********************************************************************/
105   offset = 0;
106   while (1)
107   {
108      if (offset + 512 > tar_size)
109         break;
110
111      /******************************************************************
112       * Read a header.
113       ******************************************************************/
114      hdr_ptr = &tar_image[offset];
115      offset += 512;
116      if (strncmp(&hdr_ptr[257], "ustar  ", 7))
117         break;
118
119      strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
120      filename[MAX_NAME_FIELD_SIZE] = '\0';
121
122      linkflag   = hdr_ptr[156];
123      file_mode  = _rtems_octal2ulong(&hdr_ptr[100], 8);
124      file_size  = _rtems_octal2ulong(&hdr_ptr[124], 12);
125      hdr_chksum = _rtems_octal2ulong(&hdr_ptr[148], 8);
126
127      if (_rtems_tar_header_checksum(hdr_ptr) != hdr_chksum)
128         break;
129
130      /******************************************************************
131       * Generate an IMFS node depending on the file type.
132       * - For directories, just create directories as usual.  IMFS
133       *   will take care of the rest.
134       * - For files, create a file node with special tarfs properties.
135       *****************************************************************/
136      if (linkflag == DIRTYPE)
137      {
138         strcpy(full_filename, mountpoint);
139         if (full_filename[strlen(full_filename)-1] != '/')
140            strcat(full_filename, "/");
141         strcat(full_filename, filename);
142         mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
143      }
144      /******************************************************************
145       * Create a LINEAR_FILE node
146       *****************************************************************/
147      else if (linkflag == REGTYPE)
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                        (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | 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
167   return(status);
168}
169
Note: See TracBrowser for help on using the repository browser.