source: rtems/cpukit/libcsupport/src/mount.c @ 955a34b5

4.10
Last change on this file since 955a34b5 was 955a34b5, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 1, 2010 at 3:18:06 PM

2010-07-01 Sebastian Huber <sebastian.huber@…>

  • libcsupport/include/rtems/libio_.h: Removed rtems_filesystem_mount_table_control.
  • libcsupport/include/rtems/libio.h, libcsupport/src/mount-mgr.c, libcsupport/src/mount.c libcsupport/src/statvfs.c, libcsupport/src/unmount.c, libmisc/shell/main_mount.c: Documentation. Removed rtems_filesystem_mounts_first() and rtems_filesystem_mounts_next(). Added rtems_filesystem_mount_iterate(). Changed return type of rtems_filesystem_iterate(). Removed rtems_filesystem_nodes_equal().

2010-07-01 Sebastian Huber <sebastian.huber@…>

  • libfs/src/nfsclient/src/nfs.c, libfs/src/nfsclient/src/nfs.c, libfs/src/nfsclient/src/librtemsNfs.h: Renamed rtems_nfsfs_initialize() in rtems_nfs_initialize().
  • sapi/include/confdefs.h: Reflect changes above. Renamed *_miniIMFS in *_MINIIMFS. Renamed *_NFSFS in *_NFS.
  • Property mode set to 100644
