summaryrefslogtreecommitdiffstats
path: root/cpukit/libfs/src/dosfs/fat_file.h
blob: 0f491a90021dd79f7b8abbe03d89a04e6463e22d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/**
 * @file
 *
 * @brief Constants/Data Structures/Prototypes for Operations on "fat-file"
 *
 * @ingroup libfs_ff
 */

/*
 *
 *  Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
 *  Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */

#ifndef __DOSFS_FAT_FILE_H__
#define __DOSFS_FAT_FILE_H__

#include <rtems.h>
#include <rtems/libio_.h>

#include <time.h>

#include "fat.h"

/**
 *  @defgroup libfs_ff Fat File
 *
 *  @ingroup libfs
 */
/**@{*/

#ifdef __cplusplus
extern "C" {
#endif

typedef enum {
  FAT_DIRECTORY = 0,
  FAT_HARD_LINK = 2, /* pseudo type */
  FAT_FILE = 4
} fat_file_type_t;

/**
 * @brief The "fat-file" representation.
 *
 * the idea is: fat-file is nothing but a cluster chain, any open fat-file is
 * represented in system by fat-file descriptor and has well-known
 * file interface:
 *
 * fat_file_open()
 * fat_file_close()
 * fat_file_read()
 * fat_file_write()
 *
 * Such interface hides the architecture of fat-file and represents it like
 * linear file
 */
typedef struct fat_file_map_s
{
    uint32_t   file_cln;
    uint32_t   disk_cln;
    uint32_t   last_cln;
} fat_file_map_t;

/**
 * @brief Descriptor of a fat-file.
 *
 * To each particular clusters chain
 */
typedef struct fat_file_fd_s
{
    rtems_chain_node link;          /*
                                     * fat-file descriptors organized into hash;
                                     * collision lists are handled via link
                                     * field
                                     */
    uint32_t         links_num;     /*
                                     * the number of fat_file_open call on
                                     * this fat-file
                                     */
    uint32_t         ino;           /* inode, file serial number :)))) */
    fat_file_type_t  fat_file_type;
    uint32_t         size_limit;
    uint32_t         fat_file_size; /* length  */
    uint32_t         cln;
    fat_dir_pos_t    dir_pos;
    uint8_t          flags;
    fat_file_map_t   map;
    time_t           ctime;
    time_t           mtime;

} fat_file_fd_t;

#define FAT_FILE_REMOVED 0x01

#define FAT_FILE_META_DATA_CHANGED 0x02

static inline bool FAT_FILE_IS_REMOVED(const fat_file_fd_t *fat_fd)
{
     return (fat_fd->flags & FAT_FILE_REMOVED) != 0;
}

static inline bool FAT_FILE_HAS_META_DATA_CHANGED(const fat_file_fd_t *fat_fd)
{
     return (fat_fd->flags & FAT_FILE_META_DATA_CHANGED) != 0;
}

/* ioctl macros */
#define F_CLU_NUM  0x01

/*
 * Each file and directory on a MSDOS volume is unique identified by it
 * location, i.e. location of it 32 Bytes Directory Entry Structure. We can
 * distinguish them by cluster number it locates on and offset inside this
 * cluster. But root directory on any volumes (FAT12/16/32) has no 32 Bytes
 * Directory Entry Structure corresponded to it. So we assume 32 Bytes
 * Directory Entry Structure of root directory locates at cluster 1 (invalid
 * cluaster number) and offset 0
 */
#define FAT_ROOTDIR_CLUSTER_NUM 0x01

#define FAT_FD_OF_ROOT_DIR(fat_fd)  \
  ((fat_fd->dir_pos.sname.cln == FAT_ROOTDIR_CLUSTER_NUM) && \
  (fat_fd->dir_pos.sname.ofs == 0))

#define FAT_EOF           0x00

/* @brief Construct key for hash access.
 *
 * Construct key for hash access: convert (cluster num, offset) to
 * (sector512 num, new offset) and than construct key as
 * key = (sector512 num) << 4 | (new offset)
 *
 * @param[in] cl - cluster number
 * @param[in] ofs - offset inside cluster 'cl'
 * @param[in] fs_info - FS info
 *
 * @retval constructed key
 */
static inline uint32_t
fat_construct_key(
    const fat_fs_info_t                  *fs_info,
    fat_pos_t                            *pos)
{
    return ( ((fat_cluster_num_to_sector512_num(fs_info, pos->cln) +
              (pos->ofs >> FAT_SECTOR512_BITS)) << 4)              +
              ((pos->ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
}

static inline void
fat_file_set_first_cluster_num(fat_file_fd_t *fat_fd, uint32_t cln)
{
    fat_fd->cln = cln;
    fat_fd->flags |= FAT_FILE_META_DATA_CHANGED;
}

static inline void fat_file_set_file_size(fat_file_fd_t *fat_fd, uint32_t s)
{
    fat_fd->fat_file_size = s;
    fat_fd->flags |= FAT_FILE_META_DATA_CHANGED;
}

static inline void fat_file_set_ctime(fat_file_fd_t *fat_fd, time_t t)
{
    fat_fd->ctime = t;
    fat_fd->flags |= FAT_FILE_META_DATA_CHANGED;
}

static inline void fat_file_set_mtime(fat_file_fd_t *fat_fd, time_t t)
{
    fat_fd->mtime = t;
    fat_fd->flags |= FAT_FILE_META_DATA_CHANGED;
}

static inline void fat_file_set_ctime_mtime(fat_file_fd_t *fat_fd, time_t t)
{
    fat_fd->ctime = t;
    fat_fd->mtime = t;
    fat_fd->flags |= FAT_FILE_META_DATA_CHANGED;
}

/* Prototypes for "fat-file" operations */
int
fat_file_open(fat_fs_info_t                         *fs_info,
              fat_dir_pos_t                         *dir_pos,
              fat_file_fd_t                        **fat_fd);

int
fat_file_reopen(fat_file_fd_t *fat_fd);

int
fat_file_close(fat_fs_info_t                        *fs_info,
               fat_file_fd_t                        *fat_fd);

ssize_t
fat_file_read(fat_fs_info_t                        *fs_info,
              fat_file_fd_t                        *fat_fd,
              uint32_t                              start,
              uint32_t                              count,
              uint8_t                              *buf);

ssize_t
fat_file_write(fat_fs_info_t                        *fs_info,
               fat_file_fd_t                        *fat_fd,
               uint32_t                              start,
               uint32_t                              count,
               const uint8_t                        *buf);

int
fat_file_extend(fat_fs_info_t                        *fs_info,
                fat_file_fd_t                        *fat_fd,
                bool                                  zero_fill,
                uint32_t                              new_length,
                uint32_t                             *a_length);

int
fat_file_truncate(fat_fs_info_t                        *fs_info,
                  fat_file_fd_t                        *fat_fd,
                  uint32_t                              new_length);

int
fat_file_ioctl(fat_fs_info_t                        *fs_info,
               fat_file_fd_t                        *fat_fd,
               int                                   cmd,
               ...);

int
fat_file_size(fat_fs_info_t                        *fs_info,
              fat_file_fd_t                        *fat_fd);

void
fat_file_mark_removed(fat_fs_info_t                        *fs_info,
                      fat_file_fd_t                        *fat_fd);

int
fat_file_size(fat_fs_info_t                        *fs_info,
              fat_file_fd_t                        *fat_fd);

int
fat_file_write_first_cluster_num(fat_fs_info_t *fs_info,
                                 fat_file_fd_t *fat_fd);

int
fat_file_write_file_size(fat_fs_info_t *fs_info,
                         fat_file_fd_t *fat_fd);

int
fat_file_write_time_and_date(fat_fs_info_t *fs_info,
                             fat_file_fd_t *fat_fd);

int
fat_file_update(fat_fs_info_t *fs_info,
                fat_file_fd_t *fat_fd);

#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* __DOSFS_FAT_FILE_H__ */