OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libfs/] [src/] [dosfs/] [msdos_dir.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
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.OARcorp.com/rtems/license.html.
10
 *
11
 *  @(#) msdos_dir.c,v 1.1 2002/02/28 20:43:50 joel Exp
12
 */
13
#if HAVE_CONFIG_H
14
#include "config.h"
15
#endif
16
 
17
#include <stdlib.h>
18
#include <unistd.h>
19
#include <assert.h>
20
#include <errno.h>
21
#include <rtems/libio_.h>
22
#include <sys/types.h>
23
#include <sys/stat.h>
24
 
25
#include <dirent.h>
26
 
27
#include "fat.h"
28
#include "fat_fat_operations.h"
29
#include "fat_file.h"
30
 
31
#include "msdos.h"
32
 
33
/* msdos_dir_open --
34
 *     Open fat-file which correspondes to the directory being opened and
35
 *     set offset field of file control block to zero.
36
 *
37
 * PARAMETERS:
38
 *     iop        - file control block
39
 *     pathname   - name
40
 *     flag       - flags
41
 *     mode       - mode
42
 *
43
 * RETURNS:
44
 *     RC_OK, if directory opened successfully, or -1 if error occured (errno
45
 *     set apropriately)
46
 */
47
int
48
msdos_dir_open(rtems_libio_t *iop, const char *pathname, unsigned32 flag,
49
               unsigned32 mode)
50
{
51
    int                rc = RC_OK;
52
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
53
    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
54
    fat_file_fd_t     *fat_fd = iop->file_info;
55
 
56
    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
57
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
58
    if (sc != RTEMS_SUCCESSFUL)
59
        set_errno_and_return_minus_one( EIO );
60
 
61
    rc = fat_file_reopen(fat_fd);
62
    if (rc != RC_OK)
63
    {
64
        rtems_semaphore_release(fs_info->vol_sema);
65
        return rc;
66
    }
67
 
68
    iop->offset = 0;
69
    rtems_semaphore_release(fs_info->vol_sema);
70
    return RC_OK;
71
}
72
 
73
/* msdos_dir_close --
74
 *     Close  fat-file which correspondes to the directory being closed
75
 *
76
 * PARAMETERS:
77
 *     iop - file control block
78
 *
79
 * RETURNS:
80
 *     RC_OK, if directory closed successfully, or -1 if error occured (errno
81
 *     set apropriately.
82
 */
83
int
84
msdos_dir_close(rtems_libio_t *iop)
85
{
86
    int                rc = RC_OK;
87
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
88
    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
89
    fat_file_fd_t     *fat_fd = iop->file_info;
90
 
91
    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
92
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
93
    if (sc != RTEMS_SUCCESSFUL)
94
        set_errno_and_return_minus_one( EIO );
95
 
96
    rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
97
    if (rc != RC_OK)
98
    {
99
        rtems_semaphore_release(fs_info->vol_sema);
100
        return rc;
101
    }
102
 
103
    rtems_semaphore_release(fs_info->vol_sema);
104
    return RC_OK;
105
}
106
 
107
/*  msdos_dir_read --
108
 *      This routine will read the next directory entry based on the directory
109
 *      offset. The offset should be equal to -n- time the size of an
110
 *      individual dirent structure. If n is not an integer multiple of the
111
 *      sizeof a dirent structure, an integer division will be performed to
112
 *      determine directory entry that will be returned in the buffer. Count
113
 *      should reflect -m- times the sizeof dirent bytes to be placed in the
114
 *      buffer.
115
 *      If there are not -m- dirent elements from the current directory
116
 *      position to the end of the exisiting file, the remaining entries will
117
 *      be placed in the buffer and the returned value will be equal to
118
 *      -m actual- times the size of a directory entry.
119
 *
120
 * PARAMETERS:
121
 *     iop    - file control block
122
 *     buffer - buffer provided by user
123
 *     count  - count of bytes to read
124
 *
125
 * RETURNS:
126
 *     the number of bytes read on success, or -1 if error occured (errno
127
 *     set apropriately).
128
 */
129
ssize_t
130
msdos_dir_read(rtems_libio_t *iop, void *buffer, unsigned32 count)
131
{
132
    int                rc = RC_OK;
133
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
134
    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
135
    fat_file_fd_t     *fat_fd = iop->file_info;
136
    fat_file_fd_t     *tmp_fat_fd = NULL;
137
    struct dirent      tmp_dirent;
138
    unsigned32         start = 0;
139
    ssize_t            ret = 0;
140
    unsigned32         cmpltd = 0;
141
    unsigned32         j = 0, i = 0;
142
    unsigned32         bts2rd = 0;
143
    unsigned32         cur_cln = 0;
144
 
145
    /*
146
     * cast start and count - protect against using sizes that are not exact
147
     * multiples of the -dirent- size. These could result in unexpected
148
     * results
149
     */
150
    start = iop->offset / sizeof(struct dirent);
151
    count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
152
 
153
    /*
154
     * optimization: we know that root directory for FAT12/16 volumes is
155
     * sequential set of sectors and any cluster is sequential set of sectors
156
     * too, so read such set of sectors is quick operation for low-level IO
157
     * layer.
158
     */
159
    bts2rd = (FAT_FD_OF_ROOT_DIR(fat_fd) &&
160
             (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) ?
161
             fat_fd->fat_file_size                              :
162
             fs_info->fat.vol.bpc;
163
 
164
    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
165
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
166
    if (sc != RTEMS_SUCCESSFUL)
167
        set_errno_and_return_minus_one(EIO);
168
 
169
    while (count > 0)
170
    {
171
        /*
172
         * fat-file is already opened by open call, so read it
173
         * Always read directory fat-file from the beggining because of MSDOS
174
         * directories feature :( - we should count elements currently
175
         * present in the directory because there may be holes :)
176
         */
177
        ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, (j * bts2rd),
178
                            bts2rd, fs_info->cl_buf);
179
        if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
180
        {
181
            rtems_semaphore_release(fs_info->vol_sema);
182
            set_errno_and_return_minus_one(EIO);
183
        }
184
 
185
        for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
186
        {
187
            if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
188
                MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
189
            {
190
                rtems_semaphore_release(fs_info->vol_sema);
191
                return cmpltd;
192
            }
193
 
194
            if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
195
                MSDOS_THIS_DIR_ENTRY_EMPTY)
196
                continue;
197
 
198
            /*
199
             * skip active entries until get the entry to start from
200
             */
201
            if (start)
202
            {
203
                start--;
204
                continue;
205
            }
206
 
207
            /*
208
             * Move the entry to the return buffer
209
             *
210
             * unfortunately there is no method to extract ino except to
211
             * open fat-file descriptor :( ... so, open it
212
             */
213
 
214
            /* get number of cluster we are working with */
215
            rc = fat_file_ioctl(iop->pathinfo.mt_entry, fat_fd, F_CLU_NUM,
216
                                j * bts2rd, &cur_cln);
217
            if (rc != RC_OK)
218
            {
219
                rtems_semaphore_release(fs_info->vol_sema);
220
                return rc;
221
            }
222
 
223
            rc = fat_file_open(iop->pathinfo.mt_entry, cur_cln, i,
224
                               &tmp_fat_fd);
225
            if (rc != RC_OK)
226
            {
227
                rtems_semaphore_release(fs_info->vol_sema);
228
                return rc;
229
            }
230
 
231
            tmp_fat_fd->info_cln = cur_cln;
232
            tmp_fat_fd->info_ofs = i;
233
 
234
            /* fill in dirent structure */
235
            /* XXX: from what and in what d_off should be computed ?! */
236
            tmp_dirent.d_off = start + cmpltd;
237
            tmp_dirent.d_reclen = sizeof(struct dirent);
238
            tmp_dirent.d_ino = tmp_fat_fd->ino;
239
            tmp_dirent.d_namlen = MSDOS_SHORT_NAME_LEN;
240
            memcpy(tmp_dirent.d_name, MSDOS_DIR_NAME((fs_info->cl_buf + i)),
241
                   MSDOS_SHORT_NAME_LEN);
242
 
243
            /* d_name is null-terminated */
244
            tmp_dirent.d_name[MSDOS_SHORT_NAME_LEN] = 0;
245
            memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
246
 
247
            iop->offset = iop->offset + sizeof(struct dirent);
248
            cmpltd += (sizeof(struct dirent));
249
            count -= (sizeof(struct dirent));
250
 
251
            /* inode number extracted, close fat-file */
252
            rc = fat_file_close(iop->pathinfo.mt_entry, tmp_fat_fd);
253
            if (rc != RC_OK)
254
            {
255
                rtems_semaphore_release(fs_info->vol_sema);
256
                return rc;
257
            }
258
 
259
            if (count <= 0)
260
                break;
261
        }
262
        j++;
263
    }
264
 
265
    rtems_semaphore_release(fs_info->vol_sema);
266
    return cmpltd;
267
}
268
 
269
/* msdos_dir_write --
270
 *     no write for directory
271
 */
272
 
273
/* msdos_dir_lseek --
274
 *
275
 *  This routine will behave in one of three ways based on the state of
276
 *  argument whence. Based on the state of its value the offset argument will
277
 *  be interpreted using one of the following methods:
278
 *
279
 *     SEEK_SET - offset is the absolute byte offset from the start of the
280
 *                logical start of the dirent sequence that represents the
281
 *                directory
282
 *     SEEK_CUR - offset is used as the relative byte offset from the current
283
 *                directory position index held in the iop structure
284
 *     SEEK_END - N/A --> This will cause an assert.
285
 *
286
 * PARAMETERS:
287
 *     iop    - file control block
288
 *     offset - offset
289
 *     whence - predefine directive
290
 *
291
 * RETURNS:
292
 *     RC_OK on success, or -1 if error occured (errno
293
 *     set apropriately).
294
 */
295
int
296
msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
297
{
298
    switch (whence)
299
    {
300
        case SEEK_SET:
301
        case SEEK_CUR:
302
            break;
303
        /*
304
         * Movement past the end of the directory via lseek is not a
305
         * permitted operation
306
         */
307
        case SEEK_END:
308
        default:
309
            set_errno_and_return_minus_one( EINVAL );
310
            break;
311
    }
312
    return RC_OK;
313
}
314
 
315
/* msdos_dir_stat --
316
 *
317
 * This routine will obtain the following information concerning the current
318
 * directory:
319
 *     st_dev      device id
320
 *     st_ino      node serial number :)
321
 *     st_mode     mode extracted from the node
322
 *     st_size     total size in bytes
323
 *     st_blksize  blocksize for filesystem I/O
324
 *     st_blocks   number of blocks allocated
325
 *     stat_mtime  time of last modification
326
 *
327
 * PARAMETERS:
328
 *     loc - this directory
329
 *     buf - stat buffer provided by user
330
 *
331
 * RETURNS:
332
 *     RC_OK and filled stat buffer on success, or -1 if error occured (errno
333
 *     set apropriately).
334
 */
335
int
336
msdos_dir_stat(
337
    rtems_filesystem_location_info_t *loc,
338
    struct stat                      *buf
339
    )
340
{
341
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
342
    msdos_fs_info_t   *fs_info = loc->mt_entry->fs_info;
343
    fat_file_fd_t     *fat_fd = loc->node_access;
344
 
345
    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
346
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
347
    if (sc != RTEMS_SUCCESSFUL)
348
        set_errno_and_return_minus_one(EIO);
349
 
350
    buf->st_dev = fs_info->fat.vol.dev;
351
    buf->st_ino = fat_fd->ino;
352
    buf->st_mode  = S_IFDIR;
353
    buf->st_rdev = 0ll;
354
    buf->st_size = fat_fd->fat_file_size;
355
    buf->st_blocks = fat_fd->fat_file_size >> FAT_SECTOR512_BITS;
356
    buf->st_blksize = fs_info->fat.vol.bps;
357
    buf->st_mtime = fat_fd->mtime;
358
 
359
    rtems_semaphore_release(fs_info->vol_sema);
360
    return RC_OK;
361
}
362
 
363
/* msdos_dir_truncate --
364
 *     No truncate for directory.
365
 *
366
 * PARAMETERS:
367
 *
368
 * RETURNS:
369
 *
370
 */
371
 
372
/* msdos_dir_sync --
373
 *     The following routine does a syncronization on a MSDOS directory node.
374
 *     DIR_WrtTime, DIR_WrtDate and DIR_fileSize fields of 32 Bytes Directory
375
 *     Entry Structure(see M$ White Paper) should not be updated for
376
 *     directories, so only call to corresponding fat-file routine.
377
 *
378
 * PARAMETERS:
379
 *     iop - file control block
380
 *
381
 * RETURNS:
382
 *     RC_OK on success, or -1 if error occured (errno set apropriately).
383
 */
384
int
385
msdos_dir_sync(rtems_libio_t *iop)
386
{
387
    int                rc = RC_OK;
388
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
389
    fat_file_fd_t     *fat_fd = iop->file_info;
390
    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
391
 
392
    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
393
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
394
    if (sc != RTEMS_SUCCESSFUL)
395
        set_errno_and_return_minus_one(EIO);
396
 
397
    rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
398
 
399
    rtems_semaphore_release(fs_info->vol_sema);
400
    return rc;
401
}
402
 
403
/* msdos_dir_rmnod --
404
 *     Remove directory node.
405
 *
406
 *     Check that this directory node is not opened as fat-file, is empty and
407
 *     not filesystem root node. If all this conditions met then delete.
408
 *
409
 * PARAMETERS:
410
 *     pathloc - node description
411
 *
412
 * RETURNS:
413
 *     RC_OK on success, or -1 if error occured (errno set apropriately).
414
 */
415
int
416
msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
417
{
418
    int                rc = RC_OK;
419
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
420
    msdos_fs_info_t   *fs_info = pathloc->mt_entry->fs_info;
421
    fat_file_fd_t     *fat_fd = pathloc->node_access;
422
    rtems_boolean      is_empty = FALSE;
423
 
424
    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
425
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
426
    if (sc != RTEMS_SUCCESSFUL)
427
        set_errno_and_return_minus_one(EIO);
428
 
429
    /*
430
     * We deny attemp to delete open directory (if directory is current
431
     * directory we assume it is open one)
432
     */
433
    if (fat_fd->links_num > 1)
434
    {
435
        rtems_semaphore_release(fs_info->vol_sema);
436
        set_errno_and_return_minus_one(EBUSY);
437
    }
438
 
439
    /*
440
     * You cannot remove a node that still has children
441
     */
442
    rc = msdos_dir_is_empty(pathloc->mt_entry, fat_fd, &is_empty);
443
    if (rc != RC_OK)
444
    {
445
        rtems_semaphore_release(fs_info->vol_sema);
446
        return rc;
447
    }
448
 
449
    if (!is_empty)
450
    {
451
        rtems_semaphore_release(fs_info->vol_sema);
452
        set_errno_and_return_minus_one(ENOTEMPTY);
453
    }
454
 
455
    /*
456
     * You cannot remove the file system root node.
457
     */
458
    if (pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access)
459
    {
460
        rtems_semaphore_release(fs_info->vol_sema);
461
        set_errno_and_return_minus_one(EBUSY);
462
    }
463
 
464
    /*
465
     * You cannot remove a mountpoint.
466
     * not used - mount() not implemenetd yet.
467
     */
468
 
469
    /* mark file removed */
470
    rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
471
                                        fat_fd->info_ofs,
472
                                        MSDOS_THIS_DIR_ENTRY_EMPTY);
473
    if (rc != RC_OK)
474
    {
475
        rtems_semaphore_release(fs_info->vol_sema);
476
        return rc;
477
    }
478
 
479
    fat_file_mark_removed(pathloc->mt_entry, fat_fd);
480
 
481
    rtems_semaphore_release(fs_info->vol_sema);
482
    return rc;
483
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.