diff options
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r-- | firmware/drivers/fat.c | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 999e6f1c9b..c9028aa762 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -1863,6 +1863,10 @@ int fat_rename(struct fat_file* file, | |||
1863 | int rc; | 1863 | int rc; |
1864 | struct fat_dir olddir; | 1864 | struct fat_dir olddir; |
1865 | struct fat_file newfile = *file; | 1865 | struct fat_file newfile = *file; |
1866 | unsigned char buf[SECTOR_SIZE]; | ||
1867 | unsigned char* entry = NULL; | ||
1868 | unsigned short* clusptr = NULL; | ||
1869 | unsigned int parentcluster; | ||
1866 | #ifdef HAVE_MULTIVOLUME | 1870 | #ifdef HAVE_MULTIVOLUME |
1867 | struct bpb* fat_bpb = &fat_bpbs[file->volume]; | 1871 | struct bpb* fat_bpb = &fat_bpbs[file->volume]; |
1868 | 1872 | ||
@@ -1870,6 +1874,8 @@ int fat_rename(struct fat_file* file, | |||
1870 | DEBUGF("No rename across volumes!\n"); | 1874 | DEBUGF("No rename across volumes!\n"); |
1871 | return -1; | 1875 | return -1; |
1872 | } | 1876 | } |
1877 | #else | ||
1878 | struct bpb* fat_bpb = &fat_bpbs[0]; | ||
1873 | #endif | 1879 | #endif |
1874 | 1880 | ||
1875 | if ( !file->dircluster ) { | 1881 | if ( !file->dircluster ) { |
@@ -1880,26 +1886,73 @@ int fat_rename(struct fat_file* file, | |||
1880 | /* create a temporary file handle */ | 1886 | /* create a temporary file handle */ |
1881 | rc = fat_opendir(IF_MV2(file->volume,) &olddir, file->dircluster, NULL); | 1887 | rc = fat_opendir(IF_MV2(file->volume,) &olddir, file->dircluster, NULL); |
1882 | if (rc < 0) | 1888 | if (rc < 0) |
1883 | return rc * 10 - 3; | 1889 | return rc * 10 - 1; |
1884 | 1890 | ||
1885 | /* create new name */ | 1891 | /* create new name */ |
1886 | rc = add_dir_entry(dir, &newfile, newname, false, false); | 1892 | rc = add_dir_entry(dir, &newfile, newname, false, false); |
1887 | if (rc < 0) | 1893 | if (rc < 0) |
1888 | return rc * 10 - 4; | 1894 | return rc * 10 - 2; |
1889 | 1895 | ||
1890 | /* write size and cluster link */ | 1896 | /* write size and cluster link */ |
1891 | rc = update_short_entry(&newfile, size, attr); | 1897 | rc = update_short_entry(&newfile, size, attr); |
1892 | if (rc < 0) | 1898 | if (rc < 0) |
1893 | return rc * 10 - 5; | 1899 | return rc * 10 - 3; |
1894 | 1900 | ||
1895 | /* remove old name */ | 1901 | /* remove old name */ |
1896 | rc = free_direntries(file); | 1902 | rc = free_direntries(file); |
1897 | if (rc < 0) | 1903 | if (rc < 0) |
1898 | return rc * 10 - 6; | 1904 | return rc * 10 - 4; |
1899 | 1905 | ||
1900 | rc = flush_fat(IF_MV(fat_bpb)); | 1906 | rc = flush_fat(IF_MV(fat_bpb)); |
1901 | if (rc < 0) | 1907 | if (rc < 0) |
1902 | return rc * 10 - 7; | 1908 | return rc * 10 - 5; |
1909 | |||
1910 | /* if renaming a directory, update the .. entry to make sure | ||
1911 | it points to its parent directory (we don't check if it was a move) */ | ||
1912 | if(FAT_ATTR_DIRECTORY == attr) { | ||
1913 | /* open the dir that was renamed, we re-use the olddir struct */ | ||
1914 | rc = fat_opendir(IF_MV2(file->volume,) &olddir, newfile.firstcluster, | ||
1915 | NULL); | ||
1916 | if (rc < 0) | ||
1917 | return rc * 10 - 6; | ||
1918 | |||
1919 | /* get the first sector of the dir */ | ||
1920 | rc = fat_seek(&olddir.file, 0); | ||
1921 | if (rc < 0) | ||
1922 | return rc * 10 - 7; | ||
1923 | |||
1924 | rc = fat_readwrite(&olddir.file, 1, buf, false); | ||
1925 | if (rc < 0) | ||
1926 | return rc * 10 - 8; | ||
1927 | |||
1928 | /* parent cluster is 0 if parent dir is the root - FAT spec (p.29) */ | ||
1929 | if(dir->file.firstcluster == fat_bpb->bpb_rootclus) | ||
1930 | parentcluster = 0; | ||
1931 | else | ||
1932 | parentcluster = dir->file.firstcluster; | ||
1933 | |||
1934 | entry = buf + DIR_ENTRY_SIZE; | ||
1935 | if(strncmp(".. ", entry, 11)) | ||
1936 | { | ||
1937 | /* .. entry must be second entry according to FAT spec (p.29) */ | ||
1938 | DEBUGF("Second dir entry is not double-dot!\n"); | ||
1939 | return rc * 10 - 9; | ||
1940 | } | ||
1941 | clusptr = (short*)(entry + FATDIR_FSTCLUSHI); | ||
1942 | *clusptr = htole16(parentcluster >> 16); | ||
1943 | |||
1944 | clusptr = (short*)(entry + FATDIR_FSTCLUSLO); | ||
1945 | *clusptr = htole16(parentcluster & 0xffff); | ||
1946 | |||
1947 | /* write back this sector */ | ||
1948 | rc = fat_seek(&olddir.file, 0); | ||
1949 | if (rc < 0) | ||
1950 | return rc * 10 - 7; | ||
1951 | |||
1952 | rc = fat_readwrite(&olddir.file, 1, buf, true); | ||
1953 | if (rc < 1) | ||
1954 | return rc * 10 - 8; | ||
1955 | } | ||
1903 | 1956 | ||
1904 | return 0; | 1957 | return 0; |
1905 | } | 1958 | } |