summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2002-11-19 12:48:50 +0000
committerBjörn Stenberg <bjorn@haxx.se>2002-11-19 12:48:50 +0000
commitc5f5be565ea5488b3c6ba18b4af7696ef0cd92b8 (patch)
tree4bb0853b28ed368f04472372331b2bce7df5418d /firmware
parentfde9b57f7010369800d56b6b2eb98e6593236e13 (diff)
downloadrockbox-c5f5be565ea5488b3c6ba18b4af7696ef0cd92b8.zip
rockbox-c5f5be565ea5488b3c6ba18b4af7696ef0cd92b8.tar.gz
rockbox-c5f5be565ea5488b3c6ba18b4af7696ef0cd92b8.tar.bz2
rockbox-c5f5be565ea5488b3c6ba18b4af7696ef0cd92b8.tar.xz
Added rename()
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2857 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/common/file.c57
-rw-r--r--firmware/common/file.h2
-rw-r--r--firmware/drivers/fat.c159
-rw-r--r--firmware/drivers/fat.h3
4 files changed, 163 insertions, 58 deletions
diff --git a/firmware/common/file.c b/firmware/common/file.c
index 01a0ebf..1d78dcb 100644
--- a/firmware/common/file.c
+++ b/firmware/common/file.c
@@ -125,7 +125,7 @@ int open(const char* pathname, int flags)
break;
}
}
- closedir(dir);
+
if ( !entry ) {
LDEBUGF("Didn't find file %s\n",name);
if ( file->write && (flags & O_CREAT) ) {
@@ -135,6 +135,7 @@ int open(const char* pathname, int flags)
DEBUGF("Couldn't create %s in %s\n",name,pathname);
errno = EIO;
file->busy = false;
+ closedir(dir);
return -5;
}
file->size = 0;
@@ -143,9 +144,11 @@ int open(const char* pathname, int flags)
DEBUGF("Couldn't find %s in %s\n",name,pathname);
errno = ENOENT;
file->busy = false;
+ closedir(dir);
return -6;
}
}
+ closedir(dir);
file->cacheoffset = -1;
file->fileoffset = 0;
@@ -205,23 +208,69 @@ int remove(const char* name)
file = &openfiles[fd];
rc = fat_truncate(&(file->fatfile));
if ( rc < 0 ) {
- DEBUGF("Failed truncating file\n");
+ DEBUGF("Failed truncating file: %d\n", rc);
errno = EIO;
return -1;
}
rc = fat_remove(&(file->fatfile));
if ( rc < 0 ) {
- DEBUGF("Failed removing file\n");
+ DEBUGF("Failed removing file: %d\n", rc);
errno = EIO;
return -2;
}
file->size = 0;
+ rc = close(fd);
+ if (rc<0)
+ return -3;
+
+ return 0;
+}
+
+int rename(const char* path, const char* newpath)
+{
+ int rc, fd;
+ char* nameptr;
+ struct filedesc* file;
+
+ /* verify new path does not already exist */
+ fd = open(newpath, O_RDONLY);
+ if ( fd >= 0 ) {
+ errno = EBUSY;
+ return fd;
+ }
close(fd);
- return rc;
+ fd = open(path, O_RDONLY);
+ if ( fd < 0 ) {
+ errno = EIO;
+ return fd;
+ }
+
+ /* strip path */
+ nameptr = strrchr(newpath,'/');
+ if (nameptr)
+ nameptr++;
+ else
+ nameptr = (char*)newpath;
+
+ file = &openfiles[fd];
+ rc = fat_rename(&file->fatfile, nameptr, file->size);
+ if ( rc < 0 ) {
+ DEBUGF("Failed renaming file: %d\n", rc);
+ errno = EIO;
+ return -1;
+ }
+
+ rc = close(fd);
+ if (rc<0) {
+ errno = EIO;
+ return -2;
+ }
+
+ return 0;
}
int ftruncate(int fd, unsigned int size)
diff --git a/firmware/common/file.h b/firmware/common/file.h
index bf7ad82..bf8dc38 100644
--- a/firmware/common/file.h
+++ b/firmware/common/file.h
@@ -58,7 +58,7 @@ extern int lseek(int fd, int offset, int whence);
extern int creat(const char *pathname, int mode);
extern int write(int fd, void* buf, int count);
extern int remove(const char* pathname);
-extern int rename(const char* oldname, const char* newname);
+extern int rename(const char* path, const char* newname);
extern int ftruncate(int fd, unsigned int size);
#else
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index 2ff36e2..b6bedc1 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -1175,6 +1175,68 @@ int fat_closewrite(struct fat_file *file, int size)
return 0;
}
+static int free_direntries(int dircluster, int startentry, int numentries)
+{
+ unsigned char buf[SECTOR_SIZE];
+ struct fat_file dir;
+ unsigned int entry = startentry - numentries + 1;
+ unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR;
+ int i;
+ int err;
+
+ /* create a temporary file handle for the dir holding this file */
+ err = fat_open(dircluster, &dir, NULL);
+ if (err<0)
+ return -1;
+
+ err = fat_seek( &dir, sector );
+ if (err<0)
+ return -2;
+
+ err = fat_readwrite(&dir, 1, buf, false);
+ if (err<1)
+ return -3;
+
+ for (i=0; i < numentries; i++) {
+ LDEBUGF("Clearing dir entry %d (%d/%d)\n",
+ entry, i+1, numentries);
+ buf[(entry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE] = 0xe5;
+ entry++;
+
+ if ( (entry % DIR_ENTRIES_PER_SECTOR) == 0 ) {
+ /* flush this sector */
+ err = fat_seek(&dir, sector);
+ if (err<0)
+ return -4;
+
+ err = fat_readwrite(&dir, 1, buf, true);
+ if (err<1)
+ return -5;
+
+ if ( i+1 < numentries ) {
+ /* read next sector */
+ err = fat_readwrite(&dir, 1, buf, false);
+ if (err<1)
+ return -6;
+ }
+ sector++;
+ }
+ }
+
+ if ( entry % DIR_ENTRIES_PER_SECTOR ) {
+ /* flush this sector */
+ err = fat_seek(&dir, sector);
+ if (err<0)
+ return -7;
+
+ err = fat_readwrite(&dir, 1, buf, true);
+ if (err<1)
+ return -8;
+ }
+
+ return 0;
+}
+
int fat_remove(struct fat_file* file)
{
int next, last = file->firstcluster;
@@ -1187,68 +1249,59 @@ int fat_remove(struct fat_file* file)
last = next;
}
- /* free all dir entries */
- if ( file->dircluster ) {
- unsigned char buf[SECTOR_SIZE];
- struct fat_file dir;
- unsigned int entry = file->direntry - file->direntries + 1;
- unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR;
- unsigned int i;
- int err;
-
- /* create a temporary file handle for the dir holding this file */
- err = fat_open(file->dircluster, &dir, NULL);
- if (err<0)
+ if ( file->dircluster )
+ if ( free_direntries(file->dircluster,
+ file->direntry,
+ file->direntries) < 0 )
return -1;
- err = fat_seek( &dir, sector );
- if (err<0)
- return -2;
+ file->firstcluster = 0;
+ file->dircluster = 0;
- err = fat_readwrite(&dir, 1, buf, false);
- if (err<1)
- return -3;
+ return 0;
+}
- for (i=0; i < file->direntries; i++) {
- LDEBUGF("Clearing dir entry %d (%d/%d)\n",
- entry, i+1, file->direntries);
- buf[(entry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE] = 0xe5;
- entry++;
+int fat_rename(struct fat_file* file,
+ unsigned char* newname,
+ int size)
+{
+ int err;
+ struct fat_dir dir;
+ struct fat_file newfile = *file;
- if ( (entry % DIR_ENTRIES_PER_SECTOR) == 0 ) {
- /* flush this sector */
- err = fat_seek(&dir, sector);
- if (err<0)
- return -4;
+ if ( !file->dircluster ) {
+ LDEBUGF("File has no dir cluster!\n");
+ return -1;
+ }
- err = fat_readwrite(&dir, 1, buf, true);
- if (err<1)
- return -5;
+ /* create a temporary file handle */
+ LDEBUGF("create a temporary file handle: fat_opendir(%x,%x)\n",
+ &dir, file->dircluster);
+ err = fat_opendir(&dir, file->dircluster);
+ if (err<0)
+ return -2;
- if ( i+1 < file->direntries ) {
- /* read next sector */
- err = fat_readwrite(&dir, 1, buf, false);
- if (err<1)
- return -6;
- }
- sector++;
- }
- }
+ /* create new name */
+ LDEBUGF("create new name\n");
+ err = add_dir_entry(&dir, &newfile, newname);
+ if (err<0)
+ return -3;
- if ( entry % DIR_ENTRIES_PER_SECTOR ) {
- /* flush this sector */
- err = fat_seek(&dir, sector);
- if (err<0)
- return -7;
-
- err = fat_readwrite(&dir, 1, buf, true);
- if (err<1)
- return -8;
- }
- }
+ /* write size and cluster link */
+ LDEBUGF("write size and cluster link\n");
+ err = update_file_size(&newfile, size);
+ if (err<0)
+ return -4;
- file->firstcluster = 0;
- file->dircluster = 0;
+ /* remove old name */
+ LDEBUGF("remove old name\n");
+ err = free_direntries(file->dircluster, file->direntry, file->direntries);
+ if (err<0)
+ return -5;
+
+ err = flush_fat();
+ if (err<0)
+ return -6;
return 0;
}
diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h
index a5abfd5..d81ec65 100644
--- a/firmware/drivers/fat.h
+++ b/firmware/drivers/fat.h
@@ -84,6 +84,9 @@ extern int fat_closewrite(struct fat_file *ent, int size);
extern int fat_seek(struct fat_file *ent, unsigned int sector );
extern int fat_remove(struct fat_file *ent);
extern int fat_truncate(struct fat_file *ent);
+extern int fat_rename(struct fat_file* file,
+ unsigned char* newname,
+ int size);
extern int fat_opendir(struct fat_dir *ent, unsigned int currdir);
extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry);