diff options
author | Linus Nielsen Feltzing <linus@haxx.se> | 2004-08-22 11:28:24 +0000 |
---|---|---|
committer | Linus Nielsen Feltzing <linus@haxx.se> | 2004-08-22 11:28:24 +0000 |
commit | e0e0140f4e63b451a110840dc5ef5c22c3ed9f7c (patch) | |
tree | 6e48d6ddc4609f9a49eb2913b145b8d1f81e5436 | |
parent | 1a6a4812aa46d66ca46e308897e0cf759e42773f (diff) | |
download | rockbox-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.c | 42 | ||||
-rw-r--r-- | firmware/drivers/fat.c | 13 | ||||
-rw-r--r-- | firmware/export/fat.h | 1 |
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) | |||
277 | int rename(const char* path, const char* newpath) | 277 | int 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 | ||
1553 | int fat_rename(struct fat_file* file, | 1553 | int 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 ); | |||
89 | extern int fat_remove(struct fat_file *ent); | 89 | extern int fat_remove(struct fat_file *ent); |
90 | extern int fat_truncate(const struct fat_file *ent); | 90 | extern int fat_truncate(const struct fat_file *ent); |
91 | extern int fat_rename(struct fat_file* file, | 91 | extern 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 | ||