summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/fat.c63
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}