#include <config.h>
#include <exports.h>
#include <fat.h>
+#include <fs.h>
#include <asm/byteorder.h>
#include <part.h>
#include <malloc.h>
#endif
/*
- * Convert a string to lowercase.
+ * Convert a string to lowercase. Converts at most 'len' characters,
+ * 'len' may be larger than the length of 'str' if 'str' is NULL
+ * terminated.
*/
-static void downcase(char *str)
+static void downcase(char *str, size_t len)
{
- while (*str != '\0') {
+ while (*str != '\0' && len--) {
*str = tolower(*str);
str++;
}
ptr = s_name;
while (*ptr && *ptr != ' ')
ptr++;
+ if (dirent->lcase & CASE_LOWER_BASE)
+ downcase(s_name, (unsigned)(ptr - s_name));
if (dirent->ext[0] && dirent->ext[0] != ' ') {
- *ptr = '.';
- ptr++;
+ *ptr++ = '.';
memcpy(ptr, dirent->ext, 3);
+ if (dirent->lcase & CASE_LOWER_EXT)
+ downcase(ptr, 3);
ptr[3] = '\0';
while (*ptr && *ptr != ' ')
ptr++;
*s_name = '\0';
else if (*s_name == aRING)
*s_name = DELETED_FLAG;
- downcase(s_name);
}
static int flush_dirty_fat_buffer(fsdata *mydata);
int ret;
if (clustnum > 0) {
- startsect = mydata->data_begin +
- clustnum * mydata->clust_size;
+ startsect = clust_to_sect(mydata, clustnum);
} else {
startsect = mydata->rootdir_sect;
}
return -1;
}
- block = memalign(ARCH_DMA_MINALIGN, cur_dev->blksz);
+ block = malloc_cache_aligned(cur_dev->blksz);
if (block == NULL) {
debug("Error: allocating block\n");
return -1;
mydata->data_begin = mydata->rootdir_sect +
mydata->rootdir_size -
(mydata->clust_size * 2);
- mydata->root_cluster = (mydata->rootdir_sect -
- mydata->data_begin) /
- mydata->clust_size;
+ mydata->root_cluster =
+ sect_to_clust(mydata, mydata->rootdir_sect);
}
mydata->fatbufnum = -1;
mydata->fat_dirty = 0;
- mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
+ mydata->fatbuf = malloc_cache_aligned(FATBUFSIZE);
if (mydata->fatbuf == NULL) {
debug("Error: allocating memory\n");
return -1;
itr->fsdata = parent->fsdata;
if (clustnum > 0) {
itr->clust = clustnum;
+ itr->is_root = 0;
} else {
itr->clust = parent->fsdata->root_cluster;
+ itr->is_root = 1;
}
itr->dent = NULL;
itr->remaining = 0;
itr->last_cluster = 0;
- itr->is_root = 0;
}
static void *next_cluster(fat_itr *itr)
return 0;
}
-int file_fat_ls(const char *dir)
-{
- fsdata fsdata;
- fat_itr itrblock, *itr = &itrblock;
- int files = 0, dirs = 0;
- int ret;
-
- ret = fat_itr_root(itr, &fsdata);
- if (ret)
- return ret;
-
- ret = fat_itr_resolve(itr, dir, TYPE_DIR);
- if (ret)
- return ret;
-
- while (fat_itr_next(itr)) {
- if (fat_itr_isdir(itr)) {
- printf(" %s/\n", itr->name);
- dirs++;
- } else {
- printf(" %8u %s\n",
- FAT2CPU32(itr->dent->size),
- itr->name);
- files++;
- }
- }
-
- printf("\n%d file(s), %d dir(s)\n\n", files, dirs);
-
- return 0;
-}
-
int fat_exists(const char *filename)
{
fsdata fsdata;
- fat_itr itrblock, *itr = &itrblock;
+ fat_itr *itr;
int ret;
+ itr = malloc_cache_aligned(sizeof(fat_itr));
+ if (!itr)
+ return 0;
ret = fat_itr_root(itr, &fsdata);
if (ret)
- return 0;
+ goto out;
ret = fat_itr_resolve(itr, filename, TYPE_ANY);
+ free(fsdata.fatbuf);
+out:
+ free(itr);
return ret == 0;
}
int fat_size(const char *filename, loff_t *size)
{
fsdata fsdata;
- fat_itr itrblock, *itr = &itrblock;
+ fat_itr *itr;
int ret;
+ itr = malloc_cache_aligned(sizeof(fat_itr));
+ if (!itr)
+ return -ENOMEM;
ret = fat_itr_root(itr, &fsdata);
if (ret)
- return ret;
+ goto out_free_itr;
ret = fat_itr_resolve(itr, filename, TYPE_FILE);
if (ret) {
* Directories don't have size, but fs_size() is not
* expected to fail if passed a directory path:
*/
+ free(fsdata.fatbuf);
fat_itr_root(itr, &fsdata);
if (!fat_itr_resolve(itr, filename, TYPE_DIR)) {
*size = 0;
- return 0;
+ ret = 0;
}
- return ret;
+ goto out_free_both;
}
*size = FAT2CPU32(itr->dent->size);
-
- return 0;
+out_free_both:
+ free(fsdata.fatbuf);
+out_free_itr:
+ free(itr);
+ return ret;
}
int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
loff_t maxsize, loff_t *actread)
{
fsdata fsdata;
- fat_itr itrblock, *itr = &itrblock;
+ fat_itr *itr;
int ret;
+ itr = malloc_cache_aligned(sizeof(fat_itr));
+ if (!itr)
+ return -ENOMEM;
ret = fat_itr_root(itr, &fsdata);
if (ret)
- return ret;
+ goto out_free_itr;
ret = fat_itr_resolve(itr, filename, TYPE_FILE);
if (ret)
- return ret;
+ goto out_free_both;
printf("reading %s\n", filename);
- return get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread);
+ ret = get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread);
+
+out_free_both:
+ free(fsdata.fatbuf);
+out_free_itr:
+ free(itr);
+ return ret;
}
int file_fat_read(const char *filename, void *buffer, int maxsize)
return ret;
}
+typedef struct {
+ struct fs_dir_stream parent;
+ struct fs_dirent dirent;
+ fsdata fsdata;
+ fat_itr itr;
+} fat_dir;
+
+int fat_opendir(const char *filename, struct fs_dir_stream **dirsp)
+{
+ fat_dir *dir;
+ int ret;
+
+ dir = malloc_cache_aligned(sizeof(*dir));
+ if (!dir)
+ return -ENOMEM;
+ memset(dir, 0, sizeof(*dir));
+
+ ret = fat_itr_root(&dir->itr, &dir->fsdata);
+ if (ret)
+ goto fail_free_dir;
+
+ ret = fat_itr_resolve(&dir->itr, filename, TYPE_DIR);
+ if (ret)
+ goto fail_free_both;
+
+ *dirsp = (struct fs_dir_stream *)dir;
+ return 0;
+
+fail_free_both:
+ free(dir->fsdata.fatbuf);
+fail_free_dir:
+ free(dir);
+ return ret;
+}
+
+int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp)
+{
+ fat_dir *dir = (fat_dir *)dirs;
+ struct fs_dirent *dent = &dir->dirent;
+
+ if (!fat_itr_next(&dir->itr))
+ return -ENOENT;
+
+ memset(dent, 0, sizeof(*dent));
+ strcpy(dent->name, dir->itr.name);
+
+ if (fat_itr_isdir(&dir->itr)) {
+ dent->type = FS_DT_DIR;
+ } else {
+ dent->type = FS_DT_REG;
+ dent->size = FAT2CPU32(dir->itr.dent->size);
+ }
+
+ *dentp = dent;
+
+ return 0;
+}
+
+void fat_closedir(struct fs_dir_stream *dirs)
+{
+ fat_dir *dir = (fat_dir *)dirs;
+ free(dir->fsdata.fatbuf);
+ free(dir);
+}
+
void fat_close(void)
{
}