File indexing completed on 2025-05-11 08:24:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #ifdef HAVE_CONFIG_H
0021 #include "config.h"
0022 #endif
0023
0024 #include <ctype.h>
0025 #include <stdlib.h>
0026 #include <unistd.h>
0027 #include <errno.h>
0028 #include <rtems/libio_.h>
0029 #include <sys/types.h>
0030 #include <sys/stat.h>
0031
0032 #include <dirent.h>
0033
0034 #include "fat.h"
0035 #include "fat_fat_operations.h"
0036 #include "fat_file.h"
0037
0038 #include "msdos.h"
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 ssize_t
0065 msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
0066 {
0067 int rc = RC_OK;
0068 int eno = 0;
0069 msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
0070 rtems_dosfs_convert_control *converter = fs_info->converter;
0071 const rtems_dosfs_convert_handler *convert_handler = converter->handler;
0072 fat_file_fd_t *fat_fd = iop->pathinfo.node_access;
0073 fat_file_fd_t *tmp_fat_fd = NULL;
0074 struct dirent tmp_dirent;
0075 size_t lfn_len = 0;
0076 uint16_t *lfn_buf = converter->buffer.data;
0077 char *sfn_buf = converter->buffer.data;
0078 const size_t buf_size = converter->buffer.size;
0079 uint32_t start = 0;
0080 ssize_t ret = 0;
0081 ssize_t cmpltd = 0;
0082 uint32_t j = 0, i = 0;
0083 uint32_t bts2rd = 0;
0084 uint32_t cur_cln = 0;
0085 uint32_t lfn_start = FAT_FILE_SHORT_NAME;
0086 uint8_t lfn_checksum = 0;
0087 int lfn_entries = 0;
0088 bool is_first_entry;
0089
0090 msdos_fs_lock(fs_info);
0091
0092
0093
0094
0095
0096
0097 start = iop->offset / sizeof(struct dirent);
0098 count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
0099
0100
0101
0102
0103
0104
0105
0106 bts2rd = (FAT_FD_OF_ROOT_DIR(fat_fd) &&
0107 (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) ?
0108 fat_fd->fat_file_size :
0109 fs_info->fat.vol.bpc;
0110
0111 while (count > 0 && cmpltd >= 0)
0112 {
0113
0114
0115
0116
0117
0118
0119 ret = fat_file_read(&fs_info->fat, fat_fd, (j * bts2rd),
0120 bts2rd, fs_info->cl_buf);
0121 if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
0122 {
0123 msdos_fs_unlock(fs_info);
0124 rtems_set_errno_and_return_minus_one(EIO);
0125 }
0126
0127 for (i = 0; i < ret && cmpltd >= 0; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
0128 {
0129 char* entry = (char*) fs_info->cl_buf + i;
0130
0131
0132
0133
0134 if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
0135 MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
0136 {
0137 msdos_fs_unlock(fs_info);
0138 return cmpltd;
0139 }
0140
0141
0142 if ((*MSDOS_DIR_ENTRY_TYPE(entry)) == MSDOS_THIS_DIR_ENTRY_EMPTY)
0143 continue;
0144
0145
0146 if (((*MSDOS_DIR_ATTR(entry)) & MSDOS_ATTR_VOLUME_ID) &&
0147 ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) != MSDOS_ATTR_LFN))
0148 continue;
0149
0150
0151
0152
0153
0154 if ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
0155 MSDOS_ATTR_LFN)
0156 {
0157 int offset_lfn;
0158
0159
0160
0161
0162 if (lfn_start == FAT_FILE_SHORT_NAME)
0163 {
0164 is_first_entry = true;
0165
0166
0167
0168 if ((*MSDOS_DIR_ENTRY_TYPE(entry) &
0169 MSDOS_LAST_LONG_ENTRY) == 0)
0170 continue;
0171
0172
0173
0174
0175 lfn_start =
0176 ((j * bts2rd) + i) / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
0177
0178
0179
0180
0181
0182 lfn_entries = (*MSDOS_DIR_ENTRY_TYPE(entry) &
0183 MSDOS_LAST_LONG_ENTRY_MASK);
0184 lfn_len = 0;
0185 lfn_checksum = *MSDOS_DIR_LFN_CHECKSUM(entry);
0186 memset (tmp_dirent.d_name, 0, sizeof(tmp_dirent.d_name));
0187 }
0188 else
0189 is_first_entry = false;
0190
0191
0192
0193
0194
0195
0196
0197 if ((lfn_entries != (*MSDOS_DIR_ENTRY_TYPE(entry) &
0198 MSDOS_LAST_LONG_ENTRY_MASK)) ||
0199 (lfn_checksum != *MSDOS_DIR_LFN_CHECKSUM(entry)))
0200 {
0201 lfn_start = FAT_FILE_SHORT_NAME;
0202 continue;
0203 }
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217 lfn_entries--;
0218 offset_lfn = lfn_entries * MSDOS_LFN_LEN_PER_ENTRY;
0219 lfn_len += msdos_get_utf16_string_from_long_entry (
0220 entry,
0221 &lfn_buf[offset_lfn],
0222 buf_size - offset_lfn,
0223 is_first_entry
0224 );
0225 }
0226 else
0227 {
0228 fat_dir_pos_t dir_pos;
0229
0230
0231
0232
0233 if (start)
0234 {
0235 lfn_start = FAT_FILE_SHORT_NAME;
0236 start--;
0237 continue;
0238 }
0239
0240 #ifdef DT_DIR
0241 if ((*MSDOS_DIR_ATTR(entry)) & MSDOS_ATTR_DIRECTORY)
0242 {
0243 tmp_dirent.d_type = DT_DIR;
0244 }
0245 else
0246 {
0247 tmp_dirent.d_type = DT_REG;
0248 }
0249 #endif
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 rc = fat_file_ioctl(&fs_info->fat, fat_fd, F_CLU_NUM,
0260 j * bts2rd, &cur_cln);
0261 if (rc != RC_OK)
0262 {
0263 msdos_fs_unlock(fs_info);
0264 return rc;
0265 }
0266
0267 fat_dir_pos_init(&dir_pos);
0268 dir_pos.sname.cln = cur_cln;
0269 dir_pos.sname.ofs = i;
0270 rc = fat_file_open(&fs_info->fat, &dir_pos, &tmp_fat_fd);
0271 if (rc != RC_OK)
0272 {
0273 msdos_fs_unlock(fs_info);
0274 return rc;
0275 }
0276
0277
0278
0279 tmp_dirent.d_off = start + cmpltd;
0280 tmp_dirent.d_reclen = sizeof(struct dirent);
0281 tmp_dirent.d_ino = tmp_fat_fd->ino;
0282
0283
0284
0285
0286
0287
0288
0289 if (lfn_start != FAT_FILE_SHORT_NAME)
0290 {
0291 if (lfn_entries == 0 &&
0292 lfn_checksum == msdos_lfn_checksum(entry)) {
0293 size_t len = sizeof(tmp_dirent.d_name) - 1;
0294
0295 eno = (*convert_handler->utf16_to_utf8) (
0296 converter,
0297 lfn_buf,
0298 lfn_len,
0299 (uint8_t *) &tmp_dirent.d_name[0],
0300 &len);
0301 if (eno == 0) {
0302 tmp_dirent.d_namlen = len;
0303 tmp_dirent.d_name[len] = '\0';
0304 } else {
0305 lfn_start = FAT_FILE_SHORT_NAME;
0306 }
0307 } else {
0308 lfn_start = FAT_FILE_SHORT_NAME;
0309 }
0310 }
0311
0312 if (lfn_start == FAT_FILE_SHORT_NAME) {
0313 size_t len = sizeof(tmp_dirent.d_name) - 1;
0314
0315
0316
0317
0318
0319 tmp_dirent.d_namlen = msdos_format_dirent_with_dot(
0320 sfn_buf, entry);
0321 eno = (*convert_handler->codepage_to_utf8) (
0322 converter,
0323 sfn_buf,
0324 tmp_dirent.d_namlen,
0325 (uint8_t *) &tmp_dirent.d_name[0],
0326 &len);
0327 if ( 0 == eno ) {
0328 tmp_dirent.d_namlen = len;
0329 tmp_dirent.d_name[len] = '\0';
0330 } else {
0331 cmpltd = -1;
0332 errno = eno;
0333 }
0334 }
0335
0336 if ( cmpltd >= 0 ) {
0337 memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
0338
0339 iop->offset = iop->offset + sizeof(struct dirent);
0340 cmpltd += (sizeof(struct dirent));
0341 count -= (sizeof(struct dirent));
0342 }
0343
0344
0345 rc = fat_file_close(&fs_info->fat, tmp_fat_fd);
0346 if (rc != RC_OK)
0347 {
0348 msdos_fs_unlock(fs_info);
0349 return rc;
0350 }
0351 }
0352
0353 if (count <= 0)
0354 break;
0355 }
0356 j++;
0357 }
0358
0359 msdos_fs_unlock(fs_info);
0360 return cmpltd;
0361 }
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387 int
0388 msdos_dir_stat(
0389 const rtems_filesystem_location_info_t *loc,
0390 struct stat *buf
0391 )
0392 {
0393 msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
0394 fat_file_fd_t *fat_fd = loc->node_access;
0395
0396 msdos_fs_lock(fs_info);
0397
0398 buf->st_dev = fs_info->fat.vol.dev;
0399 buf->st_ino = fat_fd->ino;
0400 buf->st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
0401 buf->st_rdev = 0ll;
0402 buf->st_size = fat_fd->fat_file_size;
0403 buf->st_blocks = fat_fd->fat_file_size >> FAT_SECTOR512_BITS;
0404 buf->st_blksize = fs_info->fat.vol.bps;
0405 buf->st_atime = fat_fd->mtime;
0406 buf->st_ctime = fat_fd->ctime;
0407 buf->st_mtime = fat_fd->mtime;
0408
0409 msdos_fs_unlock(fs_info);
0410 return RC_OK;
0411 }
0412
0413
0414
0415
0416
0417
0418
0419
0420