Example #1
0
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;
	}
Example #2
0
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;
}
Example #5
0
/* 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;
}
Example #7
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;
}