示例#1
0
ssize_t umsdos_file_write_kmem_real (struct file * filp,
				     const char *buf,
				     size_t count)
{
	mm_segment_t old_fs = get_fs ();
	ssize_t ret;

	/* note: i_binary=2 is for CVF-FAT. We put it here, instead of
	 * umsdos_file_write_kmem, since it is also wise not to compress
	 * symlinks (in the unlikely event that they are > 512 bytes and
	 * can be compressed.
	 * FIXME: should we set it when reading symlinks too?
	 */

	MSDOS_I (filp->f_dentry->d_inode)->i_binary = 2;

	set_fs (KERNEL_DS);
	ret = fat_file_write (filp, buf, count, &filp->f_pos);
	set_fs (old_fs);
	if (ret < 0) {
		printk(KERN_WARNING "umsdos_file_write: ret=%d\n", ret);
		goto out;
	}
#ifdef UMSDOS_PARANOIA
if (ret != count)
printk(KERN_WARNING "umsdos_file_write: count=%u, ret=%u\n", count, ret);
#endif
out:
	return ret;
}
示例#2
0
文件: msdos_file.c 项目: rtemss/rtems
/* msdos_file_write --
 *     This routine writes the specified data buffer into the file pointed to
 *     by file control block.
 *
 * PARAMETERS:
 *     iop    - file control block
 *     buffer - data to write
 *     count  - count of bytes to write
 *
 * RETURNS:
 *     the number of bytes written on success, or -1 if error occured
 *     and errno set appropriately
 */
ssize_t
msdos_file_write(rtems_libio_t *iop,const void *buffer, size_t count)
{
    ssize_t            ret = 0;
    rtems_status_code  sc = RTEMS_SUCCESSFUL;
    msdos_fs_info_t   *fs_info = iop->pathinfo.mt_entry->fs_info;
    fat_file_fd_t     *fat_fd = iop->pathinfo.node_access;

    sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
                                MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
    if (sc != RTEMS_SUCCESSFUL)
        rtems_set_errno_and_return_minus_one(EIO);

    ret = fat_file_write(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
                         buffer);
    if (ret < 0)
    {
        rtems_semaphore_release(fs_info->vol_sema);
        return -1;
    }

    /*
     * update file size in both fat-file descriptor and file control block if
     * file was extended
     */
    if (iop->offset + ret > fat_fd->fat_file_size)
        fat_fd->fat_file_size = iop->offset + ret;

    iop->size = fat_fd->fat_file_size;

    rtems_semaphore_release(fs_info->vol_sema);
    return ret;
}
示例#3
0
/*
 * Write a file from user space memory
 */
static ssize_t UMSDOS_file_write (
    struct file *filp,
    const char *buf,
    size_t count,
    loff_t * ppos)
{
    return fat_file_write (filp, buf, count, ppos);
}
示例#4
0
/*
	Write to a file from kernel space
*/
int umsdos_file_write_kmem(
	struct inode *inode,
	struct file *filp,
	const char *buf,
	int count)
{
	int ret;
	int old_fs = get_fs();
	set_fs (KERNEL_DS);
	ret = fat_file_write(inode,filp,buf,count);
	set_fs (old_fs);
	return ret;
}
/* msdos_find_name_in_fat_file --
 *     This routine is used in two ways: for a new mode creation (a) or for
 *     search the node which correspondes to the 'name' parameter (b).
 *     In case (a) name should be set up to NULL and 'name_dir_entry' should
 *     point to initialized 32 bytes structure described a new node.
 *     In case (b) 'name' should contain a valid string.
 *
 *     (a): reading fat-file corresponded to directory we are going to create
 *          node in. If found free slot write contents of name_dir_entry into
 *          it.
 *
 *     (b): reading fat-file corresponded to directory and trying to find slot
 *          with the name field == name parameter
 *
 * PARAMETERS:
 *     mt_entry       - mount table entry
 *     fat_fd         - fat-file descriptor
 *     name           - NULL or name to find
 *     paux           - identify a node location on the disk -
 *                      number of cluster and offset inside the cluster
 *     name_dir_entry - node to create/placeholder for found node
 *
 * RETURNS:
 *     RC_OK on success, or error code if error occured (errno set
 *     appropriately)
 *
 */
