]> git.sur5r.net Git - u-boot/blobdiff - fs/fat/fat.c
Merge git://git.denx.de/u-boot-fsl-qoriq
[u-boot] / fs / fat / fat.c
index bbba7947eeb7c03014238d0927ca9761c1baba55..d16883fa10d4af14be4391c33944dbc7d2a65c13 100644 (file)
@@ -14,6 +14,7 @@
 #include <config.h>
 #include <exports.h>
 #include <fat.h>
+#include <fs.h>
 #include <asm/byteorder.h>
 #include <part.h>
 #include <malloc.h>
@@ -28,11 +29,13 @@ static const int vfat_enabled = 0;
 #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++;
        }
@@ -130,10 +133,13 @@ static void get_name(dir_entry *dirent, char *s_name)
        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++;
@@ -143,7 +149,6 @@ static void get_name(dir_entry *dirent, char *s_name)
                *s_name = '\0';
        else if (*s_name == aRING)
                *s_name = DELETED_FLAG;
-       downcase(s_name);
 }
 
 static int flush_dirty_fat_buffer(fsdata *mydata);
@@ -252,8 +257,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
        int ret;
 
        if (clustnum > 0) {
-               startsect = mydata->data_begin +
-                               clustnum * mydata->clust_size;
+               startsect = clust_to_sect(mydata, clustnum);
        } else {
                startsect = mydata->rootdir_sect;
        }
@@ -491,7 +495,7 @@ read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
                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;
@@ -589,14 +593,13 @@ static int get_fs_info(fsdata *mydata)
                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;
@@ -707,13 +710,14 @@ static void fat_itr_child(fat_itr *itr, fat_itr *parent)
        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)
@@ -1028,61 +1032,38 @@ int file_fat_detectfs(void)
        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) {
@@ -1090,36 +1071,49 @@ int fat_size(const char *filename, loff_t *size)
                 * 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)
@@ -1146,6 +1140,71 @@ int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
        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)
 {
 }