summaryrefslogtreecommitdiffstats
path: root/sys/fs/msdosfs/msdosfs_fat.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/msdosfs/msdosfs_fat.c')
-rw-r--r--sys/fs/msdosfs/msdosfs_fat.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c
index 1e9a3cf..1f75d7a 100644
--- a/sys/fs/msdosfs/msdosfs_fat.c
+++ b/sys/fs/msdosfs/msdosfs_fat.c
@@ -1106,3 +1106,70 @@ extendfile(dep, count, bpp, ncp, flags)
return (0);
}
+
+/* [2753891]
+ * Routine to mark a FAT16 or FAT32 volume as "clean" or "dirty" by manipulating the upper bit
+ * of the FAT entry for cluster 1. Note that this bit is not defined for FAT12 volumes, which
+ * are always assumed to be dirty.
+ *
+ * The fatentry() routine only works on cluster numbers that a file could occupy, so it won't
+ * manipulate the entry for cluster 1. So we have to do it here. The code is ripped from
+ * fatentry(), and tailored for cluster 1.
+ *
+ * Inputs:
+ * pmp The MS-DOS volume to mark
+ * dirty Non-zero if the volume should be marked dirty; zero if it should be marked clean.
+ *
+ * Result:
+ * 0 Success
+ * EROFS Volume is read-only
+ * ? (other errors from called routines)
+ */
+int markvoldirty(struct msdosfsmount *pmp, int dirty)
+{
+ int error;
+ u_long bn, bo, bsize, byteoffset;
+ u_long fatval;
+ struct buf *bp;
+
+ /* FAT12 does not support a "clean" bit, so don't do anything */
+ if (FAT12(pmp))
+ return 0;
+
+ /* Can't change the bit on a read-only filesystem */
+ if (pmp->pm_flags & MSDOSFSMNT_RONLY)
+ return EROFS;
+
+ /* Fetch the block containing the FAT entry */
+ byteoffset = FATOFS(pmp, 1); /* Find the location of cluster 1 */
+ fatblock(pmp, byteoffset, &bn, &bsize, &bo);
+
+ error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ return (error);
+ }
+
+ /* Get the current value of the FAT entry and set/clear the high bit */
+ if (FAT32(pmp)) {
+ /* FAT32 uses bit 27 */
+ fatval = getulong(&bp->b_data[bo]);
+ if (dirty)
+ fatval &= 0xF7FFFFFF; /* dirty means clear the "clean" bit */
+ else
+ fatval |= 0x08000000; /* clean means set the "clean" bit */
+ putulong(&bp->b_data[bo], fatval);
+ }
+ else {
+ /* Must be FAT16; use bit 15 */
+ fatval = getushort(&bp->b_data[bo]);
+ if (dirty)
+ fatval &= 0x7FFF; /* dirty means clear the "clean" bit */
+ else
+ fatval |= 0x8000; /* clean means set the "clean" bit */
+ putushort(&bp->b_data[bo], fatval);
+ }
+
+ /* Write out the modified FAT block immediately */
+ return bwrite(bp);
+}
OpenPOWER on IntegriCloud