source: rtems/cpukit/libcsupport/src/mount.c @ 4b533522

4.104.114.84.95
Last change on this file since 4b533522 was 4b533522, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 11, 2002 at 9:36:19 PM

2002-11-07 <strauman@…>

  • src/mount.c: Per PR297, correct fs_mountme failure paths.
  • Property mode set to 100644
File size: 6.8 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 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.OARcorp.com/rtems/license.html.
16 *
17 *  $Id$
18 */
19
20#if HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <chain.h>
27#include <fcntl.h>
28#include <unistd.h>
29#include <errno.h>
30#include <stdlib.h>
31#include <string.h>
32#include <assert.h>
33
34#include <rtems/libio_.h>
35
36Chain_Control rtems_filesystem_mount_table_control;
37
38/*
39 *  Prototypes that probably should be somewhere else.
40 */
41
42int init_fs_mount_table( void );
43static int Is_node_fs_root(
44  rtems_filesystem_location_info_t  *loc
45);
46
47
48/*
49 *  XXX
50 */
51
52#define FOUND      0
53#define NOT_FOUND -1
54
55/*
56 *  mount
57 *
58 *  This routine will attempt to mount a new file system at the specified
59 *  mount point. A series of tests will be run to determine if any of the
60 *  following reasons exist to prevent the mount operation:
61 *
62 *      1) The file system type or options are not valid
63 *      2) No new file system root node is specified
64 *      3) The selected file system has already been mounted
65 *      4) The mount point exists with the proper permissions to allow mounting
66 *      5) The selected mount point already has a file system mounted to it
67 *
68 */
69
70int mount(
71  rtems_filesystem_mount_table_entry_t **mt_entry,
72  rtems_filesystem_operations_table    *fs_ops,
73  rtems_filesystem_options_t            options,
74  char                                 *device,
75  char                                 *mount_point
76)
77{
78  rtems_filesystem_location_info_t      loc;
79  rtems_filesystem_mount_table_entry_t *temp_mt_entry = NULL;
80  rtems_filesystem_location_info_t     *loc_to_free = NULL;
81  size_t size;
82
83/* XXX add code to check for required operations */
84
85  /*
86   *  Is there a file system operations table?
87   */
88
89  if ( fs_ops == NULL ) {
90    errno = EINVAL;
91    return -1;
92  }
93
94  /*
95   *  Are the file system options valid?
96   */
97
98  if ( options != RTEMS_FILESYSTEM_READ_ONLY && 
99       options != RTEMS_FILESYSTEM_READ_WRITE ) {
100    errno = EINVAL;
101    return -1;
102  }
103
104  /* Do they support being mounted at all ? */
105  if ( !fs_ops->fsmount_me_h ) {
106    errno = ENOTSUP;
107    goto cleanup_and_bail;
108  }
109
110
111  /*
112   * Allocate a mount table entry
113   */
114
115   size = sizeof(rtems_filesystem_mount_table_entry_t);
116   if ( device )
117     size += strlen( device ) + 1;
118   temp_mt_entry = malloc( size );
119
120   if ( !temp_mt_entry ) {
121     errno = ENOMEM;
122     return -1;
123   }
124
125   temp_mt_entry->mt_fs_root.mt_entry = temp_mt_entry;
126   temp_mt_entry->options = options;
127   if ( device ) {
128     temp_mt_entry->dev =
129       (char *)temp_mt_entry + sizeof( rtems_filesystem_mount_table_entry_t );
130     strcpy( temp_mt_entry->dev, device );
131   } else
132     temp_mt_entry->dev = 0;
133
134  /*
135   *  The mount_point should be a directory with read/write/execute
136   *  permissions in the existing tree.
137   */
138
139  if ( mount_point ) {
140
141    if ( rtems_filesystem_evaluate_path( 
142            mount_point, RTEMS_LIBIO_PERMS_RWX, &loc, TRUE ) == -1 )
143      goto cleanup_and_bail;
144
145    /*
146     * Test for node_type_h
147     */
148
149    if (!loc.ops->node_type_h) {
150      errno =  ENOTSUP;
151      goto cleanup_and_bail;
152    }
153
154    /*
155     *  Test to see if it is a directory
156     */
157
158    loc_to_free = &loc;
159    if ( loc.ops->node_type_h( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
160      errno = ENOTDIR; 
161      goto cleanup_and_bail;
162    }
163
164    /*
165     *  You can only mount one file system onto a single mount point.
166     */
167
168    if ( Is_node_fs_root(  &loc ) ){
169      errno = EBUSY;
170      goto cleanup_and_bail;
171    }
172 
173    /*
174     *  This must be a good mount point, so move the location information
175     *  into the allocated mount entry.  Note:  the information that
176     *  may have been allocated in loc should not be sent to freenode
177     *  until the system is unmounted.  It may be needed to correctly
178     *  traverse the tree.
179     */
180
181    temp_mt_entry->mt_point_node.node_access = loc.node_access;
182    temp_mt_entry->mt_point_node.handlers = loc.handlers;
183    temp_mt_entry->mt_point_node.ops = loc.ops;
184    temp_mt_entry->mt_point_node.mt_entry = loc.mt_entry;
185
186    /*
187     *  This link to the parent is only done when we are dealing with system
188     *  below the base file system
189     */
190
191    if ( !loc.ops->mount_h ){
192      errno = ENOTSUP;
193      goto cleanup_and_bail;
194    }
195
196    if ( loc.ops->mount_h( temp_mt_entry ) ) {
197      goto cleanup_and_bail;
198    }
199  } else {
200
201    /*
202     *  This is a mount of the base file system --> The
203     *  mt_point_node.node_access will be set to null to indicate that this
204     *  is the root of the entire file system.
205     */
206
207    temp_mt_entry->mt_fs_root.node_access = NULL;
208    temp_mt_entry->mt_fs_root.handlers = NULL;
209    temp_mt_entry->mt_fs_root.ops = NULL;
210
211    temp_mt_entry->mt_point_node.node_access = NULL;
212    temp_mt_entry->mt_point_node.handlers = NULL;
213    temp_mt_entry->mt_point_node.ops = NULL;
214    temp_mt_entry->mt_point_node.mt_entry = NULL;
215  }
216
217  if ( fs_ops->fsmount_me_h( temp_mt_entry ) ) {
218        /* try to undo the mount operation */
219        if ( loc.ops->unmount_h ) {
220                loc.ops->unmount_h( temp_mt_entry );
221    }
222    goto cleanup_and_bail;
223  }
224
225  /*
226   *  Add the mount table entry to the mount table chain
227   */
228
229  Chain_Append( &rtems_filesystem_mount_table_control, &temp_mt_entry->Node );
230
231  *mt_entry = temp_mt_entry;
232
233  return 0;
234
235cleanup_and_bail:
236
237  free( temp_mt_entry );
238 
239  if ( loc_to_free )
240    rtems_filesystem_freenode( loc_to_free );
241
242  return -1;
243}
244
245
246
247/*
248 *  init_fs_mount_table
249 *
250 *  This routine will initialize the chain control element that manages the
251 *  mount table chain.
252 */
253
254int init_fs_mount_table()
255{
256  Chain_Initialize_empty ( &rtems_filesystem_mount_table_control );
257  return 0;
258}
259
260/*
261 *  Is_node_fs_root
262 *
263 *  This routine will run through the entries that currently exist in the
264 *  mount table chain. For each entry in the mount table chain it will
265 *  compare the mount tables root node to the node describing the selected
266 *  mount point. If any match is found true is returned else false is
267 *  returned.
268 *
269 */
270
271static int Is_node_fs_root(
272  rtems_filesystem_location_info_t  *loc
273)
274{
275  Chain_Node                           *the_node;
276  rtems_filesystem_mount_table_entry_t *the_mount_entry;
277
278  /*
279   * For each mount table entry
280   */
281
282  for ( the_node = rtems_filesystem_mount_table_control.first;
283        !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
284        the_node = the_node->next ) {
285     the_mount_entry = (rtems_filesystem_mount_table_entry_t *) the_node;
286     if ( the_mount_entry->mt_fs_root.node_access  == loc->node_access )
287        return TRUE;
288  }
289  return FALSE;
290}
Note: See TracBrowser for help on using the repository browser.