static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss) { struct boot_sector b2; if (!fs->backupboot_start) { printf( "There is no backup boot sector.\n" ); if (CF_LE_W(b->reserved) < 3) { printf( "And there is no space for creating one!\n" ); return; } if (interactive) printf( "1) Create one\n2) Do without a backup\n" ); else printf( " Auto-creating backup boot block.\n" ); if (!interactive || get_key("12","?") == '1') { int bbs; /* The usual place for the backup boot sector is sector 6. Choose * that or the last reserved sector. */ if (CF_LE_W(b->reserved) >= 7 && CF_LE_W(b->info_sector) != 6) bbs = 6; else { bbs = CF_LE_W(b->reserved) - 1; if (bbs == CF_LE_W(b->info_sector)) --bbs; /* this is never 0, as we checked reserved >= 3! */ } fs->backupboot_start = bbs*lss; b->backup_boot = CT_LE_W(bbs); fs_write(fs->backupboot_start,sizeof(*b),b); fs_write((off_t)offsetof(struct boot_sector,backup_boot), sizeof(b->backup_boot),&b->backup_boot); printf( "Created backup of boot sector in sector %d\n", bbs ); return; }
static int msdos_default_utf8_to_utf16( rtems_dosfs_convert_control *super, const uint8_t *src, const size_t src_size, uint16_t *dst, size_t *dst_size ) { int eno = 0; size_t bytes_to_copy = MIN( src_size, *dst_size / 2); size_t i; (void) super; *dst_size = 2 * bytes_to_copy; for ( i = 0; eno == 0 && i < bytes_to_copy; ++i ) { uint16_t utf16_native = src[i]; if ( utf16_native <= 127 ) { dst[i] = CT_LE_W( utf16_native ); } else { eno = EINVAL; } } return eno; }
/* 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_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_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; }
static int do_msdos_rename(struct inode *old_dir, char *old_name, struct dentry *old_dentry, struct inode *new_dir,char *new_name, struct dentry *new_dentry, struct buffer_head *old_bh, struct msdos_dir_entry *old_de, loff_t old_ino, int is_hid) { struct super_block *sb = old_dir->i_sb; struct buffer_head *new_bh=NULL,*dotdot_bh=NULL; struct msdos_dir_entry *new_de,*dotdot_de; struct inode *old_inode,*new_inode; loff_t new_ino,dotdot_ino; int error; int is_dir; old_inode = old_dentry->d_inode; new_inode = new_dentry->d_inode; is_dir = S_ISDIR(old_inode->i_mode); if (fat_scan(new_dir,new_name,&new_bh,&new_de,&new_ino)>=0 &&!new_inode) goto degenerate_case; if (is_dir) { if (new_inode) { error = fat_dir_empty(new_inode); if (error) goto out; } error = fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh, &dotdot_de, &dotdot_ino); if (error < 0) { printk(KERN_WARNING "MSDOS: %s/%s, get dotdot failed, ret=%d\n", old_dentry->d_parent->d_name.name, old_dentry->d_name.name, error); goto out; } } if (!new_bh) { error = msdos_add_entry(new_dir, new_name, &new_bh, &new_de, &new_ino, is_dir, is_hid); if (error) goto out; } new_dir->i_version = ++event; /* There we go */ if (new_inode) fat_detach(new_inode); old_de->name[0] = DELETED_FLAG; fat_mark_buffer_dirty(sb, old_bh); fat_detach(old_inode); fat_attach(old_inode, new_ino); if (is_hid) MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN; else MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN; mark_inode_dirty(old_inode); old_dir->i_version = ++event; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(old_dir); if (new_inode) { new_inode->i_nlink--; new_inode->i_ctime = CURRENT_TIME; mark_inode_dirty(new_inode); } if (dotdot_bh) { dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart); dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16); fat_mark_buffer_dirty(sb, dotdot_bh); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { new_inode->i_nlink--; mark_inode_dirty(new_inode); } else { new_dir->i_nlink++; mark_inode_dirty(new_dir); } } error = 0; out: fat_brelse(sb, new_bh); fat_brelse(sb, dotdot_bh); return error; degenerate_case: error = -EINVAL; if (new_de!=old_de) goto out; if (is_hid) MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN; else MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN; mark_inode_dirty(old_inode); old_dir->i_version = ++event; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(old_dir); return 0; }
static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name, struct dentry *old_dentry, struct inode *new_dir, unsigned char *new_name, struct dentry *new_dentry, struct buffer_head *old_bh, struct msdos_dir_entry *old_de, loff_t old_i_pos, int is_hid) { struct buffer_head *new_bh=NULL,*dotdot_bh=NULL; struct msdos_dir_entry *new_de,*dotdot_de; struct inode *old_inode,*new_inode; loff_t new_i_pos, dotdot_i_pos; int error; int is_dir; old_inode = old_dentry->d_inode; new_inode = new_dentry->d_inode; is_dir = S_ISDIR(old_inode->i_mode); if (fat_scan(new_dir, new_name, &new_bh, &new_de, &new_i_pos) >= 0 && !new_inode) goto degenerate_case; if (is_dir) { if (new_inode) { error = fat_dir_empty(new_inode); if (error) goto out; } if (fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh, &dotdot_de, &dotdot_i_pos) < 0) { error = -EIO; goto out; } } if (!new_bh) { error = msdos_add_entry(new_dir, new_name, &new_bh, &new_de, &new_i_pos, is_dir, is_hid); if (error) goto out; } new_dir->i_version++; /* There we go */ if (new_inode) fat_detach(new_inode); old_de->name[0] = DELETED_FLAG; mark_buffer_dirty(old_bh); fat_detach(old_inode); fat_attach(old_inode, new_i_pos); if (is_hid) MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN; else MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN; mark_inode_dirty(old_inode); old_dir->i_version++; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(old_dir); if (new_inode) { new_inode->i_nlink--; new_inode->i_ctime = CURRENT_TIME; mark_inode_dirty(new_inode); } if (dotdot_bh) { dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart); dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16); mark_buffer_dirty(dotdot_bh); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { new_inode->i_nlink--; mark_inode_dirty(new_inode); } else { new_dir->i_nlink++; mark_inode_dirty(new_dir); } } error = 0; out: brelse(new_bh); brelse(dotdot_bh); return error; degenerate_case: error = -EINVAL; if (new_de!=old_de) goto out; if (is_hid) MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN; else MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN; mark_inode_dirty(old_inode); old_dir->i_version++; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(old_dir); return 0; }