[f36a7bfc] | 1 | /* |
---|
| 2 | * fat.c |
---|
| 3 | * |
---|
| 4 | * Low-level operations on a volume with FAT filesystem |
---|
| 5 | * |
---|
| 6 | * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia |
---|
| 7 | * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru> |
---|
| 8 | */ |
---|
| 9 | |
---|
[ffc144e] | 10 | #if HAVE_CONFIG_H |
---|
| 11 | #include "config.h" |
---|
| 12 | #endif |
---|
| 13 | |
---|
[f36a7bfc] | 14 | #include <sys/types.h> |
---|
| 15 | #include <sys/stat.h> |
---|
| 16 | #include <fcntl.h> |
---|
| 17 | #include <unistd.h> |
---|
| 18 | #include <errno.h> |
---|
| 19 | #include <stdlib.h> |
---|
| 20 | |
---|
| 21 | #include <rtems/libio_.h> |
---|
| 22 | |
---|
| 23 | #include "fat.h" |
---|
[d32359a7] | 24 | #include "fat_fat_operations.h" |
---|
[f36a7bfc] | 25 | |
---|
[3899a537] | 26 | int |
---|
| 27 | fat_buf_access(fat_fs_info_t *fs_info, uint32_t blk, int op_type, |
---|
| 28 | rtems_bdbuf_buffer **buf) |
---|
| 29 | { |
---|
| 30 | rtems_status_code sc = RTEMS_SUCCESSFUL; |
---|
| 31 | uint8_t i; |
---|
[0a896eb] | 32 | bool sec_of_fat; |
---|
[3899a537] | 33 | |
---|
| 34 | |
---|
| 35 | if (fs_info->c.state == FAT_CACHE_EMPTY) |
---|
| 36 | { |
---|
| 37 | if (op_type == FAT_OP_TYPE_READ) |
---|
[796967c] | 38 | sc = rtems_bdbuf_read(fs_info->vol.dd, blk, &fs_info->c.buf); |
---|
[3899a537] | 39 | else |
---|
[796967c] | 40 | sc = rtems_bdbuf_get(fs_info->vol.dd, blk, &fs_info->c.buf); |
---|
[3899a537] | 41 | if (sc != RTEMS_SUCCESSFUL) |
---|
| 42 | rtems_set_errno_and_return_minus_one(EIO); |
---|
| 43 | fs_info->c.blk_num = blk; |
---|
| 44 | fs_info->c.modified = 0; |
---|
| 45 | fs_info->c.state = FAT_CACHE_ACTUAL; |
---|
| 46 | } |
---|
| 47 | |
---|
| 48 | sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) && |
---|
| 49 | (fs_info->c.blk_num < fs_info->vol.rdir_loc)); |
---|
| 50 | |
---|
| 51 | if (fs_info->c.blk_num != blk) |
---|
| 52 | { |
---|
| 53 | if (fs_info->c.modified) |
---|
| 54 | { |
---|
| 55 | if (sec_of_fat && !fs_info->vol.mirror) |
---|
| 56 | memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, |
---|
| 57 | fs_info->vol.bps); |
---|
| 58 | |
---|
| 59 | sc = rtems_bdbuf_release_modified(fs_info->c.buf); |
---|
| 60 | fs_info->c.state = FAT_CACHE_EMPTY; |
---|
| 61 | fs_info->c.modified = 0; |
---|
| 62 | if (sc != RTEMS_SUCCESSFUL) |
---|
| 63 | rtems_set_errno_and_return_minus_one(EIO); |
---|
| 64 | |
---|
| 65 | if (sec_of_fat && !fs_info->vol.mirror) |
---|
| 66 | { |
---|
| 67 | rtems_bdbuf_buffer *b; |
---|
| 68 | |
---|
| 69 | for (i = 1; i < fs_info->vol.fats; i++) |
---|
| 70 | { |
---|
[796967c] | 71 | sc = rtems_bdbuf_get(fs_info->vol.dd, |
---|
[3899a537] | 72 | fs_info->c.blk_num + |
---|
| 73 | fs_info->vol.fat_length * i, |
---|
| 74 | &b); |
---|
| 75 | if ( sc != RTEMS_SUCCESSFUL) |
---|
| 76 | rtems_set_errno_and_return_minus_one(ENOMEM); |
---|
| 77 | memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps); |
---|
| 78 | sc = rtems_bdbuf_release_modified(b); |
---|
| 79 | if ( sc != RTEMS_SUCCESSFUL) |
---|
| 80 | rtems_set_errno_and_return_minus_one(ENOMEM); |
---|
| 81 | } |
---|
| 82 | } |
---|
| 83 | } |
---|
| 84 | else |
---|
| 85 | { |
---|
| 86 | sc = rtems_bdbuf_release(fs_info->c.buf); |
---|
| 87 | fs_info->c.state = FAT_CACHE_EMPTY; |
---|
| 88 | if (sc != RTEMS_SUCCESSFUL) |
---|
| 89 | rtems_set_errno_and_return_minus_one(EIO); |
---|
| 90 | |
---|
| 91 | } |
---|
| 92 | if (op_type == FAT_OP_TYPE_READ) |
---|
[796967c] | 93 | sc = rtems_bdbuf_read(fs_info->vol.dd, blk, &fs_info->c.buf); |
---|
[3899a537] | 94 | else |
---|
[796967c] | 95 | sc = rtems_bdbuf_get(fs_info->vol.dd, blk, &fs_info->c.buf); |
---|
[3899a537] | 96 | if (sc != RTEMS_SUCCESSFUL) |
---|
| 97 | rtems_set_errno_and_return_minus_one(EIO); |
---|
| 98 | fs_info->c.blk_num = blk; |
---|
| 99 | fs_info->c.state = FAT_CACHE_ACTUAL; |
---|
| 100 | } |
---|
| 101 | *buf = fs_info->c.buf; |
---|
| 102 | return RC_OK; |
---|
| 103 | } |
---|
| 104 | |
---|
| 105 | int |
---|
| 106 | fat_buf_release(fat_fs_info_t *fs_info) |
---|
| 107 | { |
---|
| 108 | rtems_status_code sc = RTEMS_SUCCESSFUL; |
---|
| 109 | uint8_t i; |
---|
[0a896eb] | 110 | bool sec_of_fat; |
---|
[3899a537] | 111 | |
---|
| 112 | if (fs_info->c.state == FAT_CACHE_EMPTY) |
---|
| 113 | return RC_OK; |
---|
| 114 | |
---|
| 115 | sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) && |
---|
| 116 | (fs_info->c.blk_num < fs_info->vol.rdir_loc)); |
---|
| 117 | |
---|
| 118 | if (fs_info->c.modified) |
---|
| 119 | { |
---|
| 120 | if (sec_of_fat && !fs_info->vol.mirror) |
---|
| 121 | memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, fs_info->vol.bps); |
---|
| 122 | |
---|
| 123 | sc = rtems_bdbuf_release_modified(fs_info->c.buf); |
---|
| 124 | if (sc != RTEMS_SUCCESSFUL) |
---|
| 125 | rtems_set_errno_and_return_minus_one(EIO); |
---|
| 126 | fs_info->c.modified = 0; |
---|
| 127 | |
---|
| 128 | if (sec_of_fat && !fs_info->vol.mirror) |
---|
| 129 | { |
---|
| 130 | rtems_bdbuf_buffer *b; |
---|
| 131 | |
---|
| 132 | for (i = 1; i < fs_info->vol.fats; i++) |
---|
| 133 | { |
---|
[796967c] | 134 | sc = rtems_bdbuf_get(fs_info->vol.dd, |
---|
[3899a537] | 135 | fs_info->c.blk_num + |
---|
| 136 | fs_info->vol.fat_length * i, |
---|
| 137 | &b); |
---|
| 138 | if ( sc != RTEMS_SUCCESSFUL) |
---|
| 139 | rtems_set_errno_and_return_minus_one(ENOMEM); |
---|
| 140 | memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps); |
---|
| 141 | sc = rtems_bdbuf_release_modified(b); |
---|
| 142 | if ( sc != RTEMS_SUCCESSFUL) |
---|
| 143 | rtems_set_errno_and_return_minus_one(ENOMEM); |
---|
| 144 | } |
---|
| 145 | } |
---|
| 146 | } |
---|
| 147 | else |
---|
| 148 | { |
---|
| 149 | sc = rtems_bdbuf_release(fs_info->c.buf); |
---|
| 150 | if (sc != RTEMS_SUCCESSFUL) |
---|
| 151 | rtems_set_errno_and_return_minus_one(EIO); |
---|
| 152 | } |
---|
| 153 | fs_info->c.state = FAT_CACHE_EMPTY; |
---|
| 154 | return RC_OK; |
---|
| 155 | } |
---|
| 156 | |
---|
[f36a7bfc] | 157 | /* _fat_block_read -- |
---|
| 158 | * This function reads 'count' bytes from device filesystem is mounted on, |
---|
[a5305f6b] | 159 | * starts at 'start+offset' position where 'start' computed in sectors |
---|
| 160 | * and 'offset' is offset inside sector (reading may cross sectors |
---|
[f36a7bfc] | 161 | * boundary; in this case assumed we want to read sequential sector(s)) |
---|
| 162 | * |
---|
| 163 | * PARAMETERS: |
---|
[c65afce4] | 164 | * fs_info - FS info |
---|
[f36a7bfc] | 165 | * start - sector num to start read from |
---|
| 166 | * offset - offset inside sector 'start' |
---|
| 167 | * count - count of bytes to read |
---|
| 168 | * buff - buffer provided by user |
---|
| 169 | * |
---|
| 170 | * RETURNS: |
---|
| 171 | * bytes read on success, or -1 if error occured |
---|
| 172 | * and errno set appropriately |
---|
| 173 | */ |
---|
| 174 | ssize_t |
---|
| 175 | _fat_block_read( |
---|
[c65afce4] | 176 | fat_fs_info_t *fs_info, |
---|
[a5305f6b] | 177 | uint32_t start, |
---|
[f91bbe64] | 178 | uint32_t offset, |
---|
[a5305f6b] | 179 | uint32_t count, |
---|
[f36a7bfc] | 180 | void *buff |
---|
| 181 | ) |
---|
| 182 | { |
---|
| 183 | int rc = RC_OK; |
---|
| 184 | ssize_t cmpltd = 0; |
---|
[f91bbe64] | 185 | uint32_t blk = start; |
---|
| 186 | uint32_t ofs = offset; |
---|
[3899a537] | 187 | rtems_bdbuf_buffer *block = NULL; |
---|
[f91bbe64] | 188 | uint32_t c = 0; |
---|
[a5305f6b] | 189 | |
---|
[f36a7bfc] | 190 | while (count > 0) |
---|
| 191 | { |
---|
| 192 | rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block); |
---|
| 193 | if (rc != RC_OK) |
---|
[08c09e24] | 194 | return -1; |
---|
| 195 | |
---|
[f36a7bfc] | 196 | c = MIN(count, (fs_info->vol.bps - ofs)); |
---|
| 197 | memcpy((buff + cmpltd), (block->buffer + ofs), c); |
---|
| 198 | |
---|
| 199 | count -= c; |
---|
| 200 | cmpltd += c; |
---|
| 201 | blk++; |
---|
| 202 | ofs = 0; |
---|
| 203 | } |
---|
| 204 | return cmpltd; |
---|
| 205 | } |
---|
| 206 | |
---|
| 207 | /* _fat_block_write -- |
---|
[a5305f6b] | 208 | * This function write 'count' bytes to device filesystem is mounted on, |
---|
| 209 | * starts at 'start+offset' position where 'start' computed in sectors |
---|
| 210 | * and 'offset' is offset inside sector (writing may cross sectors |
---|
[f36a7bfc] | 211 | * boundary; in this case assumed we want to write sequential sector(s)) |
---|
| 212 | * |
---|
| 213 | * PARAMETERS: |
---|
[c65afce4] | 214 | * fs_info - FS info |
---|
[f36a7bfc] | 215 | * start - sector num to start read from |
---|
| 216 | * offset - offset inside sector 'start' |
---|
| 217 | * count - count of bytes to write |
---|
| 218 | * buff - buffer provided by user |
---|
| 219 | * |
---|
| 220 | * RETURNS: |
---|
| 221 | * bytes written on success, or -1 if error occured |
---|
| 222 | * and errno set appropriately |
---|
| 223 | */ |
---|
| 224 | ssize_t |
---|
| 225 | _fat_block_write( |
---|
[c65afce4] | 226 | fat_fs_info_t *fs_info, |
---|
[a5305f6b] | 227 | uint32_t start, |
---|
[f91bbe64] | 228 | uint32_t offset, |
---|
[a5305f6b] | 229 | uint32_t count, |
---|
[f36a7bfc] | 230 | const void *buff) |
---|
| 231 | { |
---|
[3899a537] | 232 | int rc = RC_OK; |
---|
| 233 | ssize_t cmpltd = 0; |
---|
| 234 | uint32_t blk = start; |
---|
| 235 | uint32_t ofs = offset; |
---|
| 236 | rtems_bdbuf_buffer *block = NULL; |
---|
| 237 | uint32_t c = 0; |
---|
[a5305f6b] | 238 | |
---|
[f36a7bfc] | 239 | while(count > 0) |
---|
| 240 | { |
---|
| 241 | c = MIN(count, (fs_info->vol.bps - ofs)); |
---|
| 242 | |
---|
| 243 | if (c == fs_info->vol.bps) |
---|
| 244 | rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block); |
---|
| 245 | else |
---|
| 246 | rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block); |
---|
| 247 | if (rc != RC_OK) |
---|
[08c09e24] | 248 | return -1; |
---|
[a5305f6b] | 249 | |
---|
[f36a7bfc] | 250 | memcpy((block->buffer + ofs), (buff + cmpltd), c); |
---|
| 251 | |
---|
| 252 | fat_buf_mark_modified(fs_info); |
---|
| 253 | |
---|
| 254 | count -= c; |
---|
| 255 | cmpltd +=c; |
---|
| 256 | blk++; |
---|
| 257 | ofs = 0; |
---|
| 258 | } |
---|
| 259 | return cmpltd; |
---|
| 260 | } |
---|
| 261 | |
---|
[3d0c96c7] | 262 | int |
---|
| 263 | _fat_block_zero( |
---|
[c65afce4] | 264 | fat_fs_info_t *fs_info, |
---|
[3d0c96c7] | 265 | uint32_t start, |
---|
| 266 | uint32_t offset, |
---|
| 267 | uint32_t count) |
---|
| 268 | { |
---|
| 269 | int rc = RC_OK; |
---|
| 270 | uint32_t blk = start; |
---|
| 271 | uint32_t ofs = offset; |
---|
| 272 | rtems_bdbuf_buffer *block = NULL; |
---|
| 273 | uint32_t c = 0; |
---|
| 274 | |
---|
| 275 | while(count > 0) |
---|
| 276 | { |
---|
| 277 | c = MIN(count, (fs_info->vol.bps - ofs)); |
---|
| 278 | |
---|
| 279 | if (c == fs_info->vol.bps) |
---|
| 280 | rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block); |
---|
| 281 | else |
---|
| 282 | rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block); |
---|
| 283 | if (rc != RC_OK) |
---|
| 284 | return -1; |
---|
| 285 | |
---|
| 286 | memset((block->buffer + ofs), 0, c); |
---|
| 287 | |
---|
| 288 | fat_buf_mark_modified(fs_info); |
---|
| 289 | |
---|
| 290 | count -= c; |
---|
| 291 | blk++; |
---|
| 292 | ofs = 0; |
---|
| 293 | } |
---|
| 294 | return 0; |
---|
| 295 | } |
---|
| 296 | |
---|
[eb649786] | 297 | /* _fat_block_release -- |
---|
| 298 | * This function works around the hack that hold a bdbuf and does |
---|
| 299 | * not release it. |
---|
| 300 | * |
---|
| 301 | * PARAMETERS: |
---|
[c65afce4] | 302 | * fs_info - FS info |
---|
[eb649786] | 303 | * |
---|
| 304 | * RETURNS: |
---|
| 305 | * 0 on success, or -1 if error occured and errno set appropriately |
---|
| 306 | */ |
---|
| 307 | int |
---|
[c65afce4] | 308 | _fat_block_release(fat_fs_info_t *fs_info) |
---|
[eb649786] | 309 | { |
---|
| 310 | return fat_buf_release(fs_info); |
---|
| 311 | } |
---|
[0a7278e] | 312 | |
---|
[f36a7bfc] | 313 | /* fat_cluster_read -- |
---|
| 314 | * wrapper for reading a whole cluster at once |
---|
| 315 | * |
---|
| 316 | * PARAMETERS: |
---|
[c65afce4] | 317 | * fs_info - FS info |
---|
[f36a7bfc] | 318 | * cln - number of cluster to read |
---|
| 319 | * buff - buffer provided by user |
---|
| 320 | * |
---|
| 321 | * RETURNS: |
---|
| 322 | * bytes read on success, or -1 if error occured |
---|
| 323 | * and errno set appropriately |
---|
| 324 | */ |
---|
[a5305f6b] | 325 | ssize_t |
---|
[f36a7bfc] | 326 | fat_cluster_read( |
---|
[c65afce4] | 327 | fat_fs_info_t *fs_info, |
---|
[f91bbe64] | 328 | uint32_t cln, |
---|
[f36a7bfc] | 329 | void *buff |
---|
| 330 | ) |
---|
| 331 | { |
---|
[a5305f6b] | 332 | uint32_t fsec = 0; |
---|
[f36a7bfc] | 333 | |
---|
[c65afce4] | 334 | fsec = fat_cluster_num_to_sector_num(fs_info, cln); |
---|
[a5305f6b] | 335 | |
---|
[c65afce4] | 336 | return _fat_block_read(fs_info, fsec, 0, |
---|
[a5305f6b] | 337 | fs_info->vol.spc << fs_info->vol.sec_log2, buff); |
---|
| 338 | } |
---|
[f36a7bfc] | 339 | |
---|
| 340 | /* fat_cluster_write -- |
---|
| 341 | * wrapper for writting a whole cluster at once |
---|
| 342 | * |
---|
| 343 | * PARAMETERS: |
---|
[c65afce4] | 344 | * fs_info - FS info |
---|
[f36a7bfc] | 345 | * cln - number of cluster to write |
---|
| 346 | * buff - buffer provided by user |
---|
| 347 | * |
---|
| 348 | * RETURNS: |
---|
| 349 | * bytes written on success, or -1 if error occured |
---|
| 350 | * and errno set appropriately |
---|
| 351 | */ |
---|
[a5305f6b] | 352 | ssize_t |
---|
[f36a7bfc] | 353 | fat_cluster_write( |
---|
[c65afce4] | 354 | fat_fs_info_t *fs_info, |
---|
[f91bbe64] | 355 | uint32_t cln, |
---|
[f36a7bfc] | 356 | const void *buff |
---|
| 357 | ) |
---|
| 358 | { |
---|
[f91bbe64] | 359 | uint32_t fsec = 0; |
---|
[a5305f6b] | 360 | |
---|
[c65afce4] | 361 | fsec = fat_cluster_num_to_sector_num(fs_info, cln); |
---|
[a5305f6b] | 362 | |
---|
[c65afce4] | 363 | return _fat_block_write(fs_info, fsec, 0, |
---|
[a5305f6b] | 364 | fs_info->vol.spc << fs_info->vol.sec_log2, buff); |
---|
| 365 | } |
---|
[f36a7bfc] | 366 | |
---|
| 367 | /* fat_init_volume_info -- |
---|
| 368 | * Get inforamtion about volume on which filesystem is mounted on |
---|
| 369 | * |
---|
| 370 | * PARAMETERS: |
---|
[c65afce4] | 371 | * fs_info - FS info |
---|
[f36a7bfc] | 372 | * |
---|
| 373 | * RETURNS: |
---|
| 374 | * RC_OK on success, or -1 if error occured |
---|
| 375 | * and errno set appropriately |
---|
| 376 | */ |
---|
| 377 | int |
---|
[c65afce4] | 378 | fat_init_volume_info(fat_fs_info_t *fs_info, const char *device) |
---|
[f36a7bfc] | 379 | { |
---|
[bf95ccb5] | 380 | rtems_status_code sc = RTEMS_SUCCESSFUL; |
---|
[f36a7bfc] | 381 | int rc = RC_OK; |
---|
| 382 | register fat_vol_t *vol = &fs_info->vol; |
---|
[f91bbe64] | 383 | uint32_t data_secs = 0; |
---|
[f36a7bfc] | 384 | char boot_rec[FAT_MAX_BPB_SIZE]; |
---|
| 385 | char fs_info_sector[FAT_USEFUL_INFO_SIZE]; |
---|
| 386 | ssize_t ret = 0; |
---|
| 387 | struct stat stat_buf; |
---|
| 388 | int i = 0; |
---|
[3899a537] | 389 | rtems_bdbuf_buffer *block = NULL; |
---|
[f36a7bfc] | 390 | |
---|
[c65afce4] | 391 | vol->fd = open(device, O_RDWR); |
---|
[796967c] | 392 | if (vol->fd < 0) |
---|
| 393 | { |
---|
| 394 | rtems_set_errno_and_return_minus_one(ENXIO); |
---|
| 395 | } |
---|
| 396 | |
---|
| 397 | rc = fstat(vol->fd, &stat_buf); |
---|
| 398 | if (rc != 0) |
---|
| 399 | { |
---|
| 400 | close(vol->fd); |
---|
| 401 | rtems_set_errno_and_return_minus_one(ENXIO); |
---|
| 402 | } |
---|
[f36a7bfc] | 403 | |
---|
[5268642] | 404 | /* Must be a block device. */ |
---|
| 405 | if (!S_ISBLK(stat_buf.st_mode)) |
---|
[796967c] | 406 | { |
---|
| 407 | close(vol->fd); |
---|
| 408 | rtems_set_errno_and_return_minus_one(ENXIO); |
---|
| 409 | } |
---|
[f36a7bfc] | 410 | |
---|
[3899a537] | 411 | /* check that device is registred as block device and lock it */ |
---|
[796967c] | 412 | rc = rtems_disk_fd_get_disk_device(vol->fd, &vol->dd); |
---|
| 413 | if (rc != 0) { |
---|
| 414 | close(vol->fd); |
---|
| 415 | rtems_set_errno_and_return_minus_one(ENXIO); |
---|
| 416 | } |
---|
[f36a7bfc] | 417 | |
---|
[bf95ccb5] | 418 | /* Read boot record */ |
---|
| 419 | /* FIXME: Asserts FAT_MAX_BPB_SIZE < bdbuf block size */ |
---|
[796967c] | 420 | sc = rtems_bdbuf_read( vol->dd, 0, &block); |
---|
[bf95ccb5] | 421 | if (sc != RTEMS_SUCCESSFUL) |
---|
[f36a7bfc] | 422 | { |
---|
[796967c] | 423 | close(vol->fd); |
---|
[3899a537] | 424 | rtems_set_errno_and_return_minus_one( EIO); |
---|
[a5305f6b] | 425 | } |
---|
| 426 | |
---|
[bf95ccb5] | 427 | memcpy( boot_rec, block->buffer, FAT_MAX_BPB_SIZE); |
---|
| 428 | |
---|
| 429 | sc = rtems_bdbuf_release( block); |
---|
| 430 | if (sc != RTEMS_SUCCESSFUL) |
---|
[f36a7bfc] | 431 | { |
---|
[796967c] | 432 | close(vol->fd); |
---|
[3899a537] | 433 | rtems_set_errno_and_return_minus_one( EIO ); |
---|
[f36a7bfc] | 434 | } |
---|
| 435 | |
---|
[bf95ccb5] | 436 | /* Evaluate boot record */ |
---|
[c36f885a] | 437 | vol->bps = FAT_GET_BR_BYTES_PER_SECTOR(boot_rec); |
---|
[0a7278e] | 438 | |
---|
| 439 | if ( (vol->bps != 512) && |
---|
| 440 | (vol->bps != 1024) && |
---|
[f36a7bfc] | 441 | (vol->bps != 2048) && |
---|
| 442 | (vol->bps != 4096)) |
---|
[a5305f6b] | 443 | { |
---|
[796967c] | 444 | close(vol->fd); |
---|
[3899a537] | 445 | rtems_set_errno_and_return_minus_one( EINVAL ); |
---|
[a5305f6b] | 446 | } |
---|
[f36a7bfc] | 447 | |
---|
[a5305f6b] | 448 | for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0; |
---|
[f36a7bfc] | 449 | i >>= 1, vol->sec_mul++); |
---|
[a5305f6b] | 450 | for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0; |
---|
[f36a7bfc] | 451 | i >>= 1, vol->sec_log2++); |
---|
| 452 | |
---|
[c36f885a] | 453 | vol->spc = FAT_GET_BR_SECTORS_PER_CLUSTER(boot_rec); |
---|
[c151cfc3] | 454 | /* |
---|
| 455 | * "sectors per cluster" of zero is invalid |
---|
| 456 | * (and would hang the following loop) |
---|
| 457 | */ |
---|
| 458 | if (vol->spc == 0) |
---|
| 459 | { |
---|
[796967c] | 460 | close(vol->fd); |
---|
[3899a537] | 461 | rtems_set_errno_and_return_minus_one(EINVAL); |
---|
[a5305f6b] | 462 | } |
---|
[c151cfc3] | 463 | |
---|
[a5305f6b] | 464 | for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0; |
---|
[f36a7bfc] | 465 | i >>= 1, vol->spc_log2++); |
---|
[a5305f6b] | 466 | |
---|
| 467 | /* |
---|
[3b44f153] | 468 | * "bytes per cluster" value greater than 32K is invalid |
---|
[f36a7bfc] | 469 | */ |
---|
| 470 | if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT) |
---|
| 471 | { |
---|
[796967c] | 472 | close(vol->fd); |
---|
[3899a537] | 473 | rtems_set_errno_and_return_minus_one(EINVAL); |
---|
[a5305f6b] | 474 | } |
---|
[f36a7bfc] | 475 | |
---|
[a5305f6b] | 476 | for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0; |
---|
[f36a7bfc] | 477 | i >>= 1, vol->bpc_log2++); |
---|
| 478 | |
---|
[c36f885a] | 479 | vol->fats = FAT_GET_BR_FAT_NUM(boot_rec); |
---|
| 480 | vol->fat_loc = FAT_GET_BR_RESERVED_SECTORS_NUM(boot_rec); |
---|
[a5305f6b] | 481 | |
---|
[c36f885a] | 482 | vol->rdir_entrs = FAT_GET_BR_FILES_PER_ROOT_DIR(boot_rec); |
---|
[0a7278e] | 483 | |
---|
[f36a7bfc] | 484 | /* calculate the count of sectors occupied by the root directory */ |
---|
| 485 | vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) / |
---|
| 486 | vol->bps; |
---|
| 487 | |
---|
| 488 | vol->rdir_size = vol->rdir_secs << vol->sec_log2; |
---|
| 489 | |
---|
[c36f885a] | 490 | if ( (FAT_GET_BR_SECTORS_PER_FAT(boot_rec)) != 0) |
---|
| 491 | vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT(boot_rec); |
---|
[f36a7bfc] | 492 | else |
---|
[c36f885a] | 493 | vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT32(boot_rec); |
---|
[0a7278e] | 494 | |
---|
| 495 | vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length + |
---|
[f36a7bfc] | 496 | vol->rdir_secs; |
---|
| 497 | |
---|
| 498 | /* for FAT12/16 root dir starts at(sector) */ |
---|
| 499 | vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length; |
---|
[0a7278e] | 500 | |
---|
[c36f885a] | 501 | if ( (FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0) |
---|
| 502 | vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec); |
---|
[f36a7bfc] | 503 | else |
---|
[c36f885a] | 504 | vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM32(boot_rec); |
---|
[0a7278e] | 505 | |
---|
[f36a7bfc] | 506 | data_secs = vol->tot_secs - vol->data_fsec; |
---|
[a5305f6b] | 507 | |
---|
[f36a7bfc] | 508 | vol->data_cls = data_secs / vol->spc; |
---|
| 509 | |
---|
| 510 | /* determine FAT type at least */ |
---|
| 511 | if ( vol->data_cls < FAT_FAT12_MAX_CLN) |
---|
| 512 | { |
---|
| 513 | vol->type = FAT_FAT12; |
---|
| 514 | vol->mask = FAT_FAT12_MASK; |
---|
| 515 | vol->eoc_val = FAT_FAT12_EOC; |
---|
| 516 | } |
---|
[a5305f6b] | 517 | else |
---|
[f36a7bfc] | 518 | { |
---|
| 519 | if ( vol->data_cls < FAT_FAT16_MAX_CLN) |
---|
| 520 | { |
---|
| 521 | vol->type = FAT_FAT16; |
---|
| 522 | vol->mask = FAT_FAT16_MASK; |
---|
| 523 | vol->eoc_val = FAT_FAT16_EOC; |
---|
| 524 | } |
---|
| 525 | else |
---|
| 526 | { |
---|
| 527 | vol->type = FAT_FAT32; |
---|
| 528 | vol->mask = FAT_FAT32_MASK; |
---|
| 529 | vol->eoc_val = FAT_FAT32_EOC; |
---|
| 530 | } |
---|
| 531 | } |
---|
[a5305f6b] | 532 | |
---|
[f36a7bfc] | 533 | if (vol->type == FAT_FAT32) |
---|
| 534 | { |
---|
[c36f885a] | 535 | vol->rdir_cl = FAT_GET_BR_FAT32_ROOT_CLUSTER(boot_rec); |
---|
[0a7278e] | 536 | |
---|
[c36f885a] | 537 | vol->mirror = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR; |
---|
[f36a7bfc] | 538 | if (vol->mirror) |
---|
[c36f885a] | 539 | vol->afat = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM; |
---|
[f36a7bfc] | 540 | else |
---|
[a5305f6b] | 541 | vol->afat = 0; |
---|
[f36a7bfc] | 542 | |
---|
[c36f885a] | 543 | vol->info_sec = FAT_GET_BR_FAT32_FS_INFO_SECTOR(boot_rec); |
---|
[f36a7bfc] | 544 | if( vol->info_sec == 0 ) |
---|
[a5305f6b] | 545 | { |
---|
[796967c] | 546 | close(vol->fd); |
---|
[3899a537] | 547 | rtems_set_errno_and_return_minus_one( EINVAL ); |
---|
[a5305f6b] | 548 | } |
---|
| 549 | else |
---|
[f36a7bfc] | 550 | { |
---|
[c65afce4] | 551 | ret = _fat_block_read(fs_info, vol->info_sec , 0, |
---|
[f36a7bfc] | 552 | FAT_FSI_LEADSIG_SIZE, fs_info_sector); |
---|
| 553 | if ( ret < 0 ) |
---|
| 554 | { |
---|
[796967c] | 555 | close(vol->fd); |
---|
[f36a7bfc] | 556 | return -1; |
---|
[0a7278e] | 557 | } |
---|
| 558 | |
---|
| 559 | if (FAT_GET_FSINFO_LEAD_SIGNATURE(fs_info_sector) != |
---|
[f36a7bfc] | 560 | FAT_FSINFO_LEAD_SIGNATURE_VALUE) |
---|
[a5305f6b] | 561 | { |
---|
[c65afce4] | 562 | _fat_block_release(fs_info); |
---|
[796967c] | 563 | close(vol->fd); |
---|
[3899a537] | 564 | rtems_set_errno_and_return_minus_one( EINVAL ); |
---|
[a5305f6b] | 565 | } |
---|
[f36a7bfc] | 566 | else |
---|
| 567 | { |
---|
[c65afce4] | 568 | ret = _fat_block_read(fs_info, vol->info_sec , FAT_FSI_INFO, |
---|
[f36a7bfc] | 569 | FAT_USEFUL_INFO_SIZE, fs_info_sector); |
---|
| 570 | if ( ret < 0 ) |
---|
| 571 | { |
---|
[c65afce4] | 572 | _fat_block_release(fs_info); |
---|
[796967c] | 573 | close(vol->fd); |
---|
[f36a7bfc] | 574 | return -1; |
---|
[0a7278e] | 575 | } |
---|
| 576 | |
---|
[c36f885a] | 577 | vol->free_cls = FAT_GET_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector); |
---|
| 578 | vol->next_cl = FAT_GET_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector); |
---|
[8863338] | 579 | rc = fat_fat32_update_fsinfo_sector(fs_info, FAT_UNDEFINED_VALUE, |
---|
| 580 | FAT_UNDEFINED_VALUE); |
---|
[f36a7bfc] | 581 | if ( rc != RC_OK ) |
---|
| 582 | { |
---|
[c65afce4] | 583 | _fat_block_release(fs_info); |
---|
[796967c] | 584 | close(vol->fd); |
---|
[a5305f6b] | 585 | return rc; |
---|
| 586 | } |
---|
[f36a7bfc] | 587 | } |
---|
| 588 | } |
---|
| 589 | } |
---|
| 590 | else |
---|
| 591 | { |
---|
| 592 | vol->rdir_cl = 0; |
---|
| 593 | vol->mirror = 0; |
---|
| 594 | vol->afat = 0; |
---|
[8863338] | 595 | vol->free_cls = FAT_UNDEFINED_VALUE; |
---|
| 596 | vol->next_cl = FAT_UNDEFINED_VALUE; |
---|
[f36a7bfc] | 597 | } |
---|
[eb649786] | 598 | |
---|
[c65afce4] | 599 | _fat_block_release(fs_info); |
---|
[eb649786] | 600 | |
---|
[f36a7bfc] | 601 | vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat; |
---|
| 602 | |
---|
| 603 | /* set up collection of fat-files fd */ |
---|
[3899a537] | 604 | fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(rtems_chain_control)); |
---|
[a5305f6b] | 605 | if ( fs_info->vhash == NULL ) |
---|
[f36a7bfc] | 606 | { |
---|
[796967c] | 607 | close(vol->fd); |
---|
[3899a537] | 608 | rtems_set_errno_and_return_minus_one( ENOMEM ); |
---|
[a5305f6b] | 609 | } |
---|
[f36a7bfc] | 610 | |
---|
| 611 | for (i = 0; i < FAT_HASH_SIZE; i++) |
---|
[3899a537] | 612 | rtems_chain_initialize_empty(fs_info->vhash + i); |
---|
[f36a7bfc] | 613 | |
---|
[3899a537] | 614 | fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(rtems_chain_control)); |
---|
[a5305f6b] | 615 | if ( fs_info->rhash == NULL ) |
---|
[f36a7bfc] | 616 | { |
---|
[796967c] | 617 | close(vol->fd); |
---|
[f36a7bfc] | 618 | free(fs_info->vhash); |
---|
[3899a537] | 619 | rtems_set_errno_and_return_minus_one( ENOMEM ); |
---|
[f36a7bfc] | 620 | } |
---|
| 621 | for (i = 0; i < FAT_HASH_SIZE; i++) |
---|
[3899a537] | 622 | rtems_chain_initialize_empty(fs_info->rhash + i); |
---|
[a5305f6b] | 623 | |
---|
[f36a7bfc] | 624 | fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE; |
---|
| 625 | fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4; |
---|
| 626 | fs_info->index = 0; |
---|
| 627 | fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char)); |
---|
| 628 | if ( fs_info->uino == NULL ) |
---|
| 629 | { |
---|
[796967c] | 630 | close(vol->fd); |
---|
[f36a7bfc] | 631 | free(fs_info->vhash); |
---|
| 632 | free(fs_info->rhash); |
---|
[3899a537] | 633 | rtems_set_errno_and_return_minus_one( ENOMEM ); |
---|
[f36a7bfc] | 634 | } |
---|
[0247c6c] | 635 | fs_info->sec_buf = (uint8_t *)calloc(vol->bps, sizeof(uint8_t)); |
---|
[f36a7bfc] | 636 | if (fs_info->sec_buf == NULL) |
---|
| 637 | { |
---|
[796967c] | 638 | close(vol->fd); |
---|
[f36a7bfc] | 639 | free(fs_info->vhash); |
---|
| 640 | free(fs_info->rhash); |
---|
| 641 | free(fs_info->uino); |
---|
[3899a537] | 642 | rtems_set_errno_and_return_minus_one( ENOMEM ); |
---|
[f36a7bfc] | 643 | } |
---|
[a5305f6b] | 644 | |
---|
| 645 | return RC_OK; |
---|
[f36a7bfc] | 646 | } |
---|
| 647 | |
---|
| 648 | /* fat_shutdown_drive -- |
---|
[a5305f6b] | 649 | * Free all allocated resources and synchronize all necessary data |
---|
[f36a7bfc] | 650 | * |
---|
| 651 | * PARAMETERS: |
---|
[c65afce4] | 652 | * fs_info - FS info |
---|
[f36a7bfc] | 653 | * |
---|
| 654 | * RETURNS: |
---|
| 655 | * RC_OK on success, or -1 if error occured |
---|
| 656 | * and errno set appropriately |
---|
| 657 | */ |
---|
| 658 | int |
---|
[c65afce4] | 659 | fat_shutdown_drive(fat_fs_info_t *fs_info) |
---|
[f36a7bfc] | 660 | { |
---|
| 661 | int rc = RC_OK; |
---|
| 662 | int i = 0; |
---|
| 663 | |
---|
| 664 | if (fs_info->vol.type & FAT_FAT32) |
---|
| 665 | { |
---|
[c65afce4] | 666 | rc = fat_fat32_update_fsinfo_sector(fs_info, fs_info->vol.free_cls, |
---|
[f36a7bfc] | 667 | fs_info->vol.next_cl); |
---|
| 668 | if ( rc != RC_OK ) |
---|
| 669 | rc = -1; |
---|
[a5305f6b] | 670 | } |
---|
[f36a7bfc] | 671 | |
---|
| 672 | fat_buf_release(fs_info); |
---|
[a5305f6b] | 673 | |
---|
[796967c] | 674 | if (rtems_bdbuf_syncdev(fs_info->vol.dd) != RTEMS_SUCCESSFUL) |
---|
[f36a7bfc] | 675 | rc = -1; |
---|
| 676 | |
---|
| 677 | for (i = 0; i < FAT_HASH_SIZE; i++) |
---|
| 678 | { |
---|
[3899a537] | 679 | rtems_chain_node *node = NULL; |
---|
| 680 | rtems_chain_control *the_chain = fs_info->vhash + i; |
---|
[a5305f6b] | 681 | |
---|
[3899a537] | 682 | while ( (node = rtems_chain_get(the_chain)) != NULL ) |
---|
[f36a7bfc] | 683 | free(node); |
---|
[a5305f6b] | 684 | } |
---|
[f36a7bfc] | 685 | |
---|
| 686 | for (i = 0; i < FAT_HASH_SIZE; i++) |
---|
| 687 | { |
---|
[3899a537] | 688 | rtems_chain_node *node = NULL; |
---|
| 689 | rtems_chain_control *the_chain = fs_info->rhash + i; |
---|
[f36a7bfc] | 690 | |
---|
[3899a537] | 691 | while ( (node = rtems_chain_get(the_chain)) != NULL ) |
---|
[f36a7bfc] | 692 | free(node); |
---|
[a5305f6b] | 693 | } |
---|
[f36a7bfc] | 694 | |
---|
| 695 | free(fs_info->vhash); |
---|
[a5305f6b] | 696 | free(fs_info->rhash); |
---|
[f36a7bfc] | 697 | |
---|
| 698 | free(fs_info->uino); |
---|
| 699 | free(fs_info->sec_buf); |
---|
[796967c] | 700 | close(fs_info->vol.fd); |
---|
[f36a7bfc] | 701 | |
---|
| 702 | if (rc) |
---|
| 703 | errno = EIO; |
---|
| 704 | return rc; |
---|
| 705 | } |
---|
| 706 | |
---|
| 707 | /* fat_init_clusters_chain -- |
---|
| 708 | * Zeroing contents of all clusters in the chain |
---|
| 709 | * |
---|
| 710 | * PARAMETERS: |
---|
[c65afce4] | 711 | * fs_info - FS info |
---|
[a5305f6b] | 712 | * start_cluster_num - num of first cluster in the chain |
---|
[f36a7bfc] | 713 | * |
---|
| 714 | * RETURNS: |
---|
| 715 | * RC_OK on success, or -1 if error occured |
---|
| 716 | * and errno set appropriately |
---|
| 717 | */ |
---|
| 718 | int |
---|
| 719 | fat_init_clusters_chain( |
---|
[c65afce4] | 720 | fat_fs_info_t *fs_info, |
---|
[f91bbe64] | 721 | uint32_t start_cln |
---|
[f36a7bfc] | 722 | ) |
---|
| 723 | { |
---|
| 724 | int rc = RC_OK; |
---|
| 725 | ssize_t ret = 0; |
---|
[f91bbe64] | 726 | uint32_t cur_cln = start_cln; |
---|
[f36a7bfc] | 727 | char *buf; |
---|
[a5305f6b] | 728 | |
---|
[f36a7bfc] | 729 | buf = calloc(fs_info->vol.bpc, sizeof(char)); |
---|
| 730 | if ( buf == NULL ) |
---|
[3899a537] | 731 | rtems_set_errno_and_return_minus_one( EIO ); |
---|
[f36a7bfc] | 732 | |
---|
[c151cfc3] | 733 | while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val) |
---|
[f36a7bfc] | 734 | { |
---|
[c65afce4] | 735 | ret = fat_cluster_write(fs_info, cur_cln, buf); |
---|
[f36a7bfc] | 736 | if ( ret == -1 ) |
---|
| 737 | { |
---|
| 738 | free(buf); |
---|
| 739 | return -1; |
---|
| 740 | } |
---|
| 741 | |
---|
[c65afce4] | 742 | rc = fat_get_fat_cluster(fs_info, cur_cln, &cur_cln); |
---|
[f36a7bfc] | 743 | if ( rc != RC_OK ) |
---|
| 744 | { |
---|
| 745 | free(buf); |
---|
| 746 | return rc; |
---|
| 747 | } |
---|
[a5305f6b] | 748 | |
---|
[f36a7bfc] | 749 | } |
---|
| 750 | free(buf); |
---|
| 751 | return rc; |
---|
[a5305f6b] | 752 | } |
---|
| 753 | |
---|
| 754 | #define FAT_UNIQ_INO_BASE 0x0FFFFF00 |
---|
[f36a7bfc] | 755 | |
---|
| 756 | #define FAT_UNIQ_INO_IS_BUSY(index, arr) \ |
---|
| 757 | (((arr)[((index)>>3)]>>((index) & (8-1))) & 0x01) |
---|
| 758 | |
---|
| 759 | #define FAT_SET_UNIQ_INO_BUSY(index, arr) \ |
---|
| 760 | ((arr)[((index)>>3)] |= (0x01<<((index) & (8-1)))) |
---|
| 761 | |
---|
| 762 | #define FAT_SET_UNIQ_INO_FREE(index, arr) \ |
---|
| 763 | ((arr)[((index)>>3)] &= (~(0x01<<((index) & (8-1))))) |
---|
| 764 | |
---|
| 765 | /* fat_get_unique_ino -- |
---|
| 766 | * Allocate unique ino from unique ino pool |
---|
| 767 | * |
---|
| 768 | * PARAMETERS: |
---|
[c65afce4] | 769 | * fs_info - FS info |
---|
[f36a7bfc] | 770 | * |
---|
| 771 | * RETURNS: |
---|
| 772 | * unique inode number on success, or 0 if there is no free unique inode |
---|
| 773 | * number in the pool |
---|
| 774 | * |
---|
| 775 | * ATTENTION: |
---|
| 776 | * 0 means FAILED !!! |
---|
[a5305f6b] | 777 | * |
---|
[f36a7bfc] | 778 | */ |
---|
[a5305f6b] | 779 | uint32_t |
---|
[c65afce4] | 780 | fat_get_unique_ino(fat_fs_info_t *fs_info) |
---|
[f36a7bfc] | 781 | { |
---|
[f91bbe64] | 782 | uint32_t j = 0; |
---|
[0a896eb] | 783 | bool resrc_unsuff = false; |
---|
[f36a7bfc] | 784 | |
---|
| 785 | while (!resrc_unsuff) |
---|
[a5305f6b] | 786 | { |
---|
[f36a7bfc] | 787 | for (j = 0; j < fs_info->uino_pool_size; j++) |
---|
| 788 | { |
---|
| 789 | if (!FAT_UNIQ_INO_IS_BUSY(fs_info->index, fs_info->uino)) |
---|
| 790 | { |
---|
| 791 | FAT_SET_UNIQ_INO_BUSY(fs_info->index, fs_info->uino); |
---|
[a5305f6b] | 792 | return (fs_info->uino_base + fs_info->index); |
---|
[f36a7bfc] | 793 | } |
---|
| 794 | fs_info->index++; |
---|
| 795 | if (fs_info->index >= fs_info->uino_pool_size) |
---|
| 796 | fs_info->index = 0; |
---|
| 797 | } |
---|
| 798 | |
---|
| 799 | if ((fs_info->uino_pool_size << 1) < (0x0FFFFFFF - fs_info->uino_base)) |
---|
| 800 | { |
---|
| 801 | fs_info->uino_pool_size <<= 1; |
---|
| 802 | fs_info->uino = realloc(fs_info->uino, fs_info->uino_pool_size); |
---|
| 803 | if (fs_info->uino != NULL) |
---|
| 804 | fs_info->index = fs_info->uino_pool_size; |
---|
[a5305f6b] | 805 | else |
---|
[0a896eb] | 806 | resrc_unsuff = true; |
---|
[f36a7bfc] | 807 | } |
---|
| 808 | else |
---|
[0a896eb] | 809 | resrc_unsuff = true; |
---|
[a5305f6b] | 810 | } |
---|
[f36a7bfc] | 811 | return 0; |
---|
| 812 | } |
---|
| 813 | |
---|
| 814 | /* fat_free_unique_ino -- |
---|
| 815 | * Return unique ino to unique ino pool |
---|
| 816 | * |
---|
| 817 | * PARAMETERS: |
---|
[c65afce4] | 818 | * fs_info - FS info |
---|
[f36a7bfc] | 819 | * ino - inode number to free |
---|
| 820 | * |
---|
| 821 | * RETURNS: |
---|
| 822 | * None |
---|
| 823 | */ |
---|
| 824 | void |
---|
| 825 | fat_free_unique_ino( |
---|
[c65afce4] | 826 | fat_fs_info_t *fs_info, |
---|
[f91bbe64] | 827 | uint32_t ino |
---|
[f36a7bfc] | 828 | ) |
---|
| 829 | { |
---|
| 830 | FAT_SET_UNIQ_INO_FREE((ino - fs_info->uino_base), fs_info->uino); |
---|
| 831 | } |
---|
| 832 | |
---|
| 833 | /* fat_ino_is_unique -- |
---|
| 834 | * Test whether ino is from unique ino pool |
---|
| 835 | * |
---|
| 836 | * PARAMETERS: |
---|
[c65afce4] | 837 | * fs_info - FS info |
---|
[f36a7bfc] | 838 | * ino - ino to be tested |
---|
| 839 | * |
---|
| 840 | * RETURNS: |
---|
[0a896eb] | 841 | * true if ino is allocated from unique ino pool, false otherwise |
---|
[f36a7bfc] | 842 | */ |
---|
[0a896eb] | 843 | inline bool |
---|
[f36a7bfc] | 844 | fat_ino_is_unique( |
---|
[c65afce4] | 845 | fat_fs_info_t *fs_info, |
---|
[f91bbe64] | 846 | uint32_t ino |
---|
[f36a7bfc] | 847 | ) |
---|
| 848 | { |
---|
[a5305f6b] | 849 | |
---|
[f36a7bfc] | 850 | return (ino >= fs_info->uino_base); |
---|
| 851 | } |
---|
| 852 | |
---|
| 853 | /* fat_fat32_update_fsinfo_sector -- |
---|
| 854 | * Synchronize fsinfo sector for FAT32 volumes |
---|
| 855 | * |
---|
| 856 | * PARAMETERS: |
---|
[c65afce4] | 857 | * fs_info - FS info |
---|
[f36a7bfc] | 858 | * free_count - count of free clusters |
---|
| 859 | * next_free - the next free cluster num |
---|
| 860 | * |
---|
| 861 | * RETURNS: |
---|
| 862 | * RC_OK on success, or -1 if error occured (errno set appropriately) |
---|
| 863 | */ |
---|
| 864 | int |
---|
| 865 | fat_fat32_update_fsinfo_sector( |
---|
[c65afce4] | 866 | fat_fs_info_t *fs_info, |
---|
[f91bbe64] | 867 | uint32_t free_count, |
---|
| 868 | uint32_t next_free |
---|
[f36a7bfc] | 869 | ) |
---|
| 870 | { |
---|
| 871 | ssize_t ret1 = 0, ret2 = 0; |
---|
[f91bbe64] | 872 | uint32_t le_free_count = 0; |
---|
| 873 | uint32_t le_next_free = 0; |
---|
[f36a7bfc] | 874 | |
---|
| 875 | le_free_count = CT_LE_L(free_count); |
---|
| 876 | le_next_free = CT_LE_L(next_free); |
---|
| 877 | |
---|
[c65afce4] | 878 | ret1 = _fat_block_write(fs_info, |
---|
[f36a7bfc] | 879 | fs_info->vol.info_sec, |
---|
| 880 | FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET, |
---|
| 881 | 4, |
---|
| 882 | (char *)(&le_free_count)); |
---|
| 883 | |
---|
[c65afce4] | 884 | ret2 = _fat_block_write(fs_info, |
---|
[f36a7bfc] | 885 | fs_info->vol.info_sec, |
---|
| 886 | FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET, |
---|
| 887 | 4, |
---|
| 888 | (char *)(&le_next_free)); |
---|
| 889 | |
---|
| 890 | if ( (ret1 < 0) || (ret2 < 0) ) |
---|
| 891 | return -1; |
---|
| 892 | |
---|
| 893 | return RC_OK; |
---|
| 894 | } |
---|