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; }
/* 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; }
/* * 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); }
/* 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; }