source: rtems/cpukit/libfs/src/dosfs/msdos_dir.c @ 8ec7abb

4.104.115
Last change on this file since 8ec7abb was 8ec7abb, checked in by Chris Johns <chrisj@…>, on 03/04/10 at 06:36:51

010-03-04 Chris Johns <chrisj@…>

  • libcsupport/include/rtems/libio.h, libcsupport/src/_rename_r.c: Add a rename file op and have rename use it.
  • libfs/Makefile.am, libfs/src/dosfs/msdos_rename.c, libfs/src/imfs/imfs_rename.c: New files to support the rename file op.
  • libfs/src/imfs/imfs.h: Add rename interface.
  • libfs/src/imfs/imfs_init.c: Add rename handler.
  • libfs/src/imfs/miniimfs_init.c: Fix up ops struct.
  • libfs/src/dosfs/msdos.h: Add msdos_rename and remove msdos_file_link.
  • libfs/src/dosfs/msdos_create.c: Remove the link call.
  • libfs/src/dosfs/msdos_eval.c: Fix a path parsing bug.
  • libfs/src/dosfs/msdos_init.c: Add rename handler and clean up the struct naming.
  • libfs/src/rfs/rtems-rfs-link.c, libfs/src/rfs/rtems-rfs-link.h: Change the link call to allow linking of directories if told to and change the unlink to handle unlink directories that are not empty so rename can be supported.
  • libfs/src/rfs/rtems-rfs-rtems-dir.c: Fix the link/unlink calls.
  • libfs/src/rfs/rtems-rfs-rtems.c: Add a rename handler. Fix the link/unlink calls.
  • libfs/src/dosfs/msdos_dir.c, libfs/src/dosfs/msdos_format.c, libfs/src/dosfs/msdos_misc.c, httpd/asp.c, libfs/src/nfsclient/src/nfs.c: Work around a newlib warning when using the is*() family of calls.
  • Property mode set to 100644
