/* fat_file_read -- * Read 'count' bytes from 'start' position from fat-file. This * interface hides the architecture of fat-file, represents it as * linear file * * PARAMETERS: * mt_entry - mount table entry * fat_fd - fat-file descriptor * start - offset in fat-file (in bytes) to read from * count - count of bytes to read * buf - buffer provided by user * * RETURNS: * the number of bytes read on success, or -1 if error occured (errno * set appropriately) */ ssize_t fat_file_read( rtems_filesystem_mount_table_entry_t *mt_entry, fat_file_fd_t *fat_fd, uint32_t start, uint32_t count, uint8_t *buf ) { int rc = RC_OK; ssize_t ret = 0; fat_fs_info_t *fs_info = mt_entry->fs_info; uint32_t cmpltd = 0; uint32_t cur_cln = 0; uint32_t cl_start = 0; uint32_t save_cln = 0; uint32_t ofs = 0; uint32_t save_ofs; uint32_t sec = 0; uint32_t byte = 0; uint32_t c = 0; /* it couldn't be removed - otherwise cache update will be broken */ if (count == 0) return cmpltd; /* * >= because start is offset and computed from 0 and file_size * computed from 1 */ if ( start >= fat_fd->fat_file_size ) return FAT_EOF; if ((count > fat_fd->fat_file_size) || (start > fat_fd->fat_file_size - count)) count = fat_fd->fat_file_size - start; if ((FAT_FD_OF_ROOT_DIR(fat_fd)) && (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16))) { sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln); sec += (start >> fs_info->vol.sec_log2); byte = start & (fs_info->vol.bps - 1); ret = _fat_block_read(mt_entry, sec, byte, count, buf); if ( ret < 0 ) return -1; return ret; }
/* fat_cluster_write -- * wrapper for writting a whole cluster at once * * PARAMETERS: * mt_entry - mount table entry * cln - number of cluster to write * buff - buffer provided by user * * RETURNS: * bytes written on success, or -1 if error occured * and errno set appropriately */ ssize_t fat_cluster_write( rtems_filesystem_mount_table_entry_t *mt_entry, uint32_t cln, const void *buff ) { fat_fs_info_t *fs_info = mt_entry->fs_info; uint32_t fsec = 0; fsec = fat_cluster_num_to_sector_num(mt_entry, cln); return _fat_block_write(mt_entry, fsec, 0, fs_info->vol.spc << fs_info->vol.sec_log2, buff); }
/* msdos_set_first_char4file_name -- * Write first character of the name of the file to the disk (to * corresponded 32bytes slot) * * PARAMETERS: * mt_entry - mount table entry * cl - number of cluster * ofs - offset inside cluster * fchar - character to set up * * RETURNS: * RC_OK on success, or -1 if error occured (errno set apropriately) * */ int msdos_set_first_char4file_name( rtems_filesystem_mount_table_entry_t *mt_entry, uint32_t cl, uint32_t ofs, unsigned char fchar ) { ssize_t ret = 0; msdos_fs_info_t *fs_info = mt_entry->fs_info; uint32_t sec = 0; uint32_t byte = 0; sec = fat_cluster_num_to_sector_num(mt_entry, cl); sec += (ofs >> fs_info->fat.vol.sec_log2); byte = (ofs & (fs_info->fat.vol.bps - 1)); ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_NAME_OFFSET, 1, &fchar); if ( ret < 0) return -1; return RC_OK; }
/* msdos_set_file size -- * Write file size of the file to the disk (to corresponded 32bytes slot) * * PARAMETERS: * mt_entry - mount table entry * fat_fd - fat-file descriptor * * RETURNS: * RC_OK on success, or -1 if error occured (errno set apropriately). * */ int msdos_set_file_size( rtems_filesystem_mount_table_entry_t *mt_entry, fat_file_fd_t *fat_fd ) { ssize_t ret = 0; msdos_fs_info_t *fs_info = mt_entry->fs_info; uint32_t le_new_length = 0; uint32_t sec = 0; uint32_t byte = 0; sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln); sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2); byte = (fat_fd->info_ofs & (fs_info->fat.vol.bps - 1)); le_new_length = CT_LE_L((fat_fd->fat_file_size)); ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_SIZE_OFFSET, 4, (char *)(&le_new_length)); if ( ret < 0 ) return -1; return RC_OK; }
/* msdos_set_first_cluster_num -- * Write number of first cluster of the file to the disk (to corresponded * 32bytes slot) * * PARAMETERS: * mt_entry - mount table entry * fat_fd - fat-file descriptor * * RETURNS: * RC_OK on success, or -1 if error occured * */ int msdos_set_first_cluster_num( rtems_filesystem_mount_table_entry_t *mt_entry, fat_file_fd_t *fat_fd ) { ssize_t ret1 = 0, ret2 = 0; msdos_fs_info_t *fs_info = mt_entry->fs_info; uint32_t new_cln = fat_fd->cln; uint16_t le_cl_low = 0; uint16_t le_cl_hi = 0; uint32_t sec = 0; uint32_t byte = 0; /* * calculate input for _fat_block_write: convert (cluster num, offset) to * (sector num, new offset) */ sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln); sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2); /* byte from points to start of 32bytes structure */ byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1); le_cl_low = CT_LE_W((uint16_t )(new_cln & 0x0000FFFF)); ret1 = _fat_block_write(mt_entry, sec, byte + MSDOS_FIRST_CLUSTER_LOW_OFFSET, 2, (char *)(&le_cl_low)); le_cl_hi = CT_LE_W((uint16_t )((new_cln & 0xFFFF0000) >> 16)); ret2 = _fat_block_write(mt_entry, sec, byte + MSDOS_FIRST_CLUSTER_HI_OFFSET, 2, (char *)(&le_cl_hi)); if ( (ret1 < 0) || (ret2 < 0) ) return -1; return RC_OK; }
/* msdos_set_dir_wrt_time_and_date -- * Write last write date and time for a file to the disk (to corresponded * 32bytes node) * * PARAMETERS: * mt_entry - mount table entry * fat_fd - fat-file descriptor * * RETURNS: * RC_OK on success, or -1 if error occured (errno set apropriately). * */ int msdos_set_dir_wrt_time_and_date( rtems_filesystem_mount_table_entry_t *mt_entry, fat_file_fd_t *fat_fd ) { ssize_t ret1 = 0, ret2 = 0; msdos_fs_info_t *fs_info = mt_entry->fs_info; unsigned short time_val; unsigned short date; uint32_t sec = 0; uint32_t byte = 0; msdos_date_unix2dos(fat_fd->mtime, &time_val, &date); /* * calculate input for _fat_block_write: convert (cluster num, offset) to * (sector num, new offset) */ sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln); sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2); /* byte points to start of 32bytes structure */ byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1); time_val = CT_LE_W(time_val); ret1 = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_WTIME_OFFSET, 2, (char *)(&time_val)); date = CT_LE_W(date); ret2 = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_WDATE_OFFSET, 2, (char *)(&date)); if ( (ret1 < 0) || (ret2 < 0) ) return -1; return RC_OK; }
/* msdos_creat_node -- * Create a new node. Determine if the name is a long name. If long we to * scan the directory to create a short entry. * * * If a new node is file, FAT 32 Bytes Directory * Entry Structure is initialized, free space is found in parent * directory and structure is written to the disk. In case of directory, * all above steps present and also new cluster is allocated for a * new directory and dot and dotdot nodes are created in alloceted cluster. * * PARAMETERS: * parent_loc - parent (directory we are going to create node in) * type - new node type (file or directory) * name - new node name * mode - mode * link_info - fs_info of existing node for a pseudo "hard-link" * (see msdos_file.c, msdos_link for documentation) * * RETURNS: * RC_OK on success, or -1 if error occured (errno set appropriately). * */ int msdos_creat_node(const rtems_filesystem_location_info_t *parent_loc, fat_file_type_t type, const char *name, int name_len, mode_t mode, const fat_file_fd_t *link_fd) { int rc = RC_OK; ssize_t ret = 0; msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info; fat_file_fd_t *parent_fat_fd = parent_loc->node_access; fat_file_fd_t *fat_fd = NULL; time_t now; uint16_t time_val = 0; uint16_t date = 0; fat_dir_pos_t dir_pos; msdos_name_type_t name_type; char short_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2]; char link_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE]; uint32_t sec = 0; uint32_t byte = 0; fat_dir_pos_init(&dir_pos); memset(short_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE); memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2); if (name_len > MSDOS_NAME_MAX_LFN_WITH_DOT) { rtems_set_errno_and_return_minus_one(ENAMETOOLONG); } name_type = msdos_long_to_short (fs_info->converter, name, name_len, MSDOS_DIR_NAME(short_node), MSDOS_NAME_MAX); if (name_type == MSDOS_NAME_INVALID) { rtems_set_errno_and_return_minus_one(EINVAL); } /* fill reserved field */ *MSDOS_DIR_NT_RES(short_node) = MSDOS_RES_NT_VALUE; /* set up last write date and time */ now = time(NULL); fat_file_set_ctime_mtime(parent_fat_fd, now); msdos_date_unix2dos(now, &date, &time_val); *MSDOS_DIR_CRT_TIME(short_node) = CT_LE_W(time_val); *MSDOS_DIR_CRT_DATE(short_node) = CT_LE_W(date); *MSDOS_DIR_WRITE_TIME(short_node) = CT_LE_W(time_val); *MSDOS_DIR_WRITE_DATE(short_node) = CT_LE_W(date); *MSDOS_DIR_LAST_ACCESS_DATE(short_node) = CT_LE_W(date); /* initialize directory/file size */ *MSDOS_DIR_FILE_SIZE(short_node) = MSDOS_INIT_DIR_SIZE; if (type == FAT_DIRECTORY) { *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_DIRECTORY; } else if (type == FAT_HARD_LINK) { /* * when we establish a (temporary) hard link, * we must copy some information from the original * node to the newly created */ /* * read the original directory entry */ sec = fat_cluster_num_to_sector_num(&fs_info->fat, link_fd->dir_pos.sname.cln); sec += (link_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2); byte = (link_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1)); ret = _fat_block_read(&fs_info->fat, sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE, link_node); if (ret < 0) { return -1; } /* * copy various attributes */ *MSDOS_DIR_ATTR(short_node) =*MSDOS_DIR_ATTR(link_node); *MSDOS_DIR_CRT_TIME_TENTH(short_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node); *MSDOS_DIR_CRT_TIME(short_node) =*MSDOS_DIR_CRT_TIME(link_node); *MSDOS_DIR_CRT_DATE(short_node) =*MSDOS_DIR_CRT_DATE(link_node); /* * copy/set "file size", "first cluster" */ *MSDOS_DIR_FILE_SIZE(short_node) =*MSDOS_DIR_FILE_SIZE(link_node); *MSDOS_DIR_FIRST_CLUSTER_LOW(short_node) = *MSDOS_DIR_FIRST_CLUSTER_LOW(link_node); *MSDOS_DIR_FIRST_CLUSTER_HI(short_node) = *MSDOS_DIR_FIRST_CLUSTER_HI(link_node); /* * set "archive bit" due to changes */ *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_ARCHIVE; }