source: rtems/cpukit/libfs/src/dosfs/msdos_eval.c @ f36a7bfc

4.104.114.84.95
Last change on this file since f36a7bfc was f36a7bfc, checked in by Joel Sherrill <joel.sherrill@…>, on 02/28/02 at 20:43:50

2002-02-28 Victor V. Vengerov <vvv@…>

  • DOS filesystem including FAT12, FAT16, and FAT32 support submitted.
  • src/dosfs, src/dosfs/Makefile.am, src/dosfs/stamp-h2.in, src/dosfs/config.h.in, src/dosfs/dosfs.h, src/dosfs/fat.c, src/dosfs/fat.h, src/dosfs/fat_fat_operations.c, src/dosfs/fat_fat_operations.h, src/dosfs/fat_file.c, src/dosfs/fat_file.h, src/dosfs/msdos.h, src/dosfs/msdos_create.c, src/dosfs/msdos_dir.c, src/dosfs/msdos_eval.c, src/dosfs/msdos_file.c, src/dosfs/msdos_free.c, src/dosfs/msdos_fsunmount.c, src/dosfs/msdos_handlers_dir.c, src/dosfs/msdos_handlers_file.c, src/dosfs/msdos_init.c, src/dosfs/msdos_initsupp.c, src/dosfs/msdos_misc.c, src/dosfs/msdos_mknod.c, src/dosfs/msdos_node_type.c, src/dosfs/.cvsignore: New files.
  • configure.ac, src/Makefile.am, wrapup/Makefile.am: Modified to reflect addition.
  • Property mode set to 100644
