summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2004-01-15 14:30:59 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2004-01-15 14:30:59 +0000
commit60b1c4bbe1099980ced1f69a9a51674f6e05dd3e (patch)
treef09a4c07a72df14c8c217c7457acd66269aa45d3
parenta73cc6afa2c6f5c244aa1ecc1acfa0f6b6fb6422 (diff)
downloadrockbox-60b1c4bbe1099980ced1f69a9a51674f6e05dd3e.tar.gz
rockbox-60b1c4bbe1099980ced1f69a9a51674f6e05dd3e.zip
Implemented the mkdir() function in the FAT32 driver
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4238 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/common/dir.c52
-rw-r--r--firmware/drivers/fat.c88
-rw-r--r--firmware/export/fat.h5
-rw-r--r--firmware/test/fat/main.c22
-rw-r--r--firmware/test/fat/test.sh23
5 files changed, 172 insertions, 18 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c
index 61c3ccbf90..98adc5c730 100644
--- a/firmware/common/dir.c
+++ b/firmware/common/dir.c
@@ -114,3 +114,55 @@ struct dirent* readdir(DIR* dir)
return theent;
}
+
+int mkdir(char *name)
+{
+ DIR *dir;
+ char namecopy[MAX_PATH];
+ char* end;
+ char *basename;
+ char *parent;
+ struct dirent *entry;
+ struct fat_dir newdir;
+ int rc;
+
+ if ( name[0] != '/' ) {
+ DEBUGF("Only absolute paths supported right now\n");
+ return -1;
+ }
+
+ strncpy(namecopy,name,sizeof(namecopy));
+ namecopy[sizeof(namecopy)-1] = 0;
+
+ /* Split the base name and the path */
+ end = strrchr(namecopy, '/');
+ *end = 0;
+ basename = end+1;
+
+ if(namecopy == end) /* Root dir? */
+ parent = "/";
+ else
+ parent = namecopy;
+
+ DEBUGF("mkdir: parent: %s, name: %s\n", parent, basename);
+
+ dir = opendir(parent);
+
+ if(!dir) {
+ DEBUGF("mkdir: can't open parent dir\n");
+ return -2;
+ }
+
+ /* Now check if the name already exists */
+ while ((entry = readdir(dir))) {
+ if ( !strcasecmp(basename, entry->d_name) ) {
+ DEBUGF("mkdir error: file exists\n");
+ errno = EEXIST;
+ return - 3;
+ }
+ }
+
+ rc = fat_create_dir(basename, &newdir, &(dir->fatdir));
+
+ return rc;
+}
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index 02d472ceeb..55e6fa30cf 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -811,7 +811,8 @@ static int write_long_name(struct fat_file* file,
unsigned int firstentry,
unsigned int numentries,
unsigned char* name,
- unsigned char* shortname)
+ unsigned char* shortname,
+ bool is_directory)
{
unsigned char buf[SECTOR_SIZE];
unsigned char* entry;
@@ -918,7 +919,7 @@ static int write_long_name(struct fat_file* file,
unsigned short date=0, time=0, tenth=0;
LDEBUGF("Shortname entry: %.13s\n", shortname);
strncpy(entry + FATDIR_NAME, shortname, 11);
- entry[FATDIR_ATTR] = 0;
+ entry[FATDIR_ATTR] = is_directory?FAT_ATTR_DIRECTORY:0;
entry[FATDIR_NTRES] = 0;
fat_time(&date, &time, &tenth);
@@ -947,7 +948,9 @@ static int write_long_name(struct fat_file* file,
static int add_dir_entry(struct fat_dir* dir,
struct fat_file* file,
- char* name)
+ char* name,
+ bool is_directory,
+ bool dotdir)
{
unsigned char buf[SECTOR_SIZE];
unsigned char shortname[16];
@@ -963,16 +966,26 @@ static int add_dir_entry(struct fat_dir* dir,
LDEBUGF( "add_dir_entry(%s,%x)\n",
name, file->firstcluster);
- /* create dos name */
- rc = create_dos_name(name, shortname);
- if (rc < 0)
- return rc * 10 - 0;
+ /* The "." and ".." directory entries must not be long names */
+ if(dotdir) {
+ int i;
+ strncpy(shortname, name, 16);
+ for(i = strlen(shortname);i < 12;i++)
+ shortname[i] = ' ';
+
+ entries_needed = 1;
+ } else {
+ /* create dos name */
+ rc = create_dos_name(name, shortname);
+ if (rc < 0)
+ return rc * 10 - 0;
- /* one dir entry needed for every 13 bytes of filename,
- plus one entry for the short name */
- entries_needed = namelen / NAME_BYTES_PER_ENTRY + 1;
- if (namelen % NAME_BYTES_PER_ENTRY)
- entries_needed++;
+ /* one dir entry needed for every 13 bytes of filename,
+ plus one entry for the short name */
+ entries_needed = namelen / NAME_BYTES_PER_ENTRY + 1;
+ if (namelen % NAME_BYTES_PER_ENTRY)
+ entries_needed++;
+ }
restart:
firstentry = 0;
@@ -1065,7 +1078,7 @@ static int add_dir_entry(struct fat_dir* dir,
firstentry, sector);
rc = write_long_name(&dir->file, firstentry,
- entries_needed, name, shortname);
+ entries_needed, name, shortname, is_directory);
if (rc < 0)
return rc * 10 - 5;
@@ -1304,7 +1317,7 @@ int fat_create_file(char* name,
int rc;
LDEBUGF("fat_create_file(\"%s\",%x,%x)\n",name,file,dir);
- rc = add_dir_entry(dir, file, name);
+ rc = add_dir_entry(dir, file, name, false, false);
if (!rc) {
file->firstcluster = 0;
file->lastcluster = 0;
@@ -1317,6 +1330,51 @@ int fat_create_file(char* name,
return rc;
}
+int fat_create_dir(char* name,
+ struct fat_dir* newdir,
+ struct fat_dir* dir)
+{
+ int rc;
+ struct fat_file dummyfile;
+
+ LDEBUGF("fat_create_dir(\"%s\",%x,%x)\n",name,newdir,dir);
+
+ memset(newdir, sizeof(struct fat_dir), 0);
+
+ /* First, add the entry in the parent directory */
+ rc = add_dir_entry(dir, &newdir->file, name, true, false);
+ if (rc < 0)
+ return rc * 10 - 1;
+
+ /* Then add the "." entry */
+ rc = add_dir_entry(newdir, &dummyfile, ".", true, true);
+ if (rc < 0)
+ return rc * 10 - 2;
+ dummyfile.firstcluster = newdir->file.firstcluster;
+ update_short_entry(&dummyfile, 0, FAT_ATTR_DIRECTORY);
+
+ /* and the ".." entry */
+ rc = add_dir_entry(newdir, &dummyfile, "..", true, true);
+ if (rc < 0)
+ return rc * 10 - 3;
+
+ /* The root cluster is cluster 0 in the ".." entry */
+ if(dir->file.firstcluster == fat_bpb.bpb_rootclus)
+ dummyfile.firstcluster = 0;
+ else
+ dummyfile.firstcluster = dir->file.firstcluster;
+ update_short_entry(&dummyfile, 0, FAT_ATTR_DIRECTORY);
+
+ /* Set the firstcluster field in the direntry */
+ update_short_entry(&newdir->file, 0, FAT_ATTR_DIRECTORY);
+
+ rc = flush_fat();
+ if (rc < 0)
+ return rc * 10 - 4;
+
+ return rc;
+}
+
int fat_truncate(struct fat_file *file)
{
/* truncate trailing clusters */
@@ -1487,7 +1545,7 @@ int fat_rename(struct fat_file* file,
return rc * 10 - 2;
/* create new name */
- rc = add_dir_entry(&dir, &newfile, newname);
+ rc = add_dir_entry(&dir, &newfile, newname, false, false);
if (rc < 0)
return rc * 10 - 3;
diff --git a/firmware/export/fat.h b/firmware/export/fat.h
index 921f04eb8d..dbc0ab20cc 100644
--- a/firmware/export/fat.h
+++ b/firmware/export/fat.h
@@ -72,8 +72,9 @@ struct fat_dir
extern int fat_mount(int startsector);
extern void fat_size(unsigned int* size, unsigned int* free);
extern void fat_recalc_free(void);
-
-extern int fat_create_dir(unsigned int currdir, char *name);
+extern int fat_create_dir(char* name,
+ struct fat_dir* newdir,
+ struct fat_dir* dir);
extern int fat_startsector(void);
extern int fat_open(unsigned int cluster,
struct fat_file* ent,
diff --git a/firmware/test/fat/main.c b/firmware/test/fat/main.c
index 9c1b983925..37ea2f49be 100644
--- a/firmware/test/fat/main.c
+++ b/firmware/test/fat/main.c
@@ -486,6 +486,21 @@ int dbg_trunc(char* name, int size)
return close(fd);
}
+int dbg_mkdir(char* name)
+{
+ char text[BUFSIZE+1];
+ int i;
+ int fd;
+ int x=0;
+ bool stop = false;
+
+ fd = mkdir(name);
+ if (fd<0) {
+ DEBUGF("Failed creating directory\n");
+ return -1;
+ }
+}
+
int dbg_cmd(int argc, char *argv[])
{
char* cmd = NULL;
@@ -577,6 +592,13 @@ int dbg_cmd(int argc, char *argv[])
}
}
+ if (!strcasecmp(cmd, "mkdir"))
+ {
+ if (arg1) {
+ return dbg_mkdir(arg1);
+ }
+ }
+
if (!strcasecmp(cmd, "del"))
{
if (arg1)
diff --git a/firmware/test/fat/test.sh b/firmware/test/fat/test.sh
index 44ff6bb849..9b1036b69c 100644
--- a/firmware/test/fat/test.sh
+++ b/firmware/test/fat/test.sh
@@ -38,9 +38,20 @@ buildimage() {
runtests() {
rm $RESULT
+ echo ---Test: create a long name directory in the root
+ try mkdir "/very long subdir name"
+ check
+ try mkdir "/very long subdir name/apa.monkey.me.now"
+ check
+
+ echo ---Test: create a directory called "dir"
+ try mkdir "/dir"
+ check
+
echo ---Test: create a 10K file
try mkfile "/really long filenames rock" 10
check
+
try mkfile /dir/apa.monkey.me.now 10
check
try chkfile "/really long filenames rock" 10
@@ -100,24 +111,34 @@ runtests() {
}
+echo "--------------------------------------"
echo "Building test image (4 sector/cluster)"
+echo "--------------------------------------"
buildimage 4
runtests
+echo "---------------------------------------"
echo "Building test image (32 sectors/cluster)"
+echo "---------------------------------------"
buildimage 32
runtests
+echo "--------------------------------------"
echo "Building test image (1 sector/cluster)"
+echo "--------------------------------------"
buildimage 1
runtests
+echo "--------------------------------------"
echo "Building test image (8 sectors/cluster)"
+echo "--------------------------------------"
buildimage 8
runtests
+echo "----------------------------------------"
echo "Building test image (128 sectors/cluster)"
+echo "----------------------------------------"
buildimage 128
runtests
-echo "== Test completed sucessfully =="
+echo "== Test completed successfully =="