source: rtems/cpukit/libfs/src/dosfs/msdos_file.c @ 11458809

4.104.114.84.95
Last change on this file since 11458809 was 7192476f, checked in by Ralf Corsepius <ralf.corsepius@…>, on 12/08/06 at 07:18:27

Use size_t instead of uint32_t for read/write count-args.

  • Property mode set to 100644
File size: 13.4 KB
Line 
1/*
2 *  MSDOS file 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 <stdlib.h>
18#include <assert.h>
19#include <errno.h>
20
21#include <rtems.h>
22#include <rtems/libio.h>
23#include <rtems/libio_.h>
24
25#include "fat.h"
26#include "fat_fat_operations.h"
27#include "fat_file.h"
28
29#include "msdos.h"
30
31/* msdos_file_open --
32 *     Open fat-file which correspondes to the file
33 *
34 * PARAMETERS:
35 *     iop        - file control block
36 *     pathname   - name
37 *     flag       - flags
38 *     mode       - mode
39 *
40 * RETURNS:
41 *     RC_OK, if file opened successfully, or -1 if error occured
42 *     and errno set appropriately
43 */
44int
45msdos_file_open(rtems_libio_t *iop, const char *pathname, uint32_t   flag,
46                uint32_t   mode)
47{
48    int                rc = RC_OK;
49    rtems_status_code  sc = RTEMS_SUCCESSFUL;
50    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
51    fat_file_fd_t     *fat_fd = iop->file_info;
52
53    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
54                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
55    if (sc != RTEMS_SUCCESSFUL)
56        set_errno_and_return_minus_one(EIO);
57
58    rc = fat_file_reopen(fat_fd);
59    if (rc != RC_OK)
60    {
61        rtems_semaphore_release(fs_info->vol_sema);
62        return rc;
63    }
64
65    if (iop->flags & LIBIO_FLAGS_APPEND)
66        iop->offset = fat_fd->fat_file_size;
67
68    iop->size = fat_fd->fat_file_size;
69
70    rtems_semaphore_release(fs_info->vol_sema);
71    return RC_OK;
72}
73
74/* msdos_file_close --
75 *     Close fat-file which correspondes to the file. If fat-file descriptor
76 *     which correspondes to the file is not marked "removed", synchronize
77 *     size, first cluster number, write time and date fields of the file.
78 *
79 * PARAMETERS:
80 *     iop - file control block
81 *
82 * RETURNS:
83 *     RC_OK, if file closed successfully, or -1 if error occured (errno set
84 *     appropriately)
85 */
86int
87msdos_file_close(rtems_libio_t *iop)
88{
89    int                rc = RC_OK;
90    rtems_status_code  sc = RTEMS_SUCCESSFUL;
91    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
92    fat_file_fd_t     *fat_fd = iop->file_info;
93
94    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
95                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
96    if (sc != RTEMS_SUCCESSFUL)
97        set_errno_and_return_minus_one(EIO);
98
99    /*
100     * if fat-file descriptor is not marked as "removed", synchronize
101     * size, first cluster number, write time and date fields of the file
102     */
103    if (!FAT_FILE_IS_REMOVED(fat_fd))
104    {
105        rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
106        if (rc != RC_OK)
107        {
108            rtems_semaphore_release(fs_info->vol_sema);
109            return rc;
110        }
111
112        rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
113        if (rc != RC_OK)
114        {
115            rtems_semaphore_release(fs_info->vol_sema);
116            return rc;
117        }
118
119        rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
120        if (rc != RC_OK)
121        {
122            rtems_semaphore_release(fs_info->vol_sema);
123            return rc;
124        }
125    }
126
127    rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
128
129    rtems_semaphore_release(fs_info->vol_sema);
130    return rc;
131}
132
133/* msdos_file_read --
134 *     This routine read from file pointed to by file control block into
135 *     the specified data buffer provided by user
136 *
137 * PARAMETERS:
138 *     iop    - file control block
139 *     buffer - buffer  provided by user
140 *     count  - the number of bytes to read
141 *
142 * RETURNS:
143 *     the number of bytes read on success, or -1 if error occured (errno set
144 *     appropriately)
145 */
146ssize_t
147msdos_file_read(rtems_libio_t *iop, void *buffer, size_t count)
148{
149    ssize_t            ret = 0;
150    rtems_status_code  sc = RTEMS_SUCCESSFUL;
151    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
152    fat_file_fd_t     *fat_fd = iop->file_info;
153
154    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
155                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
156    if (sc != RTEMS_SUCCESSFUL)
157        set_errno_and_return_minus_one(EIO);
158
159    ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
160                        buffer);
161
162    rtems_semaphore_release(fs_info->vol_sema);
163    return ret;
164}
165
166/* msdos_file_write --
167 *     This routine writes the specified data buffer into the file pointed to
168 *     by file control block.
169 *
170 * PARAMETERS:
171 *     iop    - file control block
172 *     buffer - data to write
173 *     count  - count of bytes to write
174 *
175 * RETURNS:
176 *     the number of bytes written on success, or -1 if error occured
177 *     and errno set appropriately
178 */
179ssize_t
180msdos_file_write(rtems_libio_t *iop,const void *buffer, size_t count)
181{
182    ssize_t            ret = 0;
183    rtems_status_code  sc = RTEMS_SUCCESSFUL;
184    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
185    fat_file_fd_t     *fat_fd = iop->file_info;
186
187    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
188                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
189    if (sc != RTEMS_SUCCESSFUL)
190        set_errno_and_return_minus_one(EIO);
191
192    ret = fat_file_write(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
193                         buffer);
194    if (ret < 0)
195    {
196        rtems_semaphore_release(fs_info->vol_sema);
197        return -1;
198    }
199
200    /*
201     * update file size in both fat-file descriptor and file control block if
202     * file was extended
203     */
204    if (iop->offset + ret > fat_fd->fat_file_size)
205        fat_fd->fat_file_size = iop->offset + ret;
206
207    iop->size = fat_fd->fat_file_size;
208
209    rtems_semaphore_release(fs_info->vol_sema);
210    return ret;
211}
212
213/* msdos_file_lseek --
214 *     Process lseek call to the file: extend file if lseek is up to the end
215 *     of the file.
216 *
217 * PARAMETERS:
218 *     iop    - file control block
219 *     offset - new offset
220 *     whence - predefine directive
221 *
222 * RETURNS:
223 *     new offset on success, or -1 if error occured (errno set
224 *     appropriately).
225 */
226int
227msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
228{
229    int                rc = RC_OK;
230    rtems_status_code  sc = RTEMS_SUCCESSFUL;
231    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
232    fat_file_fd_t     *fat_fd = iop->file_info;
233    uint32_t           real_size = 0;
234
235    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
236                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
237    if (sc != RTEMS_SUCCESSFUL)
238        set_errno_and_return_minus_one(EIO);
239
240    rc = fat_file_extend(iop->pathinfo.mt_entry, fat_fd, iop->offset,
241                         &real_size);
242    if (rc != RC_OK)
243    {
244        rtems_semaphore_release(fs_info->vol_sema);
245        return rc;
246    }
247
248    if (real_size > fat_fd->fat_file_size)
249        fat_fd->fat_file_size = iop->offset = real_size;
250
251    iop->size = fat_fd->fat_file_size;
252
253    rtems_semaphore_release(fs_info->vol_sema);
254    return iop->offset;
255}
256
257/* msdos_file_stat --
258 *
259 * PARAMETERS:
260 *     loc - node description
261 *     buf - stat buffer provided by user
262 *
263 * RETURNS:
264 *     RC_OK on success, or -1 if error occured (errno set appropriately)
265 */
266int
267msdos_file_stat(
268    rtems_filesystem_location_info_t *loc,
269    struct stat                      *buf
270    )
271{
272    rtems_status_code  sc = RTEMS_SUCCESSFUL;
273    msdos_fs_info_t   *fs_info = loc->mt_entry->fs_info;
274    fat_file_fd_t     *fat_fd = loc->node_access;
275
276    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
277                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
278    if (sc != RTEMS_SUCCESSFUL)
279        set_errno_and_return_minus_one(EIO);
280
281    buf->st_dev = fs_info->fat.vol.dev;
282    buf->st_ino = fat_fd->ino;
283    buf->st_mode  = S_IFREG;
284    buf->st_rdev = 0ll;
285    buf->st_size = fat_fd->fat_file_size;
286    buf->st_blocks = fat_fd->fat_file_size >> FAT_SECTOR512_BITS;
287    buf->st_blksize = fs_info->fat.vol.bps;
288    buf->st_mtime = fat_fd->mtime;
289
290    rtems_semaphore_release(fs_info->vol_sema);
291    return RC_OK;
292}
293
294/* msdos_file_ftruncate --
295 *     Truncate the file (if new length is greater then current do nothing).
296 *
297 * PARAMETERS:
298 *     iop    - file control block
299 *     length - new length
300 *
301 * RETURNS:
302 *     RC_OK on success, or -1 if error occured (errno set appropriately).
303 */
304int
305msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
306{
307    int                rc = RC_OK;
308    rtems_status_code  sc = RTEMS_SUCCESSFUL;
309    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
310    fat_file_fd_t     *fat_fd = iop->file_info;
311
312    if (length >= fat_fd->fat_file_size)
313        return RC_OK;
314
315    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
316                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
317    if (sc != RTEMS_SUCCESSFUL)
318        set_errno_and_return_minus_one(EIO);
319
320    rc = fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, length);
321    if (rc != RC_OK)
322    {
323        rtems_semaphore_release(fs_info->vol_sema);
324        return rc;
325    }
326
327    /*
328     * fat_file_truncate do nothing if new length >= fat-file size, so update
329     * file size only if length < fat-file size
330     */
331    if (length < fat_fd->fat_file_size)
332        iop->size = fat_fd->fat_file_size = length;
333
334    rtems_semaphore_release(fs_info->vol_sema);
335    return RC_OK;
336}
337
338/* msdos_file_sync --
339 *     Synchronize file - synchronize file data and if file is not removed
340 *     synchronize file metadata.
341 *
342 * PARAMETERS:
343 *     iop - file control block
344 *
345 * RETURNS:
346 *     RC_OK on success, or -1 if error occured (errno set appropriately)
347 */
348int
349msdos_file_sync(rtems_libio_t *iop)
350{
351    int                rc = RC_OK;
352    rtems_status_code  sc = RTEMS_SUCCESSFUL;
353    fat_file_fd_t     *fat_fd = iop->file_info;
354    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
355
356    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
357                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
358    if (sc != RTEMS_SUCCESSFUL)
359        set_errno_and_return_minus_one(EIO);
360
361    /* synchronize file data */
362    rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
363    if (rc != RC_OK)
364    {
365        rtems_semaphore_release(fs_info->vol_sema);
366        return rc;
367    }
368
369    /*
370     * if fat-file descriptor is not marked "removed" - synchronize file
371     * metadata
372     */
373    if (!FAT_FILE_IS_REMOVED(fat_fd))
374    {
375        rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
376        if (rc != RC_OK)
377        {
378            rtems_semaphore_release(fs_info->vol_sema);
379            return rc;
380        }
381        rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
382        if (rc != RC_OK)
383        {
384            rtems_semaphore_release(fs_info->vol_sema);
385            return rc;
386        }
387        rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
388        if (rc != RC_OK)
389        {
390            rtems_semaphore_release(fs_info->vol_sema);
391            return rc;
392        }
393    }
394
395    rtems_semaphore_release(fs_info->vol_sema);
396    return RC_OK;
397}
398
399/* msdos_file_datasync --
400 *     Synchronize file - synchronize only file data (metadata is letf intact).
401 *
402 * PARAMETERS:
403 *     iop - file control block
404 *
405 * RETURNS:
406 *     RC_OK on success, or -1 if error occured (errno set appropriately)
407 */
408int
409msdos_file_datasync(rtems_libio_t *iop)
410{
411    int                rc = RC_OK;
412    rtems_status_code  sc = RTEMS_SUCCESSFUL;
413    fat_file_fd_t     *fat_fd = iop->file_info;
414    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
415
416    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
417                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
418    if (sc != RTEMS_SUCCESSFUL)
419        set_errno_and_return_minus_one(EIO);
420
421    /* synchronize file data */
422    rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
423
424    rtems_semaphore_release(fs_info->vol_sema);
425    return RC_OK;
426}
427
428
429/* msdos_file_ioctl --
430 *
431 *
432 * PARAMETERS:
433 *     iop    - file control block
434 *     ...
435 *
436 * RETURNS:
437 *
438 */
439int
440msdos_file_ioctl(rtems_libio_t *iop,uint32_t   command, void *buffer)
441{
442    int rc = RC_OK;
443
444    return rc;
445}
446
447/* msdos_file_rmnod --
448 *     Remove node associated with a file - set up first name character to
449 *     predefined value(and write it to the disk), and mark fat-file which
450 *     correspondes to the file as "removed"
451 *
452 * PARAMETERS:
453 *     pathloc - node description
454 *
455 * RETURNS:
456 *     RC_OK on success, or -1 if error occured (errno set appropriately)
457 */
458int
459msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc)
460{
461    int                rc = RC_OK;
462    rtems_status_code  sc = RTEMS_SUCCESSFUL;
463    msdos_fs_info_t   *fs_info = pathloc->mt_entry->fs_info;
464    fat_file_fd_t     *fat_fd = pathloc->node_access;
465
466    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
467                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
468    if (sc != RTEMS_SUCCESSFUL)
469        set_errno_and_return_minus_one(EIO);
470
471    /* mark file removed */
472    rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
473                                        fat_fd->info_ofs,
474                                        MSDOS_THIS_DIR_ENTRY_EMPTY);
475    if (rc != RC_OK)
476    {
477        rtems_semaphore_release(fs_info->vol_sema);
478        return rc;
479    }
480
481    fat_file_mark_removed(pathloc->mt_entry, fat_fd);
482
483    rtems_semaphore_release(fs_info->vol_sema);
484    return RC_OK;
485}
Note: See TracBrowser for help on using the repository browser.