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

4.115
Last change on this file since cf36b70 was cf36b70, checked in by Sebastian Huber <sebastian.huber@…>, on 12/31/14 at 09:56:05

IMFS: Replace node union with individual struct

This reduces the average node size.

Add and use IMFS_GENERIC_INITIALIZER().

  • Property mode set to 100644
File size: 4.4 KB
Line 
1/**
2 * @file
3 *
4 * @brief RTEMS Load Tarfs
5 * @ingroup IMFS
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2010.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include "imfs.h"
22
23#include <sys/param.h>
24#include <sys/stat.h>
25#include <string.h>
26#include <tar.h>
27#include <unistd.h>
28
29#include <rtems/untar.h>
30
31#define MAX_NAME_FIELD_SIZE      99
32
33int rtems_tarfs_load(
34  const char *mountpoint,
35  uint8_t *tar_image,
36  size_t tar_size
37)
38{
39   const char                       *hdr_ptr;
40   char                             filename[100];
41   char                             full_filename[256];
42   int                              hdr_chksum;
43   unsigned char                    linkflag;
44   unsigned long                    file_size;
45   unsigned long                    file_mode;
46   int                              offset;
47   unsigned long                    nblocks;
48   int rv = 0;
49   int eval_flags = RTEMS_FS_FOLLOW_LINK;
50   rtems_filesystem_eval_path_context_t ctx;
51   rtems_filesystem_location_info_t rootloc;
52   rtems_filesystem_location_info_t *currentloc =
53     rtems_filesystem_eval_path_start( &ctx, mountpoint, eval_flags );
54
55   rtems_filesystem_eval_path_extract_currentloc( &ctx, &rootloc );
56   rtems_filesystem_eval_path_set_flags(
57     &ctx,
58     RTEMS_FS_MAKE | RTEMS_FS_EXCLUSIVE
59   );
60
61   if (
62     rootloc.mt_entry->ops != &IMFS_ops
63       && rootloc.mt_entry->ops != &fifoIMFS_ops
64   ) {
65     rv = -1;
66   }
67
68   /*
69    * Create an IMFS node structure pointing to tar image memory.
70    */
71   offset = 0;
72   while ( rv == 0 ) {
73    if (offset + 512 > tar_size)
74      break;
75
76    /*
77     * Read a header.
78     */
79    hdr_ptr = (char *) &tar_image[offset];
80    offset += 512;
81    if (strncmp(&hdr_ptr[257], "ustar", 5))
82      break;
83
84    strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
85    filename[MAX_NAME_FIELD_SIZE] = '\0';
86
87    linkflag   = hdr_ptr[156];
88    file_mode  = _rtems_octal2ulong(&hdr_ptr[100], 8);
89    file_size  = _rtems_octal2ulong(&hdr_ptr[124], 12);
90    hdr_chksum = _rtems_octal2ulong(&hdr_ptr[148], 8);
91
92    if (_rtems_tar_header_checksum(hdr_ptr) != hdr_chksum)
93      break;
94
95    /*
96     * Generate an IMFS node depending on the file type.
97     * - For directories, just create directories as usual.  IMFS
98     *   will take care of the rest.
99     * - For symbolic links, create as usual
100     * - For files, create a file node with special tarfs properties.
101     */
102    if (linkflag == DIRTYPE) {
103      int len;
104      strncpy(full_filename, mountpoint, 255);
105      if (full_filename[(len=strlen(full_filename))-1] != '/')
106        strcat(full_filename, "/");
107      ++len;
108      strncat(full_filename, filename, 256-len-1);
109      rv = mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
110    }
111    /*
112     * Create a LINEAR_FILE node
113     */
114    else if (linkflag == REGTYPE) {
115      rtems_filesystem_location_free( currentloc );
116      rtems_filesystem_location_clone( currentloc, &rootloc );
117      rtems_filesystem_eval_path_set_path(
118        &ctx,
119        filename,
120        strlen( filename )
121      );
122      rtems_filesystem_eval_path_continue( &ctx );
123
124      if ( !rtems_filesystem_location_is_null( currentloc ) ) {
125        IMFS_linearfile_t *linfile = (IMFS_linearfile_t *)
126          IMFS_create_node(
127            currentloc,
128            IMFS_LINEAR_FILE,
129            rtems_filesystem_eval_path_get_token( &ctx ),
130            rtems_filesystem_eval_path_get_tokenlen( &ctx ),
131            (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG,
132            NULL
133          );
134
135        if ( linfile != NULL ) {
136          linfile->File.size = file_size;
137          linfile->direct    = &tar_image[offset];
138        }
139      }
140
141      nblocks = (((file_size) + 511) & ~511) / 512;
142      offset += 512 * nblocks;
143    }
144    /*
145     * Create a symbolic link
146     */
147    else if (linkflag == SYMTYPE) {
148      const char *linkto = hdr_ptr + 157;
149      int len;
150
151      strncpy(full_filename, mountpoint, 255);
152      if (full_filename[(len=strlen(full_filename))-1] != '/')
153        strcat(full_filename, "/");
154      ++len;
155      strncat(full_filename, filename, 256-len-1);
156
157      rv = symlink(linkto, full_filename);
158    }
159  }
160
161  rtems_filesystem_location_free( &rootloc );
162  rtems_filesystem_eval_path_cleanup( &ctx );
163
164  return rv;
165}
166
Note: See TracBrowser for help on using the repository browser.