int msdos_find_name_in_fat_file(
    rtems_filesystem_mount_table_entry_t *mt_entry,
    fat_file_fd_t                        *fat_fd,
    char                                 *name,
    fat_auxiliary_t                      *paux,
    char                                 *name_dir_entry
    )
{
    int              rc = RC_OK;
    ssize_t          ret = 0;
    msdos_fs_info_t *fs_info = mt_entry->fs_info;
    uint32_t         i = 0, j = 0;
    uint32_t         bts2rd = 0;

    if (FAT_FD_OF_ROOT_DIR(fat_fd) &&
       (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
        bts2rd = fat_fd->fat_file_size;
    else
        bts2rd = fs_info->fat.vol.bpc;

    while ((ret = fat_file_read(mt_entry, fat_fd, (j * bts2rd), bts2rd,
                                fs_info->cl_buf)) != FAT_EOF)
    {
        if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
            set_errno_and_return_minus_one(EIO);

        assert(ret == bts2rd);

        /* have to look at the DIR_NAME as "raw" 8-bit data */
        for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
        {
            /* is the entry empty ? */
            if (((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
                 MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) ||
                 ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
                 MSDOS_THIS_DIR_ENTRY_EMPTY))
            {
                /* whether we are looking for an empty entry */
                if (name == NULL)
                {
                    /* get current cluster number */
                    rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
                                        j * bts2rd, &paux->cln);
                    if (rc != RC_OK)
                        return rc;

                    /* offset is computed in bytes */
                    paux->ofs = i;

                    /* write new node entry */
                    ret = fat_file_write(mt_entry, fat_fd, j * bts2rd + i,
                                         MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
                                         (uint8_t *)name_dir_entry);
                    if (ret != MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
                        return -1;

                    /*
                     * we don't update fat_file_size here - it should not
                     * increase
                     */
                    return RC_OK;
                }

                /*
                 * if name != NULL and there is no more entries in the
                 * directory - return name-not-found
                 */
                if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
                     MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY))
                    return MSDOS_NAME_NOT_FOUND_ERR;
            }
            else
            {
                /* entry not empty and name != NULL -> compare names */
                if (name != NULL)
                {
                    if (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), name,
                                MSDOS_SHORT_NAME_LEN) == 0)
                    {
                        /*
                         * we get the entry we looked for - fill auxiliary
                         * structure and copy all 32 bytes of the entry
                         */
                        rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
                                            j * bts2rd, &paux->cln);
                        if (rc != RC_OK)
                            return rc;

                        /* offset is computed in bytes */
                        paux->ofs = i;
                        memcpy(name_dir_entry,(fs_info->cl_buf + i),
                               MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
                        return RC_OK;
                    }
                }
            }
        }
        j++;
    }
    return MSDOS_NAME_NOT_FOUND_ERR;
}
/* msdos_get_name_node --
 *     This routine is used in two ways: for a new mode creation (a) or for
 *     search the node which correspondes to the name parameter (b).
 *     In case (a) 'name' should be set up to NULL and 'name_dir_entry' should
 *     point to initialized 32 bytes structure described a new node.
 *     In case (b) 'name' should contain a valid string.
 *
 *     (a): reading fat-file which correspondes to directory we are going to
 *          create node in. If free slot is found write contents of
 *          'name_dir_entry' into it. If reach end of fat-file and no free
 *          slot found, write 32 bytes to the end of fat-file.
 *
 *     (b): reading fat-file which correspondes to directory and trying to
 *          find slot with the name field == 'name' parameter
 *
 *
 * PARAMETERS:
 *     parent_loc     - node description to create node in or to find name in
 *     name           - NULL or name to find
 *     paux           - identify a node location on the disk -
 *                      cluster num and offset inside the cluster
 *     name_dir_entry - node to create/placeholder for found node (IN/OUT)
 *
 * RETURNS:
 *     RC_OK, filled aux_struct_ptr and name_dir_entry on success, or -1 if
 *     error occured (errno set apropriately)
 *
 */
int
msdos_get_name_node(
    rtems_filesystem_location_info_t *parent_loc,
    char                             *name,
    fat_auxiliary_t                  *paux,
    char                             *name_dir_entry
    )
{
    int              rc = RC_OK;
    ssize_t          ret = 0;
    msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
    fat_file_fd_t   *fat_fd = parent_loc->node_access;
    uint32_t         dotdot_cln = 0;

    /* find name in fat-file which correspondes to the directory */
    rc = msdos_find_name_in_fat_file(parent_loc->mt_entry, fat_fd, name, paux,
                                     name_dir_entry);
    if ((rc != RC_OK) && (rc != MSDOS_NAME_NOT_FOUND_ERR))
        return rc;

    /* if we search for valid name and name not found -> return */
    if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name != NULL))
        return rc;

    /*
     * if we try to create new entry and the directory is not big enough
     * currently - try to enlarge directory
     */
    if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name == NULL))
    {
        ret = fat_file_write(parent_loc->mt_entry, fat_fd,
                             fat_fd->fat_file_size,
                             MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
                             (uint8_t *)name_dir_entry);
        if (ret == -1)
            return -1;

        /* on success directory is enlarged by a new cluster */
        fat_fd->fat_file_size += fs_info->fat.vol.bpc;

        /* get cluster num where a new node located */
        rc = fat_file_ioctl(parent_loc->mt_entry, fat_fd, F_CLU_NUM,
                            fat_fd->fat_file_size - 1, &paux->cln);

        if (rc != RC_OK)
            return rc;

        /*
         * if new cluster allocated succesfully then new node is at very
         * beginning of the cluster (offset is computed in bytes)
         */
        paux->ofs = 0;
        return RC_OK;
    }

    /*
     * if we have deal with ".." - it is a special case :(((
     *
     * Really, we should return cluster num and offset not of ".." slot, but
     * slot which correspondes to real directory name.
     */
    if ((rc == RC_OK) && (name != NULL))
    {
        if (strncmp(name, MSDOS_DOTDOT_NAME, MSDOS_SHORT_NAME_LEN) == 0)
        {
            dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM((name_dir_entry));

            /* are we right under root dir ? */
            if (dotdot_cln == 0)
            {
                /*
                 * we can relax about first_char field - it never should be
                 * used for root dir
                 */
                paux->cln = FAT_ROOTDIR_CLUSTER_NUM;
                paux->ofs = 0;
            }
            else
            {
                rc = msdos_get_dotdot_dir_info_cluster_num_and_offset(
                        parent_loc->mt_entry,
                        dotdot_cln,
                        paux,
                        name_dir_entry
                        );
                if (rc != RC_OK)
                    return rc;
            }
        }
    }
    return rc;
}