patch-2.0.34 linux/fs/fat/misc.c

Next file: linux/fs/fat/mmap.c
Previous file: linux/fs/fat/inode.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.33/linux/fs/fat/misc.c linux/fs/fat/misc.c
@@ -14,7 +14,11 @@
 
 #include "msbuffer.h"
 
-#define PRINTK(x)
+#if 0
+#  define PRINTK(x)	printk x
+#else
+#  define PRINTK(x)
+#endif
 #define Printk(x)	printk x
 
 /* Well-known binary file extensions - of course there are many more */
@@ -23,7 +27,7 @@
   "EXE" "COM" "BIN" "APP" "SYS" "DRV" "OVL" "OVR" "OBJ" "LIB" "DLL" "PIF" /* program code */
   "ARC" "ZIP" "LHA" "LZH" "ZOO" "TAR" "Z  " "ARJ"	/* common archivers */
   "TZ " "TAZ" "TZP" "TPZ"		/* abbreviations of tar.Z and tar.zip */
-  "GZ " "TGZ" "DEB"			/* .gz, .tar.gz and Debian packages   */
+  "GZ " "TGZ" "DEB" "RPM"		/* .gz, .tar.gz and Debian packages   */
   "GIF" "BMP" "TIF" "GL " "JPG" "PCX"	/* graphics */
   "TFM" "VF " "GF " "PK " "PXL" "DVI";	/* TeX */
 
@@ -77,7 +81,7 @@
 /* (rename might deadlock before detecting cross-FS moves.) */
 
 static struct wait_queue *creation_wait = NULL;
-static creation_lock = 0;
+static int creation_lock = 0;
 
 
 void fat_lock_creation(void)
@@ -107,6 +111,34 @@
 	wake_up(&MSDOS_SB(sb)->fat_wait);
 }
 
+/* Flushes the number of free clusters on FAT32 */
+/* XXX: Need to write one per FSINFO block.  Currently only writes 1 */
+void fat_clusters_flush(struct super_block *sb)
+{
+	int offset;
+	struct buffer_head *bh;
+	struct fat_boot_fsinfo *fsinfo;
+
+	/* The fat32 boot fs info is at offset 0x3e0 by observation */
+	offset = MSDOS_SB(sb)->fsinfo_offset;
+	bh = fat_bread(sb, (offset >> SECTOR_BITS));
+	if (bh == NULL) {
+		printk("FAT bread failed in fat_clusters_flush\n");
+		return;
+	}
+	fsinfo = (struct fat_boot_fsinfo *)
+		&bh->b_data[offset & (SECTOR_SIZE-1)];
+
+	/* Sanity check */
+	if (CF_LE_L(fsinfo->signature) != 0x61417272) {
+		printk("fat_clusters_flush: Did not find valid FSINFO signature. Found 0x%x.  offset=0x%x\n", CF_LE_L(fsinfo->signature), offset);
+		fat_brelse(sb, bh);
+		return;
+	}
+	fsinfo->free_clusters = CF_LE_L(MSDOS_SB(sb)->free_clusters);
+	fat_mark_buffer_dirty(sb, bh, 1);
+	fat_brelse(sb, bh);
+}
 
 /*
  * fat_add_cluster tries to allocate a new cluster and adds it to the file
@@ -120,7 +152,9 @@
 	struct buffer_head *bh;
 	int cluster_size = MSDOS_SB(sb)->cluster_size;
 
-	if (inode->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
+	if (MSDOS_SB(sb)->fat_bits != 32) {
+		if (inode->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
+	}
 	if (!MSDOS_SB(sb)->free_clusters) return -ENOSPC;
 	lock_fat(sb);
 	limit = MSDOS_SB(sb)->clusters;
@@ -139,10 +173,14 @@
 		unlock_fat(sb);
 		return -ENOSPC;
 	}
-	fat_access(sb,nr,MSDOS_SB(sb)->fat_bits == 12 ?
-	    0xff8 : 0xfff8);
-	if (MSDOS_SB(sb)->free_clusters != -1)
+	fat_access(sb,nr,MSDOS_SB(sb)->fat_bits == 12 ? EOF_FAT12 :
+		   MSDOS_SB(sb)->fat_bits == 16 ? EOF_FAT16 : EOF_FAT32);
+	if (MSDOS_SB(sb)->free_clusters != -1) {
 		MSDOS_SB(sb)->free_clusters--;
+	}
+	if (MSDOS_SB(sb)->fat_bits == 32) {
+		fat_clusters_flush(sb);
+	}
 	unlock_fat(sb);
 #ifdef DEBUG
 printk("set to %x\n",fat_access(sb,nr,-1));
@@ -179,6 +217,7 @@
 	if (last) fat_access(sb,last,nr);
 	else {
 		MSDOS_I(inode)->i_start = nr;
+		MSDOS_I(inode)->i_logstart = nr;
 		inode->i_dirt = 1;
 	}
 #ifdef DEBUG
@@ -244,6 +283,9 @@
 	    month < 2 ? 1 : 0)+3653);
 			/* days since 1.1.70 plus 80's leap day */
 	secs += sys_tz.tz_minuteswest*60;
