Compare commits
8 Commits
checkpatch
...
fata
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cd988f165 | ||
|
|
c7195de38f | ||
|
|
35eb3ad7c8 | ||
|
|
1c624170db | ||
|
|
650dbda9cb | ||
|
|
4e783237a6 | ||
|
|
ad6be5dfa6 | ||
|
|
6f08359f92 |
284
fs/fat/fat.c
284
fs/fat/fat.c
@@ -27,6 +27,25 @@
|
|||||||
#include <linux/log2.h>
|
#include <linux/log2.h>
|
||||||
#include "fat_internal.h"
|
#include "fat_internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct fat_dir - directory stream for FAT filesystem
|
||||||
|
* @parent: generic directory stream
|
||||||
|
* @dirent: directory entry information
|
||||||
|
* @fsdata: filesystem data
|
||||||
|
* @itr: FAT iterator for traversing directory entries
|
||||||
|
*/
|
||||||
|
struct fat_dir {
|
||||||
|
struct fs_dir_stream parent;
|
||||||
|
struct fs_dirent dirent;
|
||||||
|
struct fsdata fsdata;
|
||||||
|
struct fat_itr itr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Current block device */
|
||||||
|
struct blk_desc *cur_dev;
|
||||||
|
/* Current partition information */
|
||||||
|
struct disk_partition cur_part_info;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert a string to lowercase. Converts at most 'len' characters,
|
* Convert a string to lowercase. Converts at most 'len' characters,
|
||||||
* 'len' may be larger than the length of 'str' if 'str' is NULL
|
* 'len' may be larger than the length of 'str' if 'str' is NULL
|
||||||
@@ -40,9 +59,6 @@ void downcase(char *str, size_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct blk_desc *cur_dev;
|
|
||||||
struct disk_partition cur_part_info;
|
|
||||||
|
|
||||||
int disk_read(u32 block, u32 nr_blocks, void *buf)
|
int disk_read(u32 block, u32 nr_blocks, void *buf)
|
||||||
{
|
{
|
||||||
ulong ret;
|
ulong ret;
|
||||||
@@ -96,7 +112,7 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no)
|
|||||||
|
|
||||||
/* Read the partition table, if present */
|
/* Read the partition table, if present */
|
||||||
if (part_get_info(dev_desc, part_no, &info)) {
|
if (part_get_info(dev_desc, part_no, &info)) {
|
||||||
if (part_no != 0) {
|
if (part_no) {
|
||||||
log_err("Partition %d invalid on device %d\n", part_no,
|
log_err("Partition %d invalid on device %d\n", part_no,
|
||||||
dev_desc->devnum);
|
dev_desc->devnum);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -105,8 +121,8 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no)
|
|||||||
info.start = 0;
|
info.start = 0;
|
||||||
info.size = dev_desc->lba;
|
info.size = dev_desc->lba;
|
||||||
info.blksz = dev_desc->blksz;
|
info.blksz = dev_desc->blksz;
|
||||||
info.name[0] = 0;
|
info.name[0] = '\0';
|
||||||
info.type[0] = 0;
|
info.type[0] = '\0';
|
||||||
info.bootable = 0;
|
info.bootable = 0;
|
||||||
disk_partition_clr_uuid(&info);
|
disk_partition_clr_uuid(&info);
|
||||||
}
|
}
|
||||||
@@ -144,15 +160,6 @@ static void get_name(struct dir_entry *dirent, char *s_name)
|
|||||||
*s_name = DELETED_FLAG;
|
*s_name = DELETED_FLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !CONFIG_IS_ENABLED(FAT_WRITE)
|
|
||||||
/* Stub for read only operation */
|
|
||||||
int flush_dirty_fat_buffer(struct fsdata *mydata)
|
|
||||||
{
|
|
||||||
(void)(mydata);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the entry at index 'entry' in a FAT (12/16/32) table.
|
* Get the entry at index 'entry' in a FAT (12/16/32) table.
|
||||||
* On failure 0x00 is returned.
|
* On failure 0x00 is returned.
|
||||||
@@ -300,6 +307,124 @@ get_cluster(struct fsdata *mydata, u32 clustnum, u8 *buffer, unsigned long size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* seek_clust() - seek to the cluster containing the specified position
|
||||||
|
*
|
||||||
|
* Navigate through the FAT chain to find the cluster that contains the given
|
||||||
|
* file position.
|
||||||
|
*
|
||||||
|
* @mydata: file system description
|
||||||
|
* @curclust: starting cluster
|
||||||
|
* @pos: position to seek to
|
||||||
|
* @bytesperclust: bytes per cluster
|
||||||
|
* Return: cluster number at position, or 0 on error
|
||||||
|
*/
|
||||||
|
static u32 seek_clust(struct fsdata *mydata, u32 curclust, loff_t pos,
|
||||||
|
unsigned int bytesperclust)
|
||||||
|
{
|
||||||
|
loff_t actsize = bytesperclust;
|
||||||
|
|
||||||
|
/* go to cluster at pos */
|
||||||
|
while (actsize <= pos) {
|
||||||
|
curclust = get_fatent(mydata, curclust);
|
||||||
|
if (CHECK_CLUST(curclust, mydata->fatsize)) {
|
||||||
|
debug("curclust: 0x%x\n", curclust);
|
||||||
|
printf("Invalid FAT entry\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
actsize += bytesperclust;
|
||||||
|
}
|
||||||
|
|
||||||
|
return curclust;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read_partial() - read partial data from a cluster
|
||||||
|
*
|
||||||
|
* Read data from a cluster starting at a non-zero offset. This is used when
|
||||||
|
* the read position is not cluster-aligned. A temporary buffer is used to
|
||||||
|
* read the full cluster, then the requested portion is copied out.
|
||||||
|
*
|
||||||
|
* @mydata: file system description
|
||||||
|
* @curclust: cluster to read from
|
||||||
|
* @pos: offset within cluster
|
||||||
|
* @buffer: buffer to read into
|
||||||
|
* @filesize: remaining file size
|
||||||
|
* @bytesperclust: bytes per cluster
|
||||||
|
* @gotsize: pointer to accumulate bytes read
|
||||||
|
* Return: 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
static int read_partial(struct fsdata *mydata, u32 curclust, loff_t pos,
|
||||||
|
u8 **buffer, loff_t filesize,
|
||||||
|
unsigned int bytesperclust, loff_t *gotsize)
|
||||||
|
{
|
||||||
|
u8 *tmp_buffer;
|
||||||
|
loff_t actsize;
|
||||||
|
|
||||||
|
actsize = min(filesize, (loff_t)bytesperclust);
|
||||||
|
tmp_buffer = malloc_cache_aligned(actsize);
|
||||||
|
if (!tmp_buffer) {
|
||||||
|
debug("Error: allocating buffer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_cluster(mydata, curclust, tmp_buffer, actsize)) {
|
||||||
|
printf("Error reading cluster\n");
|
||||||
|
free(tmp_buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
actsize -= pos;
|
||||||
|
memcpy(*buffer, tmp_buffer + pos, actsize);
|
||||||
|
free(tmp_buffer);
|
||||||
|
*gotsize += actsize;
|
||||||
|
*buffer += actsize;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_consecutive() - find consecutive clusters
|
||||||
|
*
|
||||||
|
* Search the FAT chain to find a run of consecutive clusters starting from
|
||||||
|
* the given cluster. This allows reading multiple clusters in a single
|
||||||
|
* operation for better performance.
|
||||||
|
*
|
||||||
|
* @mydata: file system description
|
||||||
|
* @curclust: starting cluster
|
||||||
|
* @endclust: pointer to ending cluster
|
||||||
|
* @buffer: buffer to read into
|
||||||
|
* @filesize: remaining file size
|
||||||
|
* @bytesperclust: bytes per cluster
|
||||||
|
* @actsize: pointer to actual size read
|
||||||
|
* Return: 0 if all remaining data is consecutive, 1 if not consecutive
|
||||||
|
*/
|
||||||
|
static int find_consecutive(struct fsdata *mydata, u32 curclust,
|
||||||
|
u32 *endclust, u8 *buffer, loff_t filesize,
|
||||||
|
unsigned int bytesperclust, loff_t *actsize)
|
||||||
|
{
|
||||||
|
u32 newclust;
|
||||||
|
|
||||||
|
*actsize = bytesperclust;
|
||||||
|
*endclust = curclust;
|
||||||
|
|
||||||
|
/* search for consecutive clusters */
|
||||||
|
while (*actsize < filesize) {
|
||||||
|
newclust = get_fatent(mydata, *endclust);
|
||||||
|
if ((newclust - 1) != *endclust)
|
||||||
|
return 1; /* not consecutive */
|
||||||
|
if (CHECK_CLUST(newclust, mydata->fatsize)) {
|
||||||
|
debug("curclust: 0x%x\n", newclust);
|
||||||
|
printf("Invalid FAT entry\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*endclust = newclust;
|
||||||
|
*actsize += bytesperclust;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* all remaining data is consecutive */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get_contents() - read from file
|
* get_contents() - read from file
|
||||||
*
|
*
|
||||||
@@ -321,8 +446,10 @@ static int get_contents(struct fsdata *mydata, struct dir_entry *dentptr, loff_t
|
|||||||
loff_t filesize = FAT2CPU32(dentptr->size);
|
loff_t filesize = FAT2CPU32(dentptr->size);
|
||||||
unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
|
unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
|
||||||
u32 curclust = START(dentptr);
|
u32 curclust = START(dentptr);
|
||||||
u32 endclust, newclust;
|
u32 endclust;
|
||||||
loff_t actsize;
|
loff_t actsize;
|
||||||
|
loff_t offset_in_clust;
|
||||||
|
int ret;
|
||||||
|
|
||||||
*gotsize = 0;
|
*gotsize = 0;
|
||||||
debug("Filesize: %llu bytes\n", filesize);
|
debug("Filesize: %llu bytes\n", filesize);
|
||||||
@@ -337,48 +464,26 @@ static int get_contents(struct fsdata *mydata, struct dir_entry *dentptr, loff_t
|
|||||||
|
|
||||||
debug("%llu bytes\n", filesize);
|
debug("%llu bytes\n", filesize);
|
||||||
|
|
||||||
actsize = bytesperclust;
|
/* Seek to the cluster containing pos */
|
||||||
|
curclust = seek_clust(mydata, curclust, pos, bytesperclust);
|
||||||
|
if (!curclust)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* go to cluster at pos */
|
/* Calculate offset within the cluster and adjust pos/filesize */
|
||||||
while (actsize <= pos) {
|
offset_in_clust = pos % bytesperclust;
|
||||||
curclust = get_fatent(mydata, curclust);
|
filesize -= pos - offset_in_clust;
|
||||||
if (CHECK_CLUST(curclust, mydata->fatsize)) {
|
|
||||||
debug("curclust: 0x%x\n", curclust);
|
|
||||||
printf("Invalid FAT entry\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
actsize += bytesperclust;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* actsize > pos */
|
/* Handle partial cluster read at the beginning */
|
||||||
actsize -= bytesperclust;
|
if (offset_in_clust) {
|
||||||
filesize -= actsize;
|
ret = read_partial(mydata, curclust, offset_in_clust,
|
||||||
pos -= actsize;
|
&buffer, filesize, bytesperclust,
|
||||||
|
gotsize);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* align to beginning of next cluster if any */
|
filesize -= min(filesize, (loff_t)(bytesperclust - offset_in_clust));
|
||||||
if (pos) {
|
|
||||||
u8 *tmp_buffer;
|
|
||||||
|
|
||||||
actsize = min(filesize, (loff_t)bytesperclust);
|
|
||||||
tmp_buffer = malloc_cache_aligned(actsize);
|
|
||||||
if (!tmp_buffer) {
|
|
||||||
debug("Error: allocating buffer\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_cluster(mydata, curclust, tmp_buffer, actsize) != 0) {
|
|
||||||
printf("Error reading cluster\n");
|
|
||||||
free(tmp_buffer);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
filesize -= actsize;
|
|
||||||
actsize -= pos;
|
|
||||||
memcpy(buffer, tmp_buffer + pos, actsize);
|
|
||||||
free(tmp_buffer);
|
|
||||||
*gotsize += actsize;
|
|
||||||
if (!filesize)
|
if (!filesize)
|
||||||
return 0;
|
return 0;
|
||||||
buffer += actsize;
|
|
||||||
|
|
||||||
curclust = get_fatent(mydata, curclust);
|
curclust = get_fatent(mydata, curclust);
|
||||||
if (CHECK_CLUST(curclust, mydata->fatsize)) {
|
if (CHECK_CLUST(curclust, mydata->fatsize)) {
|
||||||
@@ -388,50 +493,40 @@ static int get_contents(struct fsdata *mydata, struct dir_entry *dentptr, loff_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actsize = bytesperclust;
|
/* Read remaining data in full/partial clusters */
|
||||||
endclust = curclust;
|
while (filesize > 0) {
|
||||||
|
ret = find_consecutive(mydata, curclust, &endclust,
|
||||||
|
buffer, filesize, bytesperclust,
|
||||||
|
&actsize);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
do {
|
/* Read all consecutive clusters or remaining bytes */
|
||||||
/* search for consecutive clusters */
|
if (!ret)
|
||||||
while (actsize < filesize) {
|
actsize = filesize;
|
||||||
newclust = get_fatent(mydata, endclust);
|
|
||||||
if ((newclust - 1) != endclust)
|
|
||||||
goto getit;
|
|
||||||
if (CHECK_CLUST(newclust, mydata->fatsize)) {
|
|
||||||
debug("curclust: 0x%x\n", newclust);
|
|
||||||
printf("Invalid FAT entry\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
endclust = newclust;
|
|
||||||
actsize += bytesperclust;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get remaining bytes */
|
if (get_cluster(mydata, curclust, buffer, (int)actsize)) {
|
||||||
actsize = filesize;
|
|
||||||
if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
|
|
||||||
printf("Error reading cluster\n");
|
printf("Error reading cluster\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*gotsize += actsize;
|
*gotsize += actsize;
|
||||||
return 0;
|
|
||||||
getit:
|
|
||||||
if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
|
|
||||||
printf("Error reading cluster\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*gotsize += (int)actsize;
|
|
||||||
filesize -= actsize;
|
filesize -= actsize;
|
||||||
buffer += actsize;
|
buffer += actsize;
|
||||||
|
|
||||||
|
if (!filesize || !ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Move to next cluster */
|
||||||
curclust = get_fatent(mydata, endclust);
|
curclust = get_fatent(mydata, endclust);
|
||||||
if (CHECK_CLUST(curclust, mydata->fatsize)) {
|
if (CHECK_CLUST(curclust, mydata->fatsize)) {
|
||||||
debug("curclust: 0x%x\n", curclust);
|
debug("curclust: 0x%x\n", curclust);
|
||||||
printf("Invalid FAT entry\n");
|
printf("Invalid FAT entry\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
actsize = bytesperclust;
|
}
|
||||||
endclust = curclust;
|
|
||||||
} while (1);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -445,19 +540,19 @@ static int slot2str(struct dir_slot *slotptr, char *l_name, int *idx)
|
|||||||
|
|
||||||
for (j = 0; j <= 8; j += 2) {
|
for (j = 0; j <= 8; j += 2) {
|
||||||
l_name[*idx] = slotptr->name0_4[j];
|
l_name[*idx] = slotptr->name0_4[j];
|
||||||
if (l_name[*idx] == 0x00)
|
if (!l_name[*idx])
|
||||||
return 1;
|
return 1;
|
||||||
(*idx)++;
|
(*idx)++;
|
||||||
}
|
}
|
||||||
for (j = 0; j <= 10; j += 2) {
|
for (j = 0; j <= 10; j += 2) {
|
||||||
l_name[*idx] = slotptr->name5_10[j];
|
l_name[*idx] = slotptr->name5_10[j];
|
||||||
if (l_name[*idx] == 0x00)
|
if (!l_name[*idx])
|
||||||
return 1;
|
return 1;
|
||||||
(*idx)++;
|
(*idx)++;
|
||||||
}
|
}
|
||||||
for (j = 0; j <= 2; j += 2) {
|
for (j = 0; j <= 2; j += 2) {
|
||||||
l_name[*idx] = slotptr->name11_12[j];
|
l_name[*idx] = slotptr->name11_12[j];
|
||||||
if (l_name[*idx] == 0x00)
|
if (!l_name[*idx])
|
||||||
return 1;
|
return 1;
|
||||||
(*idx)++;
|
(*idx)++;
|
||||||
}
|
}
|
||||||
@@ -643,7 +738,7 @@ static int get_fs_info(struct fsdata *mydata)
|
|||||||
mydata->sect_size, cur_part_info.blksz);
|
mydata->sect_size, cur_part_info.blksz);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (mydata->clust_size == 0) {
|
if (!mydata->clust_size) {
|
||||||
log_err("FAT cluster size not set\n");
|
log_err("FAT cluster size not set\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -816,7 +911,7 @@ void *fat_next_cluster(struct fat_itr *itr, unsigned int *nbytes)
|
|||||||
|
|
||||||
struct dir_entry *next_dent(struct fat_itr *itr)
|
struct dir_entry *next_dent(struct fat_itr *itr)
|
||||||
{
|
{
|
||||||
if (itr->remaining == 0) {
|
if (!itr->remaining) {
|
||||||
unsigned nbytes;
|
unsigned nbytes;
|
||||||
struct dir_entry *dent = fat_next_cluster(itr, &nbytes);
|
struct dir_entry *dent = fat_next_cluster(itr, &nbytes);
|
||||||
|
|
||||||
@@ -835,7 +930,7 @@ struct dir_entry *next_dent(struct fat_itr *itr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* have we reached the last valid entry? */
|
/* have we reached the last valid entry? */
|
||||||
if (itr->dent->nameext.name[0] == 0)
|
if (!itr->dent->nameext.name[0])
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return itr->dent;
|
return itr->dent;
|
||||||
@@ -967,7 +1062,7 @@ int fat_itr_resolve(struct fat_itr *itr, const char *path, uint type)
|
|||||||
path++;
|
path++;
|
||||||
|
|
||||||
/* are we at the end? */
|
/* are we at the end? */
|
||||||
if (strlen(path) == 0) {
|
if (!strlen(path)) {
|
||||||
if (!(type & TYPE_DIR))
|
if (!(type & TYPE_DIR))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -990,7 +1085,7 @@ int fat_itr_resolve(struct fat_itr *itr, const char *path, uint type)
|
|||||||
itr->remaining = 0;
|
itr->remaining = 0;
|
||||||
itr->last_cluster = 0;
|
itr->last_cluster = 0;
|
||||||
|
|
||||||
if (next[0] == 0) {
|
if (!next[0]) {
|
||||||
if (type & TYPE_DIR)
|
if (type & TYPE_DIR)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
@@ -1084,7 +1179,7 @@ int fat_exists(const char *filename)
|
|||||||
free(fsdata.fatbuf);
|
free(fsdata.fatbuf);
|
||||||
out:
|
out:
|
||||||
free(itr);
|
free(itr);
|
||||||
return ret == 0;
|
return !ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1190,13 +1285,6 @@ int file_fat_read(const char *filename, void *buffer, int maxsize)
|
|||||||
return actread;
|
return actread;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fat_dir {
|
|
||||||
struct fs_dir_stream parent;
|
|
||||||
struct fs_dirent dirent;
|
|
||||||
struct fsdata fsdata;
|
|
||||||
struct fat_itr itr;
|
|
||||||
};
|
|
||||||
|
|
||||||
int fat_opendir(const char *filename, struct fs_dir_stream **dirsp)
|
int fat_opendir(const char *filename, struct fs_dir_stream **dirsp)
|
||||||
{
|
{
|
||||||
struct fat_dir *dir;
|
struct fat_dir *dir;
|
||||||
|
|||||||
@@ -111,7 +111,14 @@ int disk_read(u32 block, u32 nr_blocks, void *buf);
|
|||||||
* @mydata: filesystem data
|
* @mydata: filesystem data
|
||||||
* Return: 0 on success, -1 on error
|
* Return: 0 on success, -1 on error
|
||||||
*/
|
*/
|
||||||
|
#if CONFIG_IS_ENABLED(FAT_WRITE)
|
||||||
int flush_dirty_fat_buffer(struct fsdata *mydata);
|
int flush_dirty_fat_buffer(struct fsdata *mydata);
|
||||||
|
#else
|
||||||
|
static inline int flush_dirty_fat_buffer(struct fsdata *mydata)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Internal function declarations */
|
/* Internal function declarations */
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include <linux/math64.h>
|
#include <linux/math64.h>
|
||||||
#include "fat_internal.h"
|
#include "fat_internal.h"
|
||||||
|
|
||||||
static struct dir_entry *find_directory_entry(struct fat_itr *itr, char *filename);
|
|
||||||
static int new_dir_table(struct fat_itr *itr);
|
static int new_dir_table(struct fat_itr *itr);
|
||||||
|
|
||||||
/* Characters that may only be used in long file names */
|
/* Characters that may only be used in long file names */
|
||||||
@@ -32,6 +31,40 @@ static const char LONG_ONLY_CHARS[] = "+,;=[]";
|
|||||||
/* Combined size of the name and ext fields in the directory entry */
|
/* Combined size of the name and ext fields in the directory entry */
|
||||||
#define SHORT_NAME_SIZE 11
|
#define SHORT_NAME_SIZE 11
|
||||||
|
|
||||||
|
/* Total number of sectors in the partition */
|
||||||
|
static int total_sector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find_dir_entry() - find a directory entry by filename
|
||||||
|
*
|
||||||
|
* @itr: directory iterator
|
||||||
|
* @filename: name of file to find
|
||||||
|
* Return: directory entry or NULL
|
||||||
|
*/
|
||||||
|
static struct dir_entry *find_dir_entry(struct fat_itr *itr, char *filename)
|
||||||
|
{
|
||||||
|
int match = 0;
|
||||||
|
|
||||||
|
while (fat_itr_next(itr)) {
|
||||||
|
/* check both long and short name: */
|
||||||
|
if (!strcasecmp(filename, itr->name))
|
||||||
|
match = 1;
|
||||||
|
else if (itr->name != itr->s_name &&
|
||||||
|
!strcasecmp(filename, itr->s_name))
|
||||||
|
match = 1;
|
||||||
|
|
||||||
|
if (!match)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (itr->dent->nameext.name[0] == '\0')
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return itr->dent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* str2fat() - convert string to valid FAT name characters
|
* str2fat() - convert string to valid FAT name characters
|
||||||
*
|
*
|
||||||
@@ -177,7 +210,7 @@ static int set_name(struct fat_itr *itr, const char *filename, char *shortname)
|
|||||||
ret = fat_move_to_cluster(itr, itr->start_clust);
|
ret = fat_move_to_cluster(itr, itr->start_clust);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
if (find_directory_entry(itr, buf))
|
if (find_dir_entry(itr, buf))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
goto out_ret;
|
goto out_ret;
|
||||||
@@ -192,7 +225,6 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int total_sector;
|
|
||||||
static int disk_write(u32 block, u32 nr_blocks, void *buf)
|
static int disk_write(u32 block, u32 nr_blocks, void *buf)
|
||||||
{
|
{
|
||||||
ulong ret;
|
ulong ret;
|
||||||
@@ -207,7 +239,7 @@ static int disk_write(u32 block, u32 nr_blocks, void *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = blk_dwrite(cur_dev, cur_part_info.start + block, nr_blocks, buf);
|
ret = blk_dwrite(cur_dev, cur_part_info.start + block, nr_blocks, buf);
|
||||||
if (nr_blocks && ret == 0)
|
if (nr_blocks && !ret)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -322,7 +354,7 @@ static int str2slot(struct dir_slot *slotptr, const char *name, int *idx)
|
|||||||
int j, end_idx = 0;
|
int j, end_idx = 0;
|
||||||
|
|
||||||
for (j = 0; j <= 8; j += 2) {
|
for (j = 0; j <= 8; j += 2) {
|
||||||
if (name[*idx] == 0x00) {
|
if (!name[*idx]) {
|
||||||
slotptr->name0_4[j] = 0;
|
slotptr->name0_4[j] = 0;
|
||||||
slotptr->name0_4[j + 1] = 0;
|
slotptr->name0_4[j + 1] = 0;
|
||||||
end_idx++;
|
end_idx++;
|
||||||
@@ -333,7 +365,7 @@ static int str2slot(struct dir_slot *slotptr, const char *name, int *idx)
|
|||||||
end_idx++;
|
end_idx++;
|
||||||
}
|
}
|
||||||
for (j = 0; j <= 10; j += 2) {
|
for (j = 0; j <= 10; j += 2) {
|
||||||
if (name[*idx] == 0x00) {
|
if (!name[*idx]) {
|
||||||
slotptr->name5_10[j] = 0;
|
slotptr->name5_10[j] = 0;
|
||||||
slotptr->name5_10[j + 1] = 0;
|
slotptr->name5_10[j + 1] = 0;
|
||||||
end_idx++;
|
end_idx++;
|
||||||
@@ -344,7 +376,7 @@ static int str2slot(struct dir_slot *slotptr, const char *name, int *idx)
|
|||||||
end_idx++;
|
end_idx++;
|
||||||
}
|
}
|
||||||
for (j = 0; j <= 2; j += 2) {
|
for (j = 0; j <= 2; j += 2) {
|
||||||
if (name[*idx] == 0x00) {
|
if (!name[*idx]) {
|
||||||
slotptr->name11_12[j] = 0;
|
slotptr->name11_12[j] = 0;
|
||||||
slotptr->name11_12[j + 1] = 0;
|
slotptr->name11_12[j + 1] = 0;
|
||||||
end_idx++;
|
end_idx++;
|
||||||
@@ -355,7 +387,7 @@ static int str2slot(struct dir_slot *slotptr, const char *name, int *idx)
|
|||||||
end_idx++;
|
end_idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name[*idx] == 0x00)
|
if (!name[*idx])
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -411,7 +443,7 @@ fill_dir_slot(struct fat_itr *itr, const char *l_name, const char *shortname)
|
|||||||
slotptr->attr = ATTR_VFAT;
|
slotptr->attr = ATTR_VFAT;
|
||||||
slotptr->alias_checksum = checksum;
|
slotptr->alias_checksum = checksum;
|
||||||
slotptr++;
|
slotptr++;
|
||||||
} while (ret == 0);
|
} while (!ret);
|
||||||
|
|
||||||
slotptr--;
|
slotptr--;
|
||||||
slotptr->id |= LAST_LONG_ENTRY_MASK;
|
slotptr->id |= LAST_LONG_ENTRY_MASK;
|
||||||
@@ -552,7 +584,7 @@ static u32 determine_fatent(struct fsdata *mydata, u32 entry)
|
|||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
next_fat = get_fatent(mydata, next_entry);
|
next_fat = get_fatent(mydata, next_entry);
|
||||||
if (next_fat == 0) {
|
if (!next_fat) {
|
||||||
/* found free entry, link to entry */
|
/* found free entry, link to entry */
|
||||||
set_fatent_value(mydata, entry, next_entry);
|
set_fatent_value(mydata, entry, next_entry);
|
||||||
break;
|
break;
|
||||||
@@ -809,7 +841,7 @@ static int find_empty_cluster(struct fsdata *mydata)
|
|||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
fat_val = get_fatent(mydata, entry);
|
fat_val = get_fatent(mydata, entry);
|
||||||
if (fat_val == 0)
|
if (!fat_val)
|
||||||
break;
|
break;
|
||||||
entry++;
|
entry++;
|
||||||
}
|
}
|
||||||
@@ -869,7 +901,7 @@ static int clear_fatent(struct fsdata *mydata, u32 entry)
|
|||||||
|
|
||||||
while (!CHECK_CLUST(entry, mydata->fatsize)) {
|
while (!CHECK_CLUST(entry, mydata->fatsize)) {
|
||||||
fat_val = get_fatent(mydata, entry);
|
fat_val = get_fatent(mydata, entry);
|
||||||
if (fat_val != 0)
|
if (fat_val)
|
||||||
set_fatent_value(mydata, entry, 0);
|
set_fatent_value(mydata, entry, 0);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@@ -912,7 +944,7 @@ static int check_overflow(struct fsdata *mydata, u32 clustnum, loff_t size)
|
|||||||
|
|
||||||
sect_num = div_u64_rem(size, mydata->sect_size, &offset);
|
sect_num = div_u64_rem(size, mydata->sect_size, &offset);
|
||||||
|
|
||||||
if (offset != 0)
|
if (offset)
|
||||||
sect_num++;
|
sect_num++;
|
||||||
|
|
||||||
if (startsect + sect_num > total_sector)
|
if (startsect + sect_num > total_sector)
|
||||||
@@ -1115,7 +1147,7 @@ set_clusters:
|
|||||||
|
|
||||||
/* set remaining bytes */
|
/* set remaining bytes */
|
||||||
actsize = filesize;
|
actsize = filesize;
|
||||||
if (set_cluster(mydata, curclust, buffer, (u32)actsize) != 0) {
|
if (set_cluster(mydata, curclust, buffer, (u32)actsize)) {
|
||||||
debug("error: writing cluster\n");
|
debug("error: writing cluster\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1132,7 +1164,7 @@ set_clusters:
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
getit:
|
getit:
|
||||||
if (set_cluster(mydata, curclust, buffer, (u32)actsize) != 0) {
|
if (set_cluster(mydata, curclust, buffer, (u32)actsize)) {
|
||||||
debug("error: writing cluster\n");
|
debug("error: writing cluster\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1335,37 +1367,6 @@ static int create_link(struct fat_itr *itr, char *basename, u32 clust, u32 size,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* find_directory_entry() - find a directory entry by filename
|
|
||||||
*
|
|
||||||
* @itr: directory iterator
|
|
||||||
* @filename: name of file to find
|
|
||||||
* Return: directory entry or NULL
|
|
||||||
*/
|
|
||||||
static struct dir_entry *find_directory_entry(struct fat_itr *itr, char *filename)
|
|
||||||
{
|
|
||||||
int match = 0;
|
|
||||||
|
|
||||||
while (fat_itr_next(itr)) {
|
|
||||||
/* check both long and short name: */
|
|
||||||
if (!strcasecmp(filename, itr->name))
|
|
||||||
match = 1;
|
|
||||||
else if (itr->name != itr->s_name &&
|
|
||||||
!strcasecmp(filename, itr->s_name))
|
|
||||||
match = 1;
|
|
||||||
|
|
||||||
if (!match)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (itr->dent->nameext.name[0] == '\0')
|
|
||||||
return NULL;
|
|
||||||
else
|
|
||||||
return itr->dent;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int split_filename(char *filename, char **dirname, char **basename)
|
static int split_filename(char *filename, char **dirname, char **basename)
|
||||||
{
|
{
|
||||||
char *p, *last_slash, *last_slash_cont;
|
char *p, *last_slash, *last_slash_cont;
|
||||||
@@ -1517,7 +1518,7 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
retdent = find_directory_entry(itr, l_filename);
|
retdent = find_dir_entry(itr, l_filename);
|
||||||
|
|
||||||
if (retdent) {
|
if (retdent) {
|
||||||
if (fat_itr_isdir(itr)) {
|
if (fat_itr_isdir(itr)) {
|
||||||
@@ -1757,7 +1758,7 @@ int fat_unlink(const char *filename)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!find_directory_entry(itr, basename)) {
|
if (!find_dir_entry(itr, basename)) {
|
||||||
log_err("%s: doesn't exist (%d)\n", basename, -ENOENT);
|
log_err("%s: doesn't exist (%d)\n", basename, -ENOENT);
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -1834,7 +1835,7 @@ int fat_mkdir(const char *dirname)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
retdent = find_directory_entry(itr, l_dirname);
|
retdent = find_dir_entry(itr, l_dirname);
|
||||||
|
|
||||||
if (retdent) {
|
if (retdent) {
|
||||||
printf("%s: already exists\n", l_dirname);
|
printf("%s: already exists\n", l_dirname);
|
||||||
@@ -2040,7 +2041,7 @@ int fat_rename(const char *old_path, const char *new_path)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!find_directory_entry(old_itr, old_basename)) {
|
if (!find_dir_entry(old_itr, old_basename)) {
|
||||||
log_debug("%s doesn't exist (%d)\n", old_basename, -ENOENT);
|
log_debug("%s doesn't exist (%d)\n", old_basename, -ENOENT);
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -2063,7 +2064,7 @@ int fat_rename(const char *old_path, const char *new_path)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
found_existing = find_directory_entry(new_itr, l_new_basename);
|
found_existing = find_dir_entry(new_itr, l_new_basename);
|
||||||
|
|
||||||
if (found_existing) {
|
if (found_existing) {
|
||||||
/* store cluster of new_path since it may need to be deleted */
|
/* store cluster of new_path since it may need to be deleted */
|
||||||
@@ -2147,7 +2148,7 @@ int fat_rename(const char *old_path, const char *new_path)
|
|||||||
struct dir_entry *dent;
|
struct dir_entry *dent;
|
||||||
|
|
||||||
fat_itr_child(new_itr, new_itr);
|
fat_itr_child(new_itr, new_itr);
|
||||||
dent = find_directory_entry(new_itr, "..");
|
dent = find_dir_entry(new_itr, "..");
|
||||||
if (!dent) {
|
if (!dent) {
|
||||||
log_debug("FAT filesystem corrupt!\n");
|
log_debug("FAT filesystem corrupt!\n");
|
||||||
log_debug("dir %s has no parent direntry\n",
|
log_debug("dir %s has no parent direntry\n",
|
||||||
|
|||||||
Reference in New Issue
Block a user