fat.h   [plain text]


/*
 * Copyright (c) 2000-2008, 2010-2011 Apple Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/* $FreeBSD: src/sys/msdosfs/fat.h,v 1.9 1999/12/29 04:54:53 peter Exp $ */
/*	$NetBSD: fat.h,v 1.12 1997/11/17 15:36:36 ws Exp $	*/

/*-
 * Copyright (C) 1994, 1997 Wolfgang Solfrank.
 * Copyright (C) 1994, 1997 TooLs GmbH.
 * All rights reserved.
 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * Written by Paul Popelka (paulp@uts.amdahl.com)
 *
 * You can do anything you want with this software, just don't say you wrote
 * it, and don't remove this notice.
 *
 * This software is provided "as is".
 *
 * The author supplies this software to be publicly redistributed on the
 * understanding that the author is not responsible for the correct
 * functioning of this software in any circumstances and is not liable for
 * any damages caused by this software.
 *
 * October 1992
 */


/*
 * Some useful cluster numbers.
 */
#define	MSDOSFSROOT	0		/* cluster 0 means the root dir */
#define	CLUST_FREE	0		/* cluster 0 also means a free cluster */
#define	MSDOSFSFREE	CLUST_FREE
#define	CLUST_FIRST	2		/* first legal cluster number */
#define	CLUST_RSRVD	0xfffffff6	/* reserved cluster range */
#define	CLUST_BAD	0xfffffff7	/* a cluster with a defect */
#define	CLUST_EOFS	0xfffffff8	/* start of eof cluster range */
#define	CLUST_EOFE	0xffffffff	/* end of eof cluster range */

/*
 * Note: FILENO_EMPTY must be larger than FAT32_MASK so that it can't accidentally
 * occur as a valid cluster number.
 */
#define FILENO_EMPTY	999999999	/* Fake file number used for empty files */
#define FILENO_ROOT	1		/* File number used for root directory of FAT12 and FAT16 */

#define	FAT12_MASK	0x00000fff	/* mask for 12 bit cluster numbers */
#define	FAT16_MASK	0x0000ffff	/* mask for 16 bit cluster numbers */
#define	FAT32_MASK	0x0fffffff	/* mask for FAT32 cluster numbers */

/*
 * MSDOSFS:
 * Return true if filesystem uses 12 bit fats. Microsoft Programmer's
 * Reference says if the maximum cluster number in a filesystem is greater
 * than 4078 ((CLUST_RSRVS - CLUST_FIRST) & FAT12_MASK) then we've got a
 * 16 bit fat filesystem. While mounting, the result of this test is stored
 * in pm_fatentrysize.
 * GEMDOS-flavour (atari):
 * If the filesystem is on floppy we've got a 12 bit fat filesystem, otherwise
 * 16 bit. We check the d_type field in the disklabel struct while mounting
 * and store the result in the pm_fatentrysize. Note that this kind of
 * detection gets flakey when mounting a vnd-device.
 */
#define	FAT12(pmp)	(pmp->pm_fatmask == FAT12_MASK)
#define	FAT16(pmp)	(pmp->pm_fatmask == FAT16_MASK)
#define	FAT32(pmp)	(pmp->pm_fatmask == FAT32_MASK)

#define	MSDOSFSEOF(pmp, cn)	((((cn) | ~(pmp)->pm_fatmask) & CLUST_EOFS) == CLUST_EOFS)

/*
		Symbolic Links for FAT

FAT does not have native support for symbolic links (symlinks).  We
implement them using ordinary files with a particular format.  Our
symlink file format is modeled after the SMB for Mac OS X implementation.

Symlink files are ordinary text files that look like:

XSym
1234
00112233445566778899AABBCCDDEEFF
/the/sym/link/path

The lines of the file are separated by ASCII newline (0x0A).  The first
line is a "magic" value to help identify the file.  The second line is
the length of the symlink itself; it is four decimal digits, with leading
zeroes.  The third line is the MD5 checksum of the symlink as 16
hexadecimal bytes.  The fourth line is the symlink, up to 1024 bytes long.
If the symlink is less than 1024 bytes, then it is padded with a single
newline character and as many spaces as needed to occupy 1024 bytes.

The file size is exactly 1067 (= 4 + 1 + 4 + 1 + 32 + 1 + 1024) bytes.
When we encounter an ordinary file whose length is 1067, we must read
it to verify that the header (including length and MD5 checksum) is
correct.

Since the file size is constant, we use the de_FileSize field in the
denode to store the actual length of the symlink.  That way, we only
check and parse the header once at vnode creation time.

*/

static const char symlink_magic[5] = "XSym\n";

#define SYMLINK_LINK_MAX 1024

struct symlink {
	char magic[5];		/* == symlink_magic */
	char length[4];		/* four decimal digits */
	char newline1;		/* '\n' */
	char md5[32];		/* MD5 hex digest of "length" bytes of "link" field */
	char newline2;		/* '\n' */
	char link[SYMLINK_LINK_MAX]; /* "length" bytes, padded by '\n' and spaces */
};

#ifdef KERNEL
/*
 * These are the values for the function argument to the function
 * msdosfs_fatentry().
 */
#define	FAT_GET		0x0001	/* get a fat entry */
#define	FAT_SET		0x0002	/* set a fat entry */
#define	FAT_GET_AND_SET	(FAT_GET | FAT_SET)

/*
 * Flags to msdosfs_extendfile:
 */
#define	DE_CLEAR	1	/* Zero out the blocks allocated */
#define DE_SYNC		IO_SYNC	/* 0x4 do it synchronisly...from vnode.h */


void msdosfs_fat_init(void);
void msdosfs_fat_uninit(void);
int  msdosfs_fat_init_vol(struct msdosfsmount *pmp);
void msdosfs_fat_uninit_vol(struct msdosfsmount *pmp);
int msdosfs_update_fsinfo(struct msdosfsmount *pmp, int waitfor, vfs_context_t context);
int msdosfs_pcbmap (struct denode *dep, uint32_t findcn, uint32_t numclusters, daddr64_t *bnp, uint32_t *cnp, uint32_t *sp);
int msdosfs_pcbmap_internal(struct denode *dep, uint32_t findcn, uint32_t numclusters, daddr64_t *bnp, uint32_t *cnp, uint32_t *sp);
int msdosfs_clusteralloc(struct msdosfsmount *pmp, uint32_t start, uint32_t count, uint32_t fillwith, uint32_t *retcluster, uint32_t *got);
int msdosfs_fatentry(int function, struct msdosfsmount *pmp, uint32_t cluster, uint32_t *oldcontents, uint32_t newcontents);
int msdosfs_freeclusterchain(struct msdosfsmount *pmp, uint32_t startchain);
int msdosfs_extendfile(struct denode *dep, uint32_t count);

/* [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.
 */
int msdosfs_markvoldirty(struct msdosfsmount *pmp, int dirty);

/*
 * Write the primary/active FAT and all directories to the device.  This
 * skips the boot sector, FSInfo sector, and non-active copies of the FAT.
 */
void msdosfs_meta_flush(struct msdosfsmount *pmp, int sync);
void msdosfs_meta_sync_callback(void *pmp, void *unused);

enum vtype msdosfs_check_link(struct denode *dep, vfs_context_t context);

extern u_char l2u[256];

/*
 * Tunables to control delayed metadata sync.
 */
extern uint32_t msdosfs_meta_delay;

#endif	/* KERNEL */