File size: 21.9 KB
Line 
1/*
2 *  MSDOS directory handlers implementation
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.rtems.com/license/LICENSE.
10 *
11 *  @(#) $Id$
12 */
13#if HAVE_CONFIG_H
14#include "config.h"
15#endif
16
17#include <ctype.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <assert.h>
21#include <errno.h>
22#include <rtems/libio_.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25
26#include <dirent.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_dir_open --
35 *     Open fat-file which correspondes to the directory being opened and
36 *     set offset field of file control block to zero.
37 *
38 * PARAMETERS:
39 *     iop        - file control block
40 *     pathname   - name
41 *     flag       - flags
42 *     mode       - mode
43 *
44 * RETURNS:
45 *     RC_OK, if directory opened successfully, or -1 if error occured (errno
46 *     set apropriately)
47 */
48int
49msdos_dir_open(rtems_libio_t *iop, const char *pathname, uint32_t   flag,
50               uint32_t   mode)
51{
52    int                rc = RC_OK;
53    rtems_status_code  sc = RTEMS_SUCCESSFUL;
54    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
55    fat_file_fd_t     *fat_fd = iop->file_info;
56
57    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
58                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
59    if (sc != RTEMS_SUCCESSFUL)
60        rtems_set_errno_and_return_minus_one( EIO );
61
62    rc = fat_file_reopen(fat_fd);
63    if (rc != RC_OK)
64    {
65        rtems_semaphore_release(fs_info->vol_sema);
66        return rc;
67    }
68
69    iop->offset = 0;
70    rtems_semaphore_release(fs_info->vol_sema);
71    return RC_OK;
72}
73
74/* msdos_dir_close --
75 *     Close  fat-file which correspondes to the directory being closed
76 *
77 * PARAMETERS:
78 *     iop - file control block
79 *
80 * RETURNS:
81 *     RC_OK, if directory closed successfully, or -1 if error occured (errno
82 *     set apropriately.
83 */
84int
85msdos_dir_close(rtems_libio_t *iop)
86{
87    int                rc = RC_OK;
88    rtems_status_code  sc = RTEMS_SUCCESSFUL;
89    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
90    fat_file_fd_t     *fat_fd = iop->file_info;
91
92    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
93                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
94    if (sc != RTEMS_SUCCESSFUL)
95        rtems_set_errno_and_return_minus_one( EIO );
96
97    rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
98    if (rc != RC_OK)
99    {
100        rtems_semaphore_release(fs_info->vol_sema);
101        return rc;
102    }
103
104    rtems_semaphore_release(fs_info->vol_sema);
105    return RC_OK;
106}
107
108/*  msdos_format_dirent_with_dot --
109 *      This routine convert a (short) MSDOS filename as present on disk
110 *      (fixed 8+3 characters, filled with blanks, without separator dot)
111 *      to a "normal" format, with between 0 and 8 name chars,
112 *      a separating dot and up to 3 extension characters
113 *   Rules to work:
114 *      - copy any (0-8) "name" part characters that are non-blank
115 *      - if an extension exists, append a dot
116 *      - copy any (0-3) non-blank extension characters
117 *      - append a '\0' (dont count it for the rturn code
118 *
119 * PARAMETERS:
120 *     dst: pointer to destination char array (must be big enough)
121 *     src: pointer to source characters
122 *
123 *
124 * RETURNS:
125 *     the number of bytes (without trailing '\0'(written to destination
126 */
127static ssize_t
128msdos_format_dirent_with_dot(char *dst,const char *src)
129{
130  ssize_t len;
131  int i;
132  const char *src_tmp;
133
134  /*
135   * find last non-blank character of base name
136   */
137  for ((i       =       MSDOS_SHORT_BASE_LEN  ,
138        src_tmp = src + MSDOS_SHORT_BASE_LEN-1);
139       ((i > 0) &&
140        (*src_tmp == ' '));
141       i--,src_tmp--)
142    {};
143  /*
144   * copy base name to destination
145   */
146  src_tmp = src;
147  len = i;
148  while (i-- > 0) {
149    *dst++ = tolower((int)(*src_tmp++));
150  }
151  /*
152   * find last non-blank character of extension
153   */
154  for ((i       =                            MSDOS_SHORT_EXT_LEN  ,
155        src_tmp = src + MSDOS_SHORT_BASE_LEN+MSDOS_SHORT_EXT_LEN-1);
156       ((i > 0) &&
157        (*src_tmp == ' '));
158       i--,src_tmp--)
159    {};
160  /*
161   * extension is not empty
162   */
163  if (i > 0) {
164    *dst++ = '.'; /* append dot */
165    len += i + 1; /* extension + dot */
166    src_tmp = src + MSDOS_SHORT_BASE_LEN;
167    while (i-- > 0) {
168      *dst++ = tolower((int)(*src_tmp++));
169      len++;
170    }
171  }
172  *dst = '\0'; /* terminate string */
173
174  return len;
175}
176
177/*  msdos_dir_read --
178 *      This routine will read the next directory entry based on the directory
179 *      offset. The offset should be equal to -n- time the size of an
180 *      individual dirent structure. If n is not an integer multiple of the
181 *      sizeof a dirent structure, an integer division will be performed to
182 *      determine directory entry that will be returned in the buffer. Count
183 *      should reflect -m- times the sizeof dirent bytes to be placed in the
184 *      buffer.
185 *      If there are not -m- dirent elements from the current directory
186 *      position to the end of the exisiting file, the remaining entries will
187 *      be placed in the buffer and the returned value will be equal to
188 *      -m actual- times the size of a directory entry.
189 *
190 * PARAMETERS:
191 *     iop    - file control block
192 *     buffer - buffer provided by user
193 *     count  - count of bytes to read
194 *
195 * RETURNS:
196 *     the number of bytes read on success, or -1 if error occured (errno
197 *     set apropriately).
198 */
199ssize_t
200msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
201{
202    int                rc = RC_OK;
203    rtems_status_code  sc = RTEMS_SUCCESSFUL;
204    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
205    fat_file_fd_t     *fat_fd = iop->file_info;
206    fat_file_fd_t     *tmp_fat_fd = NULL;
207    struct dirent      tmp_dirent;
208    uint32_t           start = 0;
209    ssize_t            ret = 0;
210    uint32_t           cmpltd = 0;
211    uint32_t           j = 0, i = 0;
212    uint32_t           bts2rd = 0;
213    uint32_t           cur_cln = 0;
214    uint32_t           lfn_start = FAT_FILE_SHORT_NAME;
215    uint8_t            lfn_checksum = 0;
216    int                lfn_entries = 0;
217
218    /*
219     * cast start and count - protect against using sizes that are not exact
220     * multiples of the -dirent- size. These could result in unexpected
221     * results
222     */
223    start = iop->offset / sizeof(struct dirent);
224    count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
225
226    /*
227     * optimization: we know that root directory for FAT12/16 volumes is
228     * sequential set of sectors and any cluster is sequential set of sectors
229     * too, so read such set of sectors is quick operation for low-level IO
230     * layer.
231     */
232    bts2rd = (FAT_FD_OF_ROOT_DIR(fat_fd) &&
233             (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) ?
234             fat_fd->fat_file_size                              :
235             fs_info->fat.vol.bpc;
236
237    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
238                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
239    if (sc != RTEMS_SUCCESSFUL)
240        rtems_set_errno_and_return_minus_one(EIO);
241
242    while (count > 0)
243    {
244        /*
245         * fat-file is already opened by open call, so read it
246         * Always read directory fat-file from the beggining because of MSDOS
247         * directories feature :( - we should count elements currently
248         * present in the directory because there may be holes :)
249         */
250        ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, (j * bts2rd),
251                            bts2rd, fs_info->cl_buf);
252        if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
253        {
254            rtems_semaphore_release(fs_info->vol_sema);
255            rtems_set_errno_and_return_minus_one(EIO);
256        }
257
258        for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
259        {
260            char* entry = (char*) fs_info->cl_buf + i;
261
262            /*
263             * Is this directory from here on empty ?
264             */
265            if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
266                MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
267            {
268                rtems_semaphore_release(fs_info->vol_sema);
269                return cmpltd;
270            }
271
272            /* Is the directory entry empty */
273            if ((*MSDOS_DIR_ENTRY_TYPE(entry)) == MSDOS_THIS_DIR_ENTRY_EMPTY)
274                continue;
275
276            /* Is the directory entry empty a volume label */
277            if (((*MSDOS_DIR_ATTR(entry)) & MSDOS_ATTR_VOLUME_ID) &&
278                ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) != MSDOS_ATTR_LFN))
279                continue;
280
281            /*
282             * Check the attribute to see if the entry is for a long file
283             * name.
284             */
285            if ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
286                MSDOS_ATTR_LFN)
287            {
288                int   o;
289                char* p;
290                int   q;
291
292                /*
293                 * Is this is the first entry of a LFN ?
294                 */
295                if (lfn_start == FAT_FILE_SHORT_NAME)
296                {
297                    /*
298                     * The first entry must have the last long entry flag set.
299                     */
300                    if ((*MSDOS_DIR_ENTRY_TYPE(entry) &
301                         MSDOS_LAST_LONG_ENTRY) == 0)
302                        continue;
303
304                    /*
305                     * Remember the start location of the long file name.
306                     */
307                    lfn_start =
308                      ((j * bts2rd) + i) / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
309
310                    /*
311                     * Get the number of entries so we can count down and
312                     * also the checksum of the short entry.
313                     */
314                    lfn_entries = (*MSDOS_DIR_ENTRY_TYPE(entry) &
315                                   MSDOS_LAST_LONG_ENTRY_MASK);
316                    lfn_checksum = *MSDOS_DIR_LFN_CHECKSUM(entry);
317                    memset (tmp_dirent.d_name, 0, sizeof(tmp_dirent.d_name));
318                }
319
320                /*
321                 * If the entry number or the check sum do not match
322                 * forget this series of long directory entries. These could
323                 * be orphaned entries depending on the history of the
324                 * disk.
325                 */
326                if ((lfn_entries != (*MSDOS_DIR_ENTRY_TYPE(entry) &
327                                     MSDOS_LAST_LONG_ENTRY_MASK)) ||
328                    (lfn_checksum != *MSDOS_DIR_LFN_CHECKSUM(entry)))
329                {
330                    lfn_start = FAT_FILE_SHORT_NAME;
331                    continue;
332                }
333
334                /*
335                 * Extract the file name into the directory entry. The data is
336                 * stored in UNICODE characters (16bit). No translation is
337                 * currently supported.
338                 *
339                 * The DOS maximum length is 255 characters without the
340                 * trailing nul character. We need to range check the length to
341                 * fit in the directory entry name field.
342                 */
343
344                lfn_entries--;
345                p = entry + 1;
346                o = lfn_entries * MSDOS_LFN_LEN_PER_ENTRY;
347
348                for (q = 0; q < MSDOS_LFN_LEN_PER_ENTRY; q++)
349                {
350                    if (o >= (sizeof(tmp_dirent.d_name) - 1))
351                        break;
352
353                    tmp_dirent.d_name[o++] = *p;
354
355                    if (*p == '\0')
356                        break;
357
358                    switch (q)
359                    {
360                        case 4:
361                            p += 5;
362                            break;
363                        case 10:
364                            p += 4;
365                            break;
366                        default:
367                            p += 2;
368                            break;
369                    }
370                }
371            }
372            else
373            {
374                fat_dir_pos_t dir_pos;
375
376                /*
377                 * Skip active entries until get the entry to start from.
378                 */
379                if (start)
380                {
381                    lfn_start = FAT_FILE_SHORT_NAME;
382                    start--;
383                    continue;
384                }
385
386                /*
387                 * Move the entry to the return buffer
388                 *
389                 * unfortunately there is no method to extract ino except to
390                 * open fat-file descriptor :( ... so, open it
391                 */
392
393                /* get number of cluster we are working with */
394                rc = fat_file_ioctl(iop->pathinfo.mt_entry, fat_fd, F_CLU_NUM,
395                                    j * bts2rd, &cur_cln);
396                if (rc != RC_OK)
397                {
398                    rtems_semaphore_release(fs_info->vol_sema);
399                    return rc;
400                }
401
402                fat_dir_pos_init(&dir_pos);
403                dir_pos.sname.cln = cur_cln;
404                dir_pos.sname.ofs = i;
405                rc = fat_file_open(iop->pathinfo.mt_entry, &dir_pos, &tmp_fat_fd);
406                if (rc != RC_OK)
407                {
408                    rtems_semaphore_release(fs_info->vol_sema);
409                    return rc;
410                }
411
412                /* fill in dirent structure */
413                /* XXX: from what and in what d_off should be computed ?! */
414                tmp_dirent.d_off = start + cmpltd;
415                tmp_dirent.d_reclen = sizeof(struct dirent);
416                tmp_dirent.d_ino = tmp_fat_fd->ino;
417
418                /*
419                 * If a long file name check if the correct number of
420                 * entries have been found and if the checksum is correct.
421                 * If not return the short file name.
422                 */
423                if (lfn_start != FAT_FILE_SHORT_NAME)
424                {
425                    uint8_t  cs = 0;
426                    uint8_t* p = (uint8_t*) entry;
427                    int      i;
428
429                    for (i = 0; i < 11; i++, p++)
430                        cs = ((cs & 1) ? 0x80 : 0) + (cs >> 1) + *p;
431
432                    if (lfn_entries || (lfn_checksum != cs))
433                        lfn_start = FAT_FILE_SHORT_NAME;
434                }
435
436                if (lfn_start == FAT_FILE_SHORT_NAME)
437                {
438                    /*
439                     * convert dir entry from fixed 8+3 format (without dot)
440                     * to 0..8 + 1dot + 0..3 format
441                     */
442                    tmp_dirent.d_namlen = msdos_format_dirent_with_dot(
443                        tmp_dirent.d_name, entry); /* src text */
444                }
445                else
446                {
447                    tmp_dirent.d_namlen = strlen(tmp_dirent.d_name);
448                }
449
450                memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
451
452                iop->offset = iop->offset + sizeof(struct dirent);
453                cmpltd += (sizeof(struct dirent));
454                count -= (sizeof(struct dirent));
455
456                /* inode number extracted, close fat-file */
457                rc = fat_file_close(iop->pathinfo.mt_entry, tmp_fat_fd);
458                if (rc != RC_OK)
459                {
460                    rtems_semaphore_release(fs_info->vol_sema);
461                    return rc;
462                }
463            }
464
465            if (count <= 0)
466                break;
467        }
468        j++;
469    }
470
471    rtems_semaphore_release(fs_info->vol_sema);
472    return cmpltd;
473}
474
475/* msdos_dir_write --
476 *     no write for directory
477 */
478
479/* msdos_dir_lseek --
480 *
481 *  This routine will behave in one of three ways based on the state of
482 *  argument whence. Based on the state of its value the offset argument will
483 *  be interpreted using one of the following methods:
484 *
485 *     SEEK_SET - offset is the absolute byte offset from the start of the
486 *                logical start of the dirent sequence that represents the
487 *                directory
488 *     SEEK_CUR - offset is used as the relative byte offset from the current
489 *                directory position index held in the iop structure
490 *     SEEK_END - N/A --> This will cause an assert.
491 *
492 * PARAMETERS:
493 *     iop    - file control block
494 *     offset - offset
495 *     whence - predefine directive
496 *
497 * RETURNS:
498 *     RC_OK on success, or -1 if error occured (errno
499 *     set apropriately).
500 */
501rtems_off64_t
502msdos_dir_lseek(rtems_libio_t *iop, rtems_off64_t offset, int whence)
503{
504    switch (whence)
505    {
506        case SEEK_SET:
507        case SEEK_CUR:
508            break;
509        /*
510         * Movement past the end of the directory via lseek is not a
511         * permitted operation
512         */
513        case SEEK_END:
514        default:
515            rtems_set_errno_and_return_minus_one( EINVAL );
516            break;
517    }
518    return RC_OK;
519}
520
521/* msdos_dir_stat --
522 *
523 * This routine will obtain the following information concerning the current
524 * directory:
525 *     st_dev      device id
526 *     st_ino      node serial number :)
527 *     st_mode     mode extracted from the node
528 *     st_size     total size in bytes
529 *     st_blksize  blocksize for filesystem I/O
530 *     st_blocks   number of blocks allocated
531 *     stat_mtime  time of last modification
532 *
533 * PARAMETERS:
534 *     loc - this directory
535 *     buf - stat buffer provided by user
536 *
537 * RETURNS:
538 *     RC_OK and filled stat buffer on success, or -1 if error occured (errno
539 *     set apropriately).
540 */
541int
542msdos_dir_stat(
543    rtems_filesystem_location_info_t *loc,
544    struct stat                      *buf
545    )
546{
547    rtems_status_code  sc = RTEMS_SUCCESSFUL;
548    msdos_fs_info_t   *fs_info = loc->mt_entry->fs_info;
549    fat_file_fd_t     *fat_fd = loc->node_access;
550
551    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
552                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
553    if (sc != RTEMS_SUCCESSFUL)
554        rtems_set_errno_and_return_minus_one(EIO);
555
556    buf->st_dev = fs_info->fat.vol.dev;
557    buf->st_ino = fat_fd->ino;
558    buf->st_mode  = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
559    buf->st_rdev = 0ll;
560    buf->st_size = fat_fd->fat_file_size;
561    buf->st_blocks = fat_fd->fat_file_size >> FAT_SECTOR512_BITS;
562    buf->st_blksize = fs_info->fat.vol.bps;
563    buf->st_mtime = fat_fd->mtime;
564
565    rtems_semaphore_release(fs_info->vol_sema);
566    return RC_OK;
567}
568
569/* msdos_dir_truncate --
570 *     No truncate for directory.
571 *
572 * PARAMETERS:
573 *
574 * RETURNS:
575 *
576 */
577
578/* msdos_dir_sync --
579 *     The following routine does a syncronization on a MSDOS directory node.
580 *     DIR_WrtTime, DIR_WrtDate and DIR_fileSize fields of 32 Bytes Directory
581 *     Entry Structure should not be updated for directories, so only call
582 *     to corresponding fat-file routine.
583 *
584 * PARAMETERS:
585 *     iop - file control block
586 *
587 * RETURNS:
588 *     RC_OK on success, or -1 if error occured (errno set apropriately).
589 */
590int
591msdos_dir_sync(rtems_libio_t *iop)
592{
593    int                rc = RC_OK;
594    rtems_status_code  sc = RTEMS_SUCCESSFUL;
595    fat_file_fd_t     *fat_fd = iop->file_info;
596    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
597
598    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
599                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
600    if (sc != RTEMS_SUCCESSFUL)
601        rtems_set_errno_and_return_minus_one(EIO);
602
603    rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
604
605    rtems_semaphore_release(fs_info->vol_sema);
606    return rc;
607}
608
609/* msdos_dir_chmod --
610 *     Change the attributes of the directory. This currently does
611 *     nothing and returns no error.
612 *
613 * PARAMETERS:
614 *     pathloc - node description
615 *     mode - the new mode
616 *
617 * RETURNS:
618 *     RC_OK always
619 */
620int
621msdos_dir_chmod(rtems_filesystem_location_info_t *pathloc,
622                mode_t                            mode)
623{
624  return RC_OK;
625}
626
627/* msdos_dir_rmnod --
628 *     Remove directory node.
629 *
630 *     Check that this directory node is not opened as fat-file, is empty and
631 *     not filesystem root node. If all this conditions met then delete.
632 *
633 * PARAMETERS:
634 *     pathloc - node description
635 *
636 * RETURNS:
637 *     RC_OK on success, or -1 if error occured (errno set apropriately).
638 */
639int
640msdos_dir_rmnod(rtems_filesystem_location_info_t *parent_pathloc,
641                rtems_filesystem_location_info_t *pathloc)
642{
643    int                rc = RC_OK;
644    rtems_status_code  sc = RTEMS_SUCCESSFUL;
645    msdos_fs_info_t   *fs_info = pathloc->mt_entry->fs_info;
646    fat_file_fd_t     *fat_fd = pathloc->node_access;
647    bool               is_empty = false;
648
649    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
650                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
651    if (sc != RTEMS_SUCCESSFUL)
652        rtems_set_errno_and_return_minus_one(EIO);
653
654    /*
655     * We deny attempts to delete open directory (if directory is current
656     * directory we assume it is open one)
657     */
658    if (fat_fd->links_num > 1)
659    {
660        rtems_semaphore_release(fs_info->vol_sema);
661        rtems_set_errno_and_return_minus_one(EBUSY);
662    }
663
664    /*
665     * You cannot remove a node that still has children
666     */
667    rc = msdos_dir_is_empty(pathloc->mt_entry, fat_fd, &is_empty);
668    if (rc != RC_OK)
669    {
670        rtems_semaphore_release(fs_info->vol_sema);
671        return rc;
672    }
673
674    if (!is_empty)
675    {
676        rtems_semaphore_release(fs_info->vol_sema);
677        rtems_set_errno_and_return_minus_one(ENOTEMPTY);
678    }
679
680    /*
681     * You cannot remove the file system root node.
682     */
683    if (pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access)
684    {
685        rtems_semaphore_release(fs_info->vol_sema);
686        rtems_set_errno_and_return_minus_one(EBUSY);
687    }
688
689    /*
690     * You cannot remove a mountpoint.
691     * not used - mount() not implemenetd yet.
692     */
693
694    /* mark file removed */
695    rc = msdos_set_first_char4file_name(pathloc->mt_entry, &fat_fd->dir_pos,
696                                        MSDOS_THIS_DIR_ENTRY_EMPTY);
697    if (rc != RC_OK)
698    {
699        rtems_semaphore_release(fs_info->vol_sema);
700        return rc;
701    }
702
703    fat_file_mark_removed(pathloc->mt_entry, fat_fd);
704
705    rtems_semaphore_release(fs_info->vol_sema);
706    return rc;
707}
Note: See TracBrowser for help on using the repository browser.