File size: 7.6 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-1999.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  Copyright (c) 2010 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 *  $Id$
20 */
21
22#if HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <rtems/chain.h>
29#include <rtems/seterr.h>
30#include <fcntl.h>
31#include <unistd.h>
32#include <errno.h>
33#include <stdlib.h>
34#include <string.h>
35#include <assert.h>
36
37#include <rtems/libio_.h>
38
39static RTEMS_CHAIN_DEFINE_EMPTY(mount_chain);
40
41/*
42 * Default pathconfs.
43 */
44const rtems_filesystem_limits_and_options_t rtems_filesystem_default_pathconf = {
45   5,    /* link_max: count */
46   128,  /* max_canon: max formatted input line size */
47   7,    /* max_input: max input line size */
48   255,  /* name_max: max name */
49   255,  /* path_max: max path */
50   1024, /* pipe_buf: pipe buffer size */
51   0,    /* posix_async_io: async IO supported on fs, 0=no, 1=yes */
52   0 ,   /* posix_chown_restrictions: can chown: 0=no, 1=yes */
53   1,    /* posix_no_trunc: error on filenames > max name, 0=no, 1=yes */
54   0,    /* posix_prio_io: priority IO, 0=no, 1=yes */
55   0,    /* posix_sync_io: file can be sync'ed, 0=no, 1=yes */
56   0     /* posix_vdisable: special char processing, 0=no, 1=yes */
57};
58
59static bool is_node_fs_root(
60  const rtems_filesystem_mount_table_entry_t *mt_entry,
61  void *arg
62)
63{
64  return arg == mt_entry->mt_fs_root.node_access;
65}
66
67static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
68  const char *source_or_null,
69  const char *target_or_null,
70  const char *filesystemtype,
71  size_t *target_length_ptr
72)
73{
74  const char *target = target_or_null != NULL ? target_or_null : "/";
75  size_t filesystemtype_size = strlen( filesystemtype ) + 1;
76  size_t source_size = source_or_null != NULL ?
77    strlen( source_or_null ) + 1 : 0;
78  size_t target_length = strlen( target );
79  size_t size = sizeof( rtems_filesystem_mount_table_entry_t )
80    + filesystemtype_size + source_size + target_length + 1;
81  rtems_filesystem_mount_table_entry_t *mt_entry = calloc( 1, size );
82
83  if ( mt_entry != NULL ) {
84    char *str = (char *) mt_entry + sizeof( *mt_entry );
85
86    strcpy( str, filesystemtype );
87    mt_entry->type = str;
88    str += filesystemtype_size;
89
90    if ( source_or_null != NULL ) {
91      strcpy( str, source_or_null );
92      mt_entry->dev = str;
93      str += source_size;
94    }
95
96    strcpy( str, target );
97    mt_entry->target = str;
98  }
99
100  *target_length_ptr = target_length;
101
102  return mt_entry;
103}
104
105/*
106 *  mount
107 *
108 *  This routine will attempt to mount a new file system at the specified
109 *  mount point. A series of tests will be run to determine if any of the
110 *  following reasons exist to prevent the mount operation:
111 *
112 *      1) The file system type or options are not valid
113 *      2) No new file system root node is specified
114 *      3) The selected file system has already been mounted
115 *      4) The mount point exists with the proper permissions to allow mounting
116 *      5) The selected mount point already has a file system mounted to it
117 *
118 */
119
120int mount(
121  const char                 *source,
122  const char                 *target,
123  const char                 *filesystemtype,
124  rtems_filesystem_options_t options,
125  const void                 *data
126)
127{
128  rtems_filesystem_fsmount_me_t mount_h = NULL;
129  rtems_filesystem_location_info_t      loc;
130  rtems_filesystem_mount_table_entry_t *mt_entry = NULL;
131  rtems_filesystem_location_info_t     *loc_to_free = NULL;
132  bool has_target = target != NULL;
133  size_t target_length = 0;
134
135  /*
136   *  Are the file system options valid?
137   */
138
139  if ( options != RTEMS_FILESYSTEM_READ_ONLY &&
140       options != RTEMS_FILESYSTEM_READ_WRITE )
141    rtems_set_errno_and_return_minus_one( EINVAL );
142
143  /*
144   *  Get mount handler
145   */
146  mount_h = rtems_filesystem_get_mount_handler( filesystemtype );
147  if ( !mount_h )
148    rtems_set_errno_and_return_minus_one( EINVAL );
149
150  /*
151   * Allocate a mount table entry
152   */
153  mt_entry = alloc_mount_table_entry(
154    source,
155    target,
156    filesystemtype,
157    &target_length
158  );
159  if ( !mt_entry )
160    rtems_set_errno_and_return_minus_one( ENOMEM );
161
162  mt_entry->mt_fs_root.mt_entry = mt_entry;
163  mt_entry->options = options;
164  mt_entry->pathconf_limits_and_options = rtems_filesystem_default_pathconf;
165
166  /*
167   *  The mount_point should be a directory with read/write/execute
168   *  permissions in the existing tree.
169   */
170
171  if ( has_target ) {
172    if ( rtems_filesystem_evaluate_path(
173           target, target_length, RTEMS_LIBIO_PERMS_RWX, &loc, true ) == -1 )
174      goto cleanup_and_bail;
175
176    loc_to_free = &loc;
177
178    /*
179     * Test for node_type_h
180     */
181
182    if (!loc.ops->node_type_h) {
183      errno =  ENOTSUP;
184      goto cleanup_and_bail;
185    }
186
187    /*
188     *  Test to see if it is a directory
189     */
190
191    if ( loc.ops->node_type_h( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
192      errno = ENOTDIR;
193      goto cleanup_and_bail;
194    }
195
196    /*
197     *  You can only mount one file system onto a single mount point.
198     */
199
200    if ( rtems_filesystem_mount_iterate( is_node_fs_root, loc.node_access ) ) {
201      errno = EBUSY;
202      goto cleanup_and_bail;
203    }
204
205    /*
206     *  This must be a good mount point, so move the location information
207     *  into the allocated mount entry.  Note:  the information that
208     *  may have been allocated in loc should not be sent to freenode
209     *  until the system is unmounted.  It may be needed to correctly
210     *  traverse the tree.
211     */
212
213    mt_entry->mt_point_node.node_access = loc.node_access;
214    mt_entry->mt_point_node.handlers = loc.handlers;
215    mt_entry->mt_point_node.ops = loc.ops;
216    mt_entry->mt_point_node.mt_entry = loc.mt_entry;
217
218    /*
219     *  This link to the parent is only done when we are dealing with system
220     *  below the base file system
221     */
222
223    if ( !loc.ops->mount_h ){
224      errno = ENOTSUP;
225      goto cleanup_and_bail;
226    }
227
228    if ( loc.ops->mount_h( mt_entry ) ) {
229      goto cleanup_and_bail;
230    }
231  } else {
232    /*
233     * Do we already have a base file system ?
234     */
235    if ( !rtems_chain_is_empty( &mount_chain ) ) {
236      errno = EINVAL;
237      goto cleanup_and_bail;
238    }
239
240    /*
241     *  This is a mount of the base file system --> The
242     *  mt_point_node.node_access will be left to null to indicate that this
243     *  is the root of the entire file system.
244     */
245  }
246
247  if ( (*mount_h)( mt_entry, data ) ) {
248    /*
249     * Try to undo the mount operation
250     */
251    if ( loc.ops->unmount_h ) {
252      loc.ops->unmount_h( mt_entry );
253    }
254    goto cleanup_and_bail;
255  }
256
257  /*
258   *  Add the mount table entry to the mount table chain
259   */
260  rtems_libio_lock();
261  rtems_chain_append( &mount_chain, &mt_entry->Node );
262  rtems_libio_unlock();
263
264  if ( !has_target )
265    rtems_filesystem_root = mt_entry->mt_fs_root;
266
267  return 0;
268
269cleanup_and_bail:
270
271  free( mt_entry );
272
273  if ( loc_to_free )
274    rtems_filesystem_freenode( loc_to_free );
275
276  return -1;
277}
278
279bool rtems_filesystem_mount_iterate(
280  rtems_per_filesystem_mount_routine routine,
281  void *routine_arg
282)
283{
284  rtems_chain_node *node = NULL;
285  bool stop = false;
286
287  rtems_libio_lock();
288  for (
289    node = rtems_chain_first( &mount_chain );
290    !rtems_chain_is_tail( &mount_chain, node ) && !stop;
291    node = rtems_chain_next( node )
292  ) {
293    const rtems_filesystem_mount_table_entry_t *mt_entry =
294      (rtems_filesystem_mount_table_entry_t *) node;
295
296    stop = (*routine)( mt_entry, routine_arg );
297  }
298  rtems_libio_unlock();
299
300  return stop;
301}
Note: See TracBrowser for help on using the repository browser.