source: rtems/cpukit/libcsupport/src/mount.c @ 3c1d387

4.115
Last change on this file since 3c1d387 was 3c1d387, checked in by Sebastian Huber <sebastian.huber@…>, on 11/09/12 at 15:02:02

Filesystem: Preserve source NULL pointer in mount

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/*
2 *  mount()
3 *
4 *  XXX
5 *
6 *  XXX make sure no required ops are NULL
7 *  XXX make sure no optional ops you are using are NULL
8 *  XXX unmount should be required.
9 *
10 *  COPYRIGHT (c) 1989-2010.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  Copyright (c) 2010-2012 embedded brains GmbH.
14 *
15 *  The license and distribution terms for this file may be
16 *  found in the file LICENSE in this distribution or at
17 *  http://www.rtems.com/license/LICENSE.
18 */
19
20#if HAVE_CONFIG_H
21  #include "config.h"
22#endif
23
24#include <stdlib.h>
25#include <string.h>
26
27#include <rtems/libio_.h>
28
29RTEMS_CHAIN_DEFINE_EMPTY(rtems_filesystem_mount_table);
30
31/*
32 * Default pathconfs.
33 */
34const rtems_filesystem_limits_and_options_t rtems_filesystem_default_pathconf = {
35   5,    /* link_max: count */
36   128,  /* max_canon: max formatted input line size */
37   7,    /* max_input: max input line size */
38   255,  /* name_max: max name */
39   255,  /* path_max: max path */
40   1024, /* pipe_buf: pipe buffer size */
41   0,    /* posix_async_io: async IO supported on fs, 0=no, 1=yes */
42   0 ,   /* posix_chown_restrictions: can chown: 0=no, 1=yes */
43   1,    /* posix_no_trunc: error on filenames > max name, 0=no, 1=yes */
44   0,    /* posix_prio_io: priority IO, 0=no, 1=yes */
45   0,    /* posix_sync_io: file can be sync'ed, 0=no, 1=yes */
46   0     /* posix_vdisable: special char processing, 0=no, 1=yes */
47};
48
49static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
50  const char *source_or_null,
51  const char *target_or_null,
52  const char *filesystemtype,
53  size_t *target_length_ptr
54)
55{
56  const char *target = target_or_null != NULL ? target_or_null : "/";
57  size_t filesystemtype_size = strlen( filesystemtype ) + 1;
58  size_t source_size = source_or_null != NULL ?
59    strlen( source_or_null ) + 1 : 0;
60  size_t target_size = strlen( target ) + 1;
61  size_t size = sizeof( rtems_filesystem_mount_table_entry_t )
62    + filesystemtype_size + source_size + target_size
63    + sizeof( rtems_filesystem_global_location_t );
64  rtems_filesystem_mount_table_entry_t *mt_entry = calloc( 1, size );
65
66  if ( mt_entry != NULL ) {
67    rtems_filesystem_global_location_t *mt_fs_root =
68      (rtems_filesystem_global_location_t *)
69        ((char *) mt_entry + sizeof( *mt_entry ));
70    char *str = (char *) mt_fs_root + sizeof( *mt_fs_root );
71
72    memcpy( str, filesystemtype, filesystemtype_size );
73    mt_entry->type = str;
74    str += filesystemtype_size;
75
76    if ( source_or_null != NULL ) {
77      memcpy( str, source_or_null, source_size );
78      mt_entry->dev = str;
79      str += source_size;
80    }
81
82    memcpy( str, target, target_size );
83    mt_entry->target = str;
84    str += target_size;
85
86    mt_entry->mounted = true;
87    mt_entry->mt_fs_root = mt_fs_root;
88    mt_entry->pathconf_limits_and_options = &rtems_filesystem_default_pathconf;
89
90    mt_fs_root->location.mt_entry = mt_entry;
91    mt_fs_root->reference_count = 1;
92
93    rtems_chain_initialize(
94      &mt_entry->location_chain,
95      mt_fs_root,
96      1,
97      sizeof(*mt_fs_root)
98    );
99  } else {
100    free( mt_entry );
101  }
102
103  *target_length_ptr = target_size - 1;
104
105  return mt_entry;
106}
107
108static int register_subordinate_file_system(
109  rtems_filesystem_mount_table_entry_t *mt_entry,
110  const char *target
111)
112{
113  int rv = 0;
114  rtems_filesystem_eval_path_context_t ctx;
115  int eval_flags = RTEMS_FS_PERMS_RWX
116    | RTEMS_FS_FOLLOW_LINK;
117  rtems_filesystem_location_info_t *currentloc =
118    rtems_filesystem_eval_path_start( &ctx, target, eval_flags );
119
120  if ( !rtems_filesystem_location_is_instance_root( currentloc ) ) {
121    rtems_filesystem_location_info_t targetloc;
122    rtems_filesystem_global_location_t *mt_point_node;
123
124    rtems_filesystem_eval_path_extract_currentloc( &ctx, &targetloc );
125    mt_point_node = rtems_filesystem_location_transform_to_global( &targetloc );
126    mt_entry->mt_point_node = mt_point_node;
127    rv = (*mt_point_node->location.mt_entry->ops->mount_h)( mt_entry );
128    if ( rv == 0 ) {
129      rtems_filesystem_mt_lock();
130      rtems_chain_append_unprotected(
131        &rtems_filesystem_mount_table,
132        &mt_entry->mt_node
133      );
134      rtems_filesystem_mt_unlock();
135    } else {
136      rtems_filesystem_global_location_release( mt_point_node );
137    }
138  } else {
139    rtems_filesystem_eval_path_error( &ctx, EBUSY );
140    rv = -1;
141  }
142
143  rtems_filesystem_eval_path_cleanup( &ctx );
144
145  return rv;
146}
147
148static int register_root_file_system(
149  rtems_filesystem_mount_table_entry_t *mt_entry
150)
151{
152  int rv = 0;
153
154  rtems_filesystem_mt_lock();
155  if ( rtems_chain_is_empty( &rtems_filesystem_mount_table ) ) {
156    rtems_chain_append_unprotected(
157      &rtems_filesystem_mount_table,
158      &mt_entry->mt_node
159    );
160  } else {
161    errno = EINVAL;
162    rv = -1;
163  }
164  rtems_filesystem_mt_unlock();
165
166  if ( rv == 0 ) {
167    rtems_filesystem_global_location_t *new_fs_root =
168      rtems_filesystem_global_location_obtain( &mt_entry->mt_fs_root );
169    rtems_filesystem_global_location_t *new_fs_current =
170      rtems_filesystem_global_location_obtain( &mt_entry->mt_fs_root );
171
172    rtems_filesystem_global_location_assign(
173      &rtems_filesystem_root,
174      new_fs_root
175    );
176    rtems_filesystem_global_location_assign(
177      &rtems_filesystem_current,
178      new_fs_current
179    );
180  }
181
182  return rv;
183}
184
185int mount(
186  const char                 *source,
187  const char                 *target,
188  const char                 *filesystemtype,
189  rtems_filesystem_options_t options,
190  const void                 *data
191)
192{
193  int rv = 0;
194
195  if (
196    options == RTEMS_FILESYSTEM_READ_ONLY
197      || options == RTEMS_FILESYSTEM_READ_WRITE
198  ) {
199    rtems_filesystem_fsmount_me_t fsmount_me_h =
200      rtems_filesystem_get_mount_handler( filesystemtype );
201
202    if ( fsmount_me_h != NULL ) {
203      size_t target_length = 0;
204      rtems_filesystem_mount_table_entry_t *mt_entry = alloc_mount_table_entry(
205        source,
206        target,
207        filesystemtype,
208        &target_length
209      );
210
211      if ( mt_entry != NULL ) {
212        mt_entry->writeable = options == RTEMS_FILESYSTEM_READ_WRITE;
213
214        rv = (*fsmount_me_h)( mt_entry, data );
215        if ( rv == 0 ) {
216          if ( target != NULL ) {
217            rv = register_subordinate_file_system( mt_entry, target );
218          } else {
219            rv = register_root_file_system( mt_entry );
220          }
221
222          if ( rv != 0 ) {
223            (*mt_entry->ops->fsunmount_me_h)( mt_entry );
224          }
225        }
226
227        if ( rv != 0 ) {
228          free( mt_entry );
229        }
230      } else {
231        errno = ENOMEM;
232        rv = -1;
233      }
234    } else {
235      errno = EINVAL;
236      rv = -1;
237    }
238  } else {
239    errno = EINVAL;
240    rv = -1;
241  }
242
243  return rv;
244}
Note: See TracBrowser for help on using the repository browser.