summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2004-08-22 11:28:24 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2004-08-22 11:28:24 +0000
commite0e0140f4e63b451a110840dc5ef5c22c3ed9f7c (patch)
tree6e48d6ddc4609f9a49eb2913b145b8d1f81e5436
parent1a6a4812aa46d66ca46e308897e0cf759e42773f (diff)
downloadrockbox-e0e0140f4e63b451a110840dc5ef5c22c3ed9f7c.tar.gz
rockbox-e0e0140f4e63b451a110840dc5ef5c22c3ed9f7c.zip
Bug fix: renaming a directory could cause a name clash. New feature: rename() can now move files/directories as well.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5008 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/common/file.c42
-rw-r--r--firmware/drivers/fat.c13
-rw-r--r--firmware/export/fat.h1
3 files changed, 44 insertions, 12 deletions
diff --git a/firmware/common/file.c b/firmware/common/file.c
index e875d43f2e..546a927037 100644
--- a/firmware/common/file.c
+++ b/firmware/common/file.c
@@ -277,12 +277,16 @@ int remove(const char* name)
277int rename(const char* path, const char* newpath) 277int rename(const char* path, const char* newpath)
278{ 278{
279 int rc, fd; 279 int rc, fd;
280 DIR* dir;
280 char* nameptr; 281 char* nameptr;
282 char* dirptr;
281 struct filedesc* file; 283 struct filedesc* file;
284 char newpath2[MAX_PATH];
282 285
283 /* verify new path does not already exist */ 286 /* verify new path does not already exist */
287 /* If it is a directory, errno == EISDIR if the name exists */
284 fd = open(newpath, O_RDONLY); 288 fd = open(newpath, O_RDONLY);
285 if ( fd >= 0 ) { 289 if ( fd >= 0 || errno == EISDIR) {
286 close(fd); 290 close(fd);
287 errno = EBUSY; 291 errno = EBUSY;
288 return -1; 292 return -1;
@@ -295,25 +299,51 @@ int rename(const char* path, const char* newpath)
295 return fd * 10 - 2; 299 return fd * 10 - 2;
296 } 300 }
297 301
298 /* strip path */ 302 /* extract new file name */
299 nameptr = strrchr(newpath,'/'); 303 nameptr = strrchr(newpath,'/');
300 if (nameptr) 304 if (nameptr)
301 nameptr++; 305 nameptr++;
302 else 306 else
303 nameptr = (char*)newpath; 307 return - 3;
308
309 /* Extract new path */
310 strcpy(newpath2, newpath);
311
312 dirptr = strrchr(newpath2,'/');
313 if(dirptr)
314 *dirptr = 0;
315 else
316 return - 4;
304 317
318 dirptr = newpath2;
319
320 if(strlen(dirptr) == 0) {
321 dirptr = "/";
322 }
323
324 dir = opendir(dirptr);
325 if(!dir)
326 return - 5;
327
305 file = &openfiles[fd]; 328 file = &openfiles[fd];
306 rc = fat_rename(&file->fatfile, nameptr, file->size, file->attr); 329 rc = fat_rename(&file->fatfile, &dir->fatdir, nameptr,
330 file->size, file->attr);
307 if ( rc < 0 ) { 331 if ( rc < 0 ) {
308 DEBUGF("Failed renaming file: %d\n", rc); 332 DEBUGF("Failed renaming file: %d\n", rc);
309 errno = EIO; 333 errno = EIO;
310 return rc * 10 - 3; 334 return rc * 10 - 6;
311 } 335 }
312 336
313 rc = close(fd); 337 rc = close(fd);
314 if (rc<0) { 338 if (rc<0) {
315 errno = EIO; 339 errno = EIO;
316 return rc * 10 - 4; 340 return rc * 10 - 7;
341 }
342
343 rc = closedir(dir);
344 if (rc<0) {
345 errno = EIO;
346 return rc * 10 - 8;
317 } 347 }
318 348
319 return 0; 349 return 0;
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index 1b530153a5..e41bbaca41 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -1551,12 +1551,13 @@ int fat_remove(struct fat_file* file)
1551} 1551}
1552 1552
1553int fat_rename(struct fat_file* file, 1553int fat_rename(struct fat_file* file,
1554 const unsigned char* newname, 1554 struct fat_dir* dir,
1555 int size, 1555 const unsigned char* newname,
1556 int attr) 1556 int size,
1557 int attr)
1557{ 1558{
1558 int rc; 1559 int rc;
1559 struct fat_dir dir; 1560 struct fat_dir olddir;
1560 struct fat_file newfile = *file; 1561 struct fat_file newfile = *file;
1561 1562
1562 if ( !file->dircluster ) { 1563 if ( !file->dircluster ) {
@@ -1565,12 +1566,12 @@ int fat_rename(struct fat_file* file,
1565 } 1566 }
1566 1567
1567 /* create a temporary file handle */ 1568 /* create a temporary file handle */
1568 rc = fat_opendir(&dir, file->dircluster, NULL); 1569 rc = fat_opendir(&olddir, file->dircluster, NULL);
1569 if (rc < 0) 1570 if (rc < 0)
1570 return rc * 10 - 2; 1571 return rc * 10 - 2;
1571 1572
1572 /* create new name */ 1573 /* create new name */
1573 rc = add_dir_entry(&dir, &newfile, newname, false, false); 1574 rc = add_dir_entry(dir, &newfile, newname, false, false);
1574 if (rc < 0) 1575 if (rc < 0)
1575 return rc * 10 - 3; 1576 return rc * 10 - 3;
1576 1577
diff --git a/firmware/export/fat.h b/firmware/export/fat.h
index f4f09a2d19..6f9c9c5d11 100644
--- a/firmware/export/fat.h
+++ b/firmware/export/fat.h
@@ -89,6 +89,7 @@ extern int fat_seek(struct fat_file *ent, unsigned int sector );
89extern int fat_remove(struct fat_file *ent); 89extern int fat_remove(struct fat_file *ent);
90extern int fat_truncate(const struct fat_file *ent); 90extern int fat_truncate(const struct fat_file *ent);
91extern int fat_rename(struct fat_file* file, 91extern int fat_rename(struct fat_file* file,
92 struct fat_dir* dir,
92 const unsigned char* newname, 93 const unsigned char* newname,
93 int size, int attr); 94 int size, int attr);
94 95