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

4.11
Last change on this file since da154e14 was da154e14, checked in by Sebastian Huber <sebastian.huber@…>, on May 14, 2012 at 2:55:41 PM

Filesystem: Move operations to mount table entry

The scope of the file system operations is the file system instance.
The scope of the file system node handlers is the file location. The
benefit of moving the operations to the mount table entry is a size
reduction of the file location (rtems_filesystem_location_info_t). The
code size is slightly increased due to additional load instructions.

Restructure rtems_filesystem_mount_table_entry_t to improve cache
efficiency.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2010.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 */
9
10#if HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14/*
15 * This file implements the "mount" procedure for tar-based IMFS
16 * extensions.  The TAR is not actually mounted under the IMFS.
17 * Directories from the TAR file are created as usual in the IMFS.
18 * File entries are created as IMFS_LINEAR_FILE nodes with their nods
19 * pointing to addresses in the TAR image.
20 */
21
22#include "imfs.h"
23
24#include <sys/stat.h>
25#include <string.h>
26#include <tar.h>
27
28#include <rtems/untar.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 PAX ("ustar\0" + 2 bytes padding)
44 *   257      8 bytes  Magic GNU tar ("ustar  \0")
45 *   265     32 bytes  User name ('\0' terminated, 31 maxmum length)
46 *   297     32 bytes  Group name ('\0' terminated, 31 maxmum length)
47 *   329      8 bytes  Major device ID (in octal ascii)
48 *   337      8 bytes  Minor device ID (in octal ascii)
49 *   345    167 bytes  Padding
50 *   512   (s+p)bytes  File contents (s+p) := (((s) + 511) & ~511),
51 *                     round up to 512 bytes
52 *
53 *   Checksum:
54 *   int i, sum;
55 *   char* header = tar_header_pointer;
56 *   sum = 0;
57 *   for(i = 0; i < 512; i++)
58 *       sum += 0xFF & header[i];
59 */
60
61#define MAX_NAME_FIELD_SIZE      99
62
63#define MIN(a,b)   ((a)>(b)?(b):(a))
64
65/*
66 * rtems_tarfs_load
67 *
68 * Here we create the mountpoint directory and load the tarfs at
69 * that node.  Once the IMFS has been mounted, we work through the
70 * tar image and perform as follows:
71 *  - For directories, simply call mkdir().  The IMFS creates nodes as
72 *    needed.
73 *  - For files, we make our own calls to IMFS eval_for_make and
74 *    create_node.
75 */
76int rtems_tarfs_load(
77  const char *mountpoint,
78  uint8_t *tar_image,
79  size_t tar_size
80)
81{
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 rv = 0;
93   int eval_flags = RTEMS_FS_FOLLOW_LINK;
94   rtems_filesystem_eval_path_context_t ctx;
95   rtems_filesystem_location_info_t rootloc;
96   rtems_filesystem_location_info_t *currentloc =
97     rtems_filesystem_eval_path_start( &ctx, mountpoint, eval_flags );
98
99   rtems_filesystem_eval_path_extract_currentloc( &ctx, &rootloc );
100   rtems_filesystem_eval_path_set_flags(
101     &ctx,
102     RTEMS_FS_MAKE | RTEMS_FS_EXCLUSIVE
103   );
104
105   if (
106     rootloc.mt_entry->ops != &IMFS_ops
107       && rootloc.mt_entry->ops != &fifoIMFS_ops
108   ) {
109     rv = -1;
110   }
111
112   /*
113    * Create an IMFS node structure pointing to tar image memory.
114    */
115   offset = 0;
116   while ( rv == 0 ) {
117    if (offset + 512 > tar_size)
118      break;
119
120    /*
121     * Read a header.
122     */
123    hdr_ptr = (char *) &tar_image[offset];
124    offset += 512;
125    if (strncmp(&hdr_ptr[257], "ustar", 5))
126      break;
127
128    strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
129    filename[MAX_NAME_FIELD_SIZE] = '\0';
130
131    linkflag   = hdr_ptr[156];
132    file_mode  = _rtems_octal2ulong(&hdr_ptr[100], 8);
133    file_size  = _rtems_octal2ulong(&hdr_ptr[124], 12);
134    hdr_chksum = _rtems_octal2ulong(&hdr_ptr[148], 8);
135
136    if (_rtems_tar_header_checksum(hdr_ptr) != hdr_chksum)
137      break;
138
139    /*
140     * Generate an IMFS node depending on the file type.
141     * - For directories, just create directories as usual.  IMFS
142     *   will take care of the rest.
143     * - For files, create a file node with special tarfs properties.
144     */
145    if (linkflag == DIRTYPE) {
146      strcpy(full_filename, mountpoint);
147      if (full_filename[strlen(full_filename)-1] != '/')
148        strcat(full_filename, "/");
149      strcat(full_filename, filename);
150      mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
151    }
152    /*
153     * Create a LINEAR_FILE node
154     */
155    else if (linkflag == REGTYPE) {
156      rtems_filesystem_location_free( currentloc );
157      rtems_filesystem_location_clone( currentloc, &rootloc );
158      rtems_filesystem_eval_path_set_path(
159        &ctx,
160        filename,
161        strlen( filename )
162      );
163      rtems_filesystem_eval_path_continue( &ctx );
164
165      if ( !rtems_filesystem_location_is_null( currentloc ) ) {
166        node = IMFS_create_node(
167          currentloc,
168          IMFS_LINEAR_FILE,
169          rtems_filesystem_eval_path_get_token( &ctx ),
170          rtems_filesystem_eval_path_get_tokenlen( &ctx ),
171          (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG,
172          NULL
173        );
174        node->info.linearfile.size   = file_size;
175        node->info.linearfile.direct = &tar_image[offset];
176      }
177
178      nblocks = (((file_size) + 511) & ~511) / 512;
179      offset += 512 * nblocks;
180    }
181  }
182
183  rtems_filesystem_location_free( &rootloc );
184  rtems_filesystem_eval_path_cleanup( &ctx );
185
186  return rv;
187}
188
Note: See TracBrowser for help on using the repository browser.