+	if (sys_tz.tz_dsttime) {
+	    secs -= 3600;
+	}
 	return secs;
 }
 
@@ -256,6 +298,8 @@
 	int day,year,nl_day,month;
 
 	unix_date -= sys_tz.tz_minuteswest*60;
+	if (sys_tz.tz_dsttime) unix_date += 3600;
+
 	*time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
 	    (((unix_date/3600) % 24) << 11);
 	day = unix_date/86400-3652;
@@ -298,7 +342,7 @@
 			fat_brelse(sb, *bh);
 		PRINTK (("get_entry sector apres brelse\n"));
 		if (!(*bh = fat_bread(sb, sector))) {
-			printk("Directory sread (sector %d) failed\n",sector);
+			printk("Directory sread (sector 0x%x) failed\n",sector);
 			continue;
 		}
 		PRINTK (("get_entry apres sread\n"));
@@ -340,7 +384,13 @@
      !(data[entry].attr & ATTR_VOLUME);
 
 #define RSS_START /* search for start cluster */ \
-    done = !IS_FREE(data[entry].name) && CF_LE_W(data[entry].start) == *number;
+    done = !IS_FREE(data[entry].name) \
+      && ( \
+           ( \
+             (MSDOS_SB(sb)->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \
+           ) \
+           | CF_LE_W(data[entry].start) \
+         ) == *number;
 
 #define RSS_FREE /* search for free entry */ \
     { \
@@ -393,6 +443,9 @@
 		if (done) {
 			if (ino) *ino = sector*MSDOS_DPS+entry;
 			start = CF_LE_W(data[entry].start);
+			if (MSDOS_SB(sb)->fat_bits == 32) {
+				start |= (CF_LE_W(data[entry].starthi) << 16);
+			}
 			if (!res_bh)
 				fat_brelse(sb, bh);
 			else {
@@ -488,6 +541,7 @@
 	static int zero = 0;
 	int error,curr,prev,nr;
 
+	PRINTK(("fat_parent_ino: Debug 0\n"));
 	if (!S_ISDIR(dir->i_mode)) panic("Non-directory fed to m_p_i");
 	if (dir->i_ino == MSDOS_ROOT_INO) return dir->i_ino;
 	if (!locked) fat_lock_creation(); /* prevent renames */
@@ -496,18 +550,27 @@
 		if (!locked) fat_unlock_creation();
 		return curr;
 	}
+	PRINTK(("fat_parent_ino: Debug 1 curr=%d\n", curr));
 	if (!curr) nr = MSDOS_ROOT_INO;
 	else {
+		PRINTK(("fat_parent_ino: Debug 2\n"));
 		if ((prev = raw_scan(dir->i_sb,curr,MSDOS_DOTDOT,&zero,NULL,
 		    NULL,NULL,SCAN_ANY)) < 0) {
+			PRINTK(("fat_parent_ino: Debug 3 prev=%d\n", prev));
 			if (!locked) fat_unlock_creation();
 			return prev;
 		}
+		PRINTK(("fat_parent_ino: Debug 4 prev=%d\n", prev));
+		if (prev == 0 && MSDOS_SB(dir->i_sb)->fat_bits == 32) {
+			prev = MSDOS_SB(dir->i_sb)->root_cluster;
+		}
 		if ((error = raw_scan(dir->i_sb,prev,NULL,&curr,&nr,NULL,
 		    NULL,SCAN_ANY)) < 0) {
+			PRINTK(("fat_parent_ino: Debug 5 error=%d\n", error));
 			if (!locked) fat_unlock_creation();
 			return error;
 		}
+		PRINTK(("fat_parent_ino: Debug 6 nr=%d\n", nr));
 	}
 	if (!locked) fat_unlock_creation();
 	return nr;
@@ -524,10 +587,12 @@
 	int count;
 
 	count = 0;
-	if (dir->i_ino == MSDOS_ROOT_INO)
+	if ((dir->i_ino == MSDOS_ROOT_INO) &&
+	    (MSDOS_SB(dir->i_sb)->fat_bits != 32)) {
 		(void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL,SCAN_ANY);
-	else {
-		if (!MSDOS_I(dir)->i_start) return 0; /* in mkdir */
+	} else {
+		if ((dir->i_ino != MSDOS_ROOT_INO) &&
+		    !MSDOS_I(dir)->i_start) return 0; /* in mkdir */
 		else (void) raw_scan_nonroot(dir->i_sb,MSDOS_I(dir)->i_start,
 		    NULL,&count,NULL,NULL,NULL,SCAN_ANY);
 	}
@@ -545,10 +610,7 @@
 {
 	int res;
 
-	res = (name)
-		? raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
-		    name, NULL, ino, res_bh, res_de, scantype)
-		: raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
-		    NULL, NULL, ino, res_bh, res_de, scantype);
+	res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
+		       name, NULL, ino, res_bh, res_de, scantype);
 	return res<0 ? res : 0;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov