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

4.11
Last change on this file since 03e54614 was 03e54614, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 27, 2013 at 7:06:16 PM

statvfs filesystem handlers: Remove restrict

  • Property mode set to 100644
File size: 8.2 KB
Line 
1/**
2 * @file
3 *
4 * @brief MSDOS File Handlers Implementation
5 * @ingroup libfs
6 */
7
8/*
9 *  Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
10 *  Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 */
16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <stdlib.h>
21#include <errno.h>
22
23#include <rtems.h>
24#include <rtems/libio.h>
25#include <rtems/libio_.h>
26
27#include "fat.h"
28#include "fat_fat_operations.h"
29#include "fat_file.h"
30
31#include "msdos.h"
32
33static int
34msdos_file_update(rtems_libio_t *iop)
35{
36    int              rc = RC_OK;
37    fat_file_fd_t   *fat_fd = iop->pathinfo.node_access;
38
39    /*
40     * if fat-file descriptor is not marked as "removed", synchronize
41     * size, first cluster number, write time and date fields of the file
42     */
43    if (!FAT_FILE_IS_REMOVED(fat_fd))
44    {
45        rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
46        if (rc != RC_OK)
47        {
48            return rc;
49        }
50
51        rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
52        if (rc != RC_OK)
53        {
54            return rc;
55        }
56
57        rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
58        if (rc != RC_OK)
59        {
60            return rc;
61        }
62    }
63
64    return rc;
65}
66
67/* msdos_file_close --
68 *     Close fat-file which correspondes to the file. If fat-file descriptor
69 *     which correspondes to the file is not marked "removed", synchronize
70 *     size, first cluster number, write time and date fields of the file.
71 *
72 * PARAMETERS:
73 *     iop - file control block
74 *
75 * RETURNS:
76 *     RC_OK, if file closed successfully, or -1 if error occured (errno set
77 *     appropriately)
78 */
79int
80msdos_file_close(rtems_libio_t *iop)
81{
82    int                rc = RC_OK;
83    rtems_status_code  sc = RTEMS_SUCCESSFUL;
84    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
85
86    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
87                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
88    if (sc != RTEMS_SUCCESSFUL)
89        rtems_set_errno_and_return_minus_one(EIO);
90
91    rc = msdos_file_update(iop);
92
93    rtems_semaphore_release(fs_info->vol_sema);
94    return rc;
95}
96
97/* msdos_file_read --
98 *     This routine read from file pointed to by file control block into
99 *     the specified data buffer provided by user
100 *
101 * PARAMETERS:
102 *     iop    - file control block
103 *     buffer - buffer  provided by user
104 *     count  - the number of bytes to read
105 *
106 * RETURNS:
107 *     the number of bytes read on success, or -1 if error occured (errno set
108 *     appropriately)
109 */
110ssize_t
111msdos_file_read(rtems_libio_t *iop, void *buffer, size_t count)
112{
113    ssize_t            ret = 0;
114    rtems_status_code  sc = RTEMS_SUCCESSFUL;
115    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
116    fat_file_fd_t     *fat_fd = iop->pathinfo.node_access;
117
118    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
119                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
120    if (sc != RTEMS_SUCCESSFUL)
121        rtems_set_errno_and_return_minus_one(EIO);
122
123    ret = fat_file_read(&fs_info->fat, fat_fd, iop->offset, count,
124                        buffer);
125    if (ret > 0)
126        iop->offset += ret;
127
128    rtems_semaphore_release(fs_info->vol_sema);
129    return ret;
130}
131
132/* msdos_file_write --
133 *     This routine writes the specified data buffer into the file pointed to
134 *     by file control block.
135 *
136 * PARAMETERS:
137 *     iop    - file control block
138 *     buffer - data to write
139 *     count  - count of bytes to write
140 *
141 * RETURNS:
142 *     the number of bytes written on success, or -1 if error occured
143 *     and errno set appropriately
144 */
145ssize_t
146msdos_file_write(rtems_libio_t *iop,const void *buffer, size_t count)
147{
148    ssize_t            ret = 0;
149    rtems_status_code  sc = RTEMS_SUCCESSFUL;
150    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
151    fat_file_fd_t     *fat_fd = iop->pathinfo.node_access;
152
153    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
154                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
155    if (sc != RTEMS_SUCCESSFUL)
156        rtems_set_errno_and_return_minus_one(EIO);
157
158    if ((iop->flags & LIBIO_FLAGS_APPEND) != 0)
159        iop->offset = fat_fd->fat_file_size;
160
161    ret = fat_file_write(&fs_info->fat, fat_fd, iop->offset, count,
162                         buffer);
163    if (ret < 0)
164    {
165        rtems_semaphore_release(fs_info->vol_sema);
166        return -1;
167    }
168
169    /*
170     * update file size in both fat-file descriptor and file control block if
171     * file was extended
172     */
173    iop->offset += ret;
174    if (iop->offset > fat_fd->fat_file_size)
175        fat_fd->fat_file_size = iop->offset;
176
177    rtems_semaphore_release(fs_info->vol_sema);
178    return ret;
179}
180
181/* msdos_file_stat --
182 *
183 * PARAMETERS:
184 *     loc - node description
185 *     buf - stat buffer provided by user
186 *
187 * RETURNS:
188 *     RC_OK on success, or -1 if error occured (errno set appropriately)
189 */
190int
191msdos_file_stat(
192    const rtems_filesystem_location_info_t *loc,
193    struct stat *buf
194)
195{
196    rtems_status_code  sc = RTEMS_SUCCESSFUL;
197    msdos_fs_info_t   *fs_info = loc->mt_entry->fs_info;
198    fat_file_fd_t     *fat_fd = loc->node_access;
199    uint32_t           cl_mask = fs_info->fat.vol.bpc - 1;
200
201    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
202                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
203    if (sc != RTEMS_SUCCESSFUL)
204        rtems_set_errno_and_return_minus_one(EIO);
205
206    buf->st_dev = rtems_disk_get_device_identifier(fs_info->fat.vol.dd);
207    buf->st_ino = fat_fd->ino;
208    buf->st_mode  = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
209    buf->st_rdev = 0ll;
210    buf->st_size = fat_fd->fat_file_size;
211    buf->st_blocks = ((fat_fd->fat_file_size + cl_mask) & ~cl_mask)
212      >> FAT_SECTOR512_BITS;
213    buf->st_blksize = fs_info->fat.vol.bpc;
214    buf->st_mtime = fat_fd->mtime;
215
216    rtems_semaphore_release(fs_info->vol_sema);
217    return RC_OK;
218}
219
220/* msdos_file_ftruncate --
221 *     Truncate the file.
222 *
223 * PARAMETERS:
224 *     iop    - file control block
225 *     length - new length
226 *
227 * RETURNS:
228 *     RC_OK on success, or -1 if error occured (errno set appropriately).
229 */
230int
231msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
232{
233    int                rc = RC_OK;
234    rtems_status_code  sc = RTEMS_SUCCESSFUL;
235    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
236    fat_file_fd_t     *fat_fd = iop->pathinfo.node_access;
237    uint32_t old_length;
238
239    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
240                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
241    if (sc != RTEMS_SUCCESSFUL)
242        rtems_set_errno_and_return_minus_one(EIO);
243
244    old_length = fat_fd->fat_file_size;
245    if (length < old_length) {
246        rc = fat_file_truncate(&fs_info->fat, fat_fd, length);
247    } else {
248        uint32_t new_length;
249
250        rc = fat_file_extend(&fs_info->fat,
251                             fat_fd,
252                             true,
253                             length,
254                             &new_length);
255        if (rc == RC_OK && length != new_length) {
256            fat_file_truncate(&fs_info->fat, fat_fd, old_length);
257            errno = ENOSPC;
258            rc = -1;
259        }
260    }
261
262    if (rc == RC_OK) {
263        fat_fd->fat_file_size = length;
264    }
265
266    rtems_semaphore_release(fs_info->vol_sema);
267
268    return rc;
269}
270
271/* msdos_file_sync --
272 *     Synchronize file - synchronize file data and if file is not removed
273 *     synchronize file metadata.
274 *
275 * PARAMETERS:
276 *     iop - file control block
277 *
278 * RETURNS:
279 *     RC_OK on success, or -1 if error occured (errno set appropriately)
280 */
281int
282msdos_file_sync(rtems_libio_t *iop)
283{
284    int                rc = RC_OK;
285    rtems_status_code  sc = RTEMS_SUCCESSFUL;
286    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
287
288    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
289                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
290    if (sc != RTEMS_SUCCESSFUL)
291        rtems_set_errno_and_return_minus_one(EIO);
292
293    rc = msdos_file_update(iop);
294    if (rc != RC_OK)
295    {
296        rtems_semaphore_release(fs_info->vol_sema);
297        return rc;
298    }
299
300    rc = fat_sync(&fs_info->fat);
301
302    rtems_semaphore_release(fs_info->vol_sema);
303    return RC_OK;
304}
Note: See TracBrowser for help on using the repository browser.