File size: 12.6 KB
Line 
1/*
2 *  MSDOS evaluation routines
3 *
4 *  Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
5 *  Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.OARcorp.com/rtems/license.html.
10 *
11 *  @(#) $Id$
12 */
13
14#if HAVE_CONFIG_H
15#include "config.h"
16#endif
17
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <fcntl.h>
21#include <unistd.h>
22#include <errno.h>
23#include <stdlib.h>
24#include <assert.h>
25
26#include <rtems/libio_.h>
27
28#include "fat.h"
29#include "fat_fat_operations.h"
30#include "fat_file.h"
31
32#include "msdos.h"
33
34/* msdos_set_handlers --
35 *     Set handlers for the node with specified type(i.e. handlers for file
36 *     or directory).
37 *
38 * PARAMETERS:
39 *     loc - node description
40 *
41 * RETURNS:
42 *     None
43 */
44static void
45msdos_set_handlers(rtems_filesystem_location_info_t *loc)
46{
47    msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
48    fat_file_fd_t   *fat_fd = loc->node_access;
49
50    if (fat_fd->fat_file_type == FAT_DIRECTORY)
51        loc->handlers = fs_info->directory_handlers;
52    else
53        loc->handlers = fs_info->file_handlers;
54}
55
56/* msdos_eval_path --
57 *
58 *     The following routine evaluate path for a node that wishes to be
59 *     accessed.  Structure 'pathloc' is returned with a pointer to the
60 *     node to be accessed.
61 *
62 * PARAMETERS:
63 *     pathname - path for evaluation
64 *     flags    - flags
65 *     pathloc  - node description (IN/OUT)
66 *
67 * RETURNS:
68 *     RC_OK and filled pathloc on success, or -1 if error occured
69 *     (errno set appropriately)
70 *       
71 */
72int
73msdos_eval_path(
74    const char                        *pathname,
75    int                                flags,
76    rtems_filesystem_location_info_t  *pathloc
77    )
78{
79    int                               rc = RC_OK;
80    rtems_status_code                 sc = RTEMS_SUCCESSFUL;
81    msdos_fs_info_t                  *fs_info = pathloc->mt_entry->fs_info;
82    fat_file_fd_t                    *fat_fd = NULL;
83    rtems_filesystem_location_info_t  newloc;
84    int                               i = 0;
85    int                               len = 0;
86    msdos_token_types_t               type = MSDOS_CURRENT_DIR;
87    char                              token[MSDOS_NAME_MAX + 1];
88
89    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
90                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
91    if (sc != RTEMS_SUCCESSFUL)
92        set_errno_and_return_minus_one(EIO);
93 
94    if (!pathloc->node_access)
95    {
96        errno = ENOENT;
97        rc = -1;
98        goto err;
99    } 
100
101    fat_fd = pathloc->node_access;
102
103    rc = fat_file_reopen(fat_fd);
104    if (rc != RC_OK)
105        goto err;
106   
107    while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
108    {
109        type = msdos_get_token(&pathname[i], token, &len);
110        i += len;
111 
112        fat_fd = pathloc->node_access;
113 
114        switch (type)
115        {
116            case MSDOS_UP_DIR:
117                /*
118                 *  Only a directory can be decended into.
119                 */
120                if (fat_fd->fat_file_type != FAT_DIRECTORY)
121                {
122                    errno = ENOTDIR;
123                    rc = -1;
124                    goto error;
125                } 
126
127                /*
128                 *  Am I at the root of this mounted filesystem?
129                 */
130                if (pathloc->node_access ==
131                    pathloc->mt_entry->mt_fs_root.node_access)
132                {
133                    /*
134                     *  Am I at the root of all filesystems?
135                     *  XXX: MSDOS is not supposed to be base fs.
136                     */
137                    if (pathloc->node_access ==
138                        rtems_filesystem_root.node_access)
139                    {   
140                        break;       /* Throw out the .. in this case */
141                    }     
142                    else
143                    {
144                        newloc = pathloc->mt_entry->mt_point_node;
145                        *pathloc = newloc;
146
147                        rc = fat_file_close(pathloc->mt_entry, fat_fd);
148                        if (rc != RC_OK)
149                            goto err;
150                           
151                        rtems_semaphore_release(fs_info->vol_sema);
152                        return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
153                                                           flags, pathloc);
154                    }
155                }
156                else
157                {
158                    rc = msdos_find_name(pathloc, token);
159                    if (rc != RC_OK)
160                    {
161                        if (rc == MSDOS_NAME_NOT_FOUND_ERR)
162                        {
163                            errno = ENOENT;
164                            rc = -1;
165                        }   
166                        goto error;
167                    } 
168                }
169                break;
170
171            case MSDOS_NAME:
172                /*
173                 *  Only a directory can be decended into.
174                 */
175                if (fat_fd->fat_file_type != FAT_DIRECTORY)
176                {
177                    errno = ENOTDIR;
178                    rc = -1;
179                    goto error;
180                } 
181
182                /*
183                 *  Otherwise find the token name in the present location and
184                 * set the node access to the point we have found.
185                 */
186                rc = msdos_find_name(pathloc, token);
187                if (rc != RC_OK)
188                {
189                    if (rc == MSDOS_NAME_NOT_FOUND_ERR)
190                    {
191                        errno = ENOENT;
192                        rc = -1;
193                    }   
194                    goto error;
195                } 
196                break;
197
198            case MSDOS_NO_MORE_PATH:
199            case MSDOS_CURRENT_DIR:       
200                break;
201
202            case MSDOS_INVALID_TOKEN:
203                errno = ENAMETOOLONG;
204                rc = -1;
205                goto error;
206                break;
207 
208        }
209    }
210
211    /*
212     *  Always return the root node.
213     *
214     *  If we are at a node that is a mount point. Set loc to the
215     *  new fs root node and let let the mounted filesystem set the handlers.
216     *
217     *  NOTE: The behavior of stat() on a mount point appears to be
218     *        questionable.
219     *  NOTE: MSDOS filesystem currently doesn't support mount functionality ->
220     *        action not implemented
221     */
222    fat_fd = pathloc->node_access;
223   
224    msdos_set_handlers(pathloc);
225   
226    rtems_semaphore_release(fs_info->vol_sema);
227    return RC_OK;
228
229error:
230    fat_file_close(pathloc->mt_entry, fat_fd);
231
232err:
233    rtems_semaphore_release(fs_info->vol_sema);
234    return rc;
235}
236
237/* msdos_eval4make --
238 *     The following routine evaluate path for a new node to be created.
239 *     'pathloc' is returned with a pointer to the parent of the new node.
240 *     'name' is returned with a pointer to the first character in the
241 *     new node name.  The parent node is verified to be a directory.
242 *
243 * PARAMETERS:
244 *     path    - path for evaluation
245 *     pathloc - IN/OUT (start point for evaluation/parent directory for
246 *               creation)
247 *     name    - new node name
248 *
249 * RETURNS:
250 *     RC_OK, filled pathloc for parent directory and name of new node on
251 *     success, or -1 if error occured (errno set appropriately)
252 */
253int
254msdos_eval4make(
255    const char                         *path,
256    rtems_filesystem_location_info_t   *pathloc, 
257    const char                        **name
258    )   
259{
260    int                               rc = RC_OK;
261    rtems_status_code                 sc = RTEMS_SUCCESSFUL;
262    msdos_fs_info_t                  *fs_info = pathloc->mt_entry->fs_info;
263    fat_file_fd_t                    *fat_fd = NULL;
264    rtems_filesystem_location_info_t  newloc;
265    msdos_token_types_t               type;
266    int                               i = 0;
267    int                               len;
268    char                              token[ MSDOS_NAME_MAX + 1 ];
269    rtems_boolean                     done = 0;
270
271    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
272                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
273    if (sc != RTEMS_SUCCESSFUL)
274        set_errno_and_return_minus_one(EIO);
275 
276    if (!pathloc->node_access)
277    {
278        errno = ENOENT;
279        rc = -1;
280        goto err;
281    } 
282
283    fat_fd = pathloc->node_access;
284
285    rc = fat_file_reopen(fat_fd);
286    if (rc != RC_OK)
287        goto err;
288
289    while (!done)
290    {
291        type = msdos_get_token(&path[i], token, &len);
292        i += len;
293        fat_fd = pathloc->node_access;
294
295        switch (type)
296        {
297            case MSDOS_UP_DIR:
298                /*
299                 *  Only a directory can be decended into.
300                 */
301                if (fat_fd->fat_file_type != FAT_DIRECTORY)
302                {
303                    errno = ENOTDIR;
304                    rc = -1;
305                    goto error;
306                } 
307
308                /*
309                 *  Am I at the root of this mounted filesystem?
310                 */
311                if (pathloc->node_access ==
312                    pathloc->mt_entry->mt_fs_root.node_access)
313                {
314                    /*
315                     *  Am I at the root of all filesystems?
316                     *  XXX: MSDOS is not supposed to be base fs.
317                     */
318                    if (pathloc->node_access ==
319                        rtems_filesystem_root.node_access)
320                    {   
321                        break;       /* Throw out the .. in this case */
322                    }   
323                    else
324                    {
325                        newloc = pathloc->mt_entry->mt_point_node;
326                        *pathloc = newloc;
327
328                        rc = fat_file_close(pathloc->mt_entry, fat_fd);
329                        if (rc != RC_OK)
330                            goto err;
331
332                        rtems_semaphore_release(fs_info->vol_sema);
333                        return (*pathloc->ops->evalformake_h)(&path[i-len],
334                                                              pathloc, name);
335                    }
336                }
337                else
338                {
339                    rc = msdos_find_name(pathloc, token);
340                    if (rc != RC_OK)
341                    {
342                        if (rc == MSDOS_NAME_NOT_FOUND_ERR)
343                        {
344                            errno = ENOENT;
345                            rc = -1;
346                        }   
347                        goto error;
348                    } 
349                }
350                break;
351
352            case MSDOS_NAME:
353                /*
354                 *  Only a directory can be decended into.
355                 */
356                if (fat_fd->fat_file_type != FAT_DIRECTORY)
357                {
358                    errno = ENOTDIR;
359                    rc = -1;
360                    goto error;
361                } 
362
363                /*
364                 *  Otherwise find the token name in the present location and
365                 * set the node access to the point we have found.
366                 */
367                rc = msdos_find_name(pathloc, token);
368                if (rc)
369                {
370                    if (rc != MSDOS_NAME_NOT_FOUND_ERR)
371                    {
372                        errno = ENOENT;
373                        rc = -1;
374                        goto error;
375                    }
376                    else
377                        done = TRUE;
378                }     
379                break;
380
381            case MSDOS_NO_MORE_PATH:
382                errno = EEXIST;
383                rc = -1;
384                goto error;
385                break;
386       
387            case MSDOS_CURRENT_DIR:
388                break;
389
390            case MSDOS_INVALID_TOKEN:
391                errno = ENAMETOOLONG;
392                rc = -1;
393                goto error;
394                break;
395
396        }
397    }
398
399    *name = &path[i - len];
400
401    /*
402     * We have evaluated the path as far as we can.
403     * Verify there is not any invalid stuff at the end of the name.
404     */
405    for( ; path[i] != '\0'; i++)
406    {
407        if (!msdos_is_separator(path[i]))
408        {
409            errno = ENOENT;
410            rc = -1;
411            goto error;
412        } 
413    }
414
415    fat_fd = pathloc->node_access;
416
417    if (fat_fd->fat_file_type != FAT_DIRECTORY)
418    {
419        errno = ENOTDIR;
420        rc = -1;
421        goto error;
422    } 
423   
424    msdos_set_handlers(pathloc);
425 
426    rtems_semaphore_release(fs_info->vol_sema);
427    return RC_OK;
428
429error:
430    fat_file_close(pathloc->mt_entry, fat_fd);
431
432err:
433    rtems_semaphore_release(fs_info->vol_sema);
434    return rc;
435}
Note: See TracBrowser for help on using the repository browser.