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

4.115
Last change on this file since 24ec25d was 24ec25d, checked in by Sebastian Huber <sebastian.huber@…>, on 02/05/15 at 15:14:59

IMFS: Introduce IMFS_mknod_control

Drop IMFS_node_control::node_size field and add node_size parameter to
IMFS_allocate_node() and IMFS_create_node(). This reduces the size of
generic nodes.

  • 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_node_control_linfile,
129            sizeof( IMFS_file_t ),
130            rtems_filesystem_eval_path_get_token( &ctx ),
131            rtems_filesystem_eval_path_get_tokenlen( &ctx ),
132            (file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG,
133            NULL
134          );
135
136        if ( linfile != NULL ) {
137          linfile->File.size = file_size;
138          linfile->direct    = &tar_image[offset];
139        }
140      }
141
142      nblocks = (((file_size) + 511) & ~511) / 512;
143      offset += 512 * nblocks;
144    }
145    /*
146     * Create a symbolic link
147     */
148    else if (linkflag == SYMTYPE) {
149      const char *linkto = hdr_ptr + 157;
150      int len;
151
152      strncpy(full_filename, mountpoint, 255);
153      if (full_filename[(len=strlen(full_filename))-1] != '/')
154        strcat(full_filename, "/");
155      ++len;
156      strncat(full_filename, filename, 256-len-1);
157
158      rv = symlink(linkto, full_filename);
159    }
160  }
161
162  rtems_filesystem_location_free( &rootloc );
163  rtems_filesystem_eval_path_cleanup( &ctx );
164
165  return rv;
166}
167
Note: See TracBrowser for help on using the repository browser.