autofs: disable by default
[unleashed.git] / include / sys / fs / pc_fs.h
blob680732d4ea4fc1feb15f0d7a3b64e5ae8b9526fc
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #ifndef _SYS_FS_PC_FS_H
27 #define _SYS_FS_PC_FS_H
29 #include <sys/thread.h>
30 #include <sys/ksynch.h>
31 #include <sys/sysmacros.h>
32 #include <sys/byteorder.h>
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
38 typedef uint16_t pc_cluster16_t;
39 typedef uint32_t pc_cluster32_t;
42 * PC (MSDOS) compatible virtual file system.
44 * A main goal of the implementation was to maintain statelessness
45 * except while files are open. Thus mounting and unmounting merely
46 * declared the file system name. The user may change disks at almost
47 * any time without concern (just like the PC). It is assumed that when
48 * files are open for writing the disk access light will be on, as a
49 * warning not to change disks. The implementation must, however, detect
50 * disk change and recover gracefully. It does this by comparing the
51 * in core entry for a directory to the on disk entry whenever a directory
52 * is searched. If a discrepancy is found active directories become root and
53 * active files are marked invalid.
55 * There are only two type of nodes on the PC file system; files and
56 * directories. These are represented by two separate vnode op vectors,
57 * and they are kept in two separate tables. Files are known by the
58 * disk block number and block (cluster) offset of the files directory
59 * entry. Directories are known by the starting cluster number.
61 * The file system is locked for during each user operation. This is
62 * done to simplify disk verification error conditions.
64 * Notes on FAT32 support
65 * ----------------------
66 * The basic difference between FAT32 and FAT16 is that cluster numbers are now
67 * 32-bit instead of 16-bit. The FAT is thus an array of 32-bit cluster numbers,
68 * and because of this the cluster size can be much smaller on a large disk
69 * (4k, say, on a 1 Gig drive instead of 16k). Unfortunately, the FAT is not
70 * the only place cluster numbers are stored - the starting cluster is stored
71 * in the directory entry for a file, and of course it's only 16-bit. Luckily,
72 * there's a 16-bit OS/2 Extended Attribute field that is now used to store the
73 * upper 16-bits of the starting cluster number.
75 * Most of the FAT32 changes to pcfs are under 'if it's FAT32' to minimize the
76 * effect on non-FAT32 filesystems (and still share the code), except for the
77 * starting cluster changes. It seemed easier to make common functions to
78 * handle that.
80 * Other changes:
82 * 1. FAT32 partitions are indicated by partition types 0xB and 0xC.
83 * 2. The boot sector is now 2 sectors, to make room for FAT32 extensions.
84 * 3. The root directory is no longer stored in a fixed location. Its'
85 * starting cluster is stored in the extended boot sector.
86 * 4. "Summary information" is now stored and we need to (at least) maintain
87 * the number of free clusters or scandisk will be upset. Though the
88 * sector this info is in is pointed to by the extensions in the boot
89 * sector, the magic offset of this information is just that so
90 * far - magic. 0x1e0.
91 * 5. FAT32 can use the alternate FAT. But we don't.
93 * FAT32 also exposed a latent bug: we bread() each copy of the FAT in one
94 * big chunk. This is not good on a large FAT32 drive, such as a 1 Gig
95 * Jaz drive that has 4k clusters, since the FAT becomes 1 Meg in size and
96 * bread blocks forever. So now we read the FAT in chunks.
101 * The FAT bootsector uses little-endian multibyte values not aligned at
102 * a 'native' wordsize. Instead of defining a strange data structure and
103 * odd accessor methods for some members while using standard C accesses
104 * for others, we don't bother and just define the structure offsets, and
105 * a common set of misaligned-littleendian accessor macros.
108 #define OFF_JMPBOOT 0
109 #define OFF_OEMNAME 3
110 #define OFF_BYTESPERSEC 11
111 #define OFF_SECPERCLUS 13
112 #define OFF_RSVDSECCNT 14
113 #define OFF_NUMFATS 16
114 #define OFF_ROOTENTCNT 17
115 #define OFF_TOTSEC16 19
116 #define OFF_MEDIA 21
117 #define OFF_FATSZ16 22
118 #define OFF_SECPERTRK 24
119 #define OFF_NUMHEADS 26
120 #define OFF_HIDDSEC 28
121 #define OFF_TOTSEC32 32
122 #define OFF_BPBSIG 510
124 #define OFF_DRVNUM16 36
125 #define OFF_BOOTSIG16 38
126 #define OFF_VOLID16 39
127 #define OFF_VOLLAB16 43
128 #define OFF_FILSYSTYP16 54
130 #define OFF_FATSZ32 36
131 #define OFF_EXTFLAGS32 40
132 #define OFF_FSVER32 42
133 #define OFF_ROOTCLUS32 44
134 #define OFF_FSINFO32 48
135 #define OFF_BKBOOTSEC32 50
136 #define OFF_DRVNUM32 64
137 #define OFF_BOOTSIG32 66
138 #define OFF_VOLID32 67
139 #define OFF_VOLLAB32 71
140 #define OFF_FILSYSTYP32 82
142 #define LE_16_NA(addr) \
143 (((uint16_t)*((uint8_t *)(addr))) + \
144 ((uint16_t)*((uint8_t *)(addr) + 1) << 8))
146 #define LE_32_NA(addr) \
147 (((uint32_t)*((uint8_t *)(addr))) + \
148 ((uint32_t)*((uint8_t *)(addr) + 1) << 8) + \
149 ((uint32_t)*((uint8_t *)(addr) + 2) << 16) + \
150 ((uint32_t)*((uint8_t *)(addr) + 3) << 24))
153 * Generic FAT BPB fields
155 #define bpb_jmpBoot(bpb) ((unsigned char *)(bpb))
156 #define bpb_OEMName(bpb) ((char *)(bpb) + OFF_OEMNAME)
157 #define bpb_get_BytesPerSec(bpb) LE_16_NA((bpb) + OFF_BYTESPERSEC)
158 #define bpb_get_SecPerClus(bpb) (((uint8_t *)(bpb))[OFF_SECPERCLUS])
159 #define bpb_get_RsvdSecCnt(bpb) LE_16_NA((bpb) + OFF_RSVDSECCNT)
160 #define bpb_get_NumFATs(bpb) (((uint8_t *)(bpb))[OFF_NUMFATS])
161 #define bpb_get_RootEntCnt(bpb) LE_16_NA((bpb) + OFF_ROOTENTCNT)
162 #define bpb_get_TotSec16(bpb) LE_16_NA((bpb) + OFF_TOTSEC16)
163 #define bpb_get_Media(bpb) (((uint8_t *)(bpb))[OFF_MEDIA])
164 #define bpb_get_FatSz16(bpb) LE_16_NA((bpb) + OFF_FATSZ16)
165 #define bpb_get_SecPerTrk(bpb) LE_16_NA((bpb) + OFF_SECPERTRK)
166 #define bpb_get_NumHeads(bpb) LE_16_NA((bpb) + OFF_NUMHEADS)
167 #define bpb_get_HiddSec(bpb) LE_32_NA((bpb) + OFF_HIDDSEC)
168 #define bpb_get_TotSec32(bpb) LE_32_NA((bpb) + OFF_TOTSEC32)
169 #define bpb_get_BPBSig(bpb) LE_16_NA((bpb) + OFF_BPBSIG)
172 * FAT12/16 extended BPB fields
174 #define bpb_get_DrvNum16(bpb) (((uint8_t *)(bpb))[OFF_DRVNUM16])
175 #define bpb_get_BootSig16(bpb) (((uint8_t *)(bpb))[OFF_BOOTSIG16])
176 #define bpb_VolLab16(bpb) ((char *)(bpb) + OFF_VOLLAB16)
177 #define bpb_FilSysType16(bpb) ((char *)(bpb) + OFF_FILSYSTYP16)
178 #define bpb_get_VolID16(bpb) LE_32_NA((bpb) + OFF_VOLID16)
181 * FAT32 extended BPB fields
183 #define bpb_get_FatSz32(bpb) LE_32_NA((bpb) + OFF_FATSZ32)
184 #define bpb_get_ExtFlags32(bpb) LE_16_NA((bpb) + OFF_EXTFLAGS32)
185 #define bpb_get_FSVer32(bpb) LE_16_NA((bpb) + OFF_FSVER32)
186 #define bpb_get_RootClus32(bpb) LE_32_NA((bpb) + OFF_ROOTCLUS32)
187 #define bpb_get_FSInfo32(bpb) LE_16_NA((bpb) + OFF_FSINFO32)
188 #define bpb_get_BkBootSec32(bpb) LE_16_NA((bpb) + OFF_BKBOOTSEC32)
189 #define bpb_get_DrvNum32(bpb) (((uint8_t *)(bpb))[OFF_DRVNUM32])
190 #define bpb_get_BootSig32(bpb) (((uint8_t *)(bpb))[OFF_BOOTSIG32])
191 #define bpb_get_VolID32(bpb) LE_32_NA((bpb) + OFF_VOLID32)
192 #define bpb_VolLab32(bpb) ((char *)(bpb) + OFF_VOLLAB32)
193 #define bpb_FilSysType32(bpb) ((char *)(bpb) + OFF_FILSYSTYP32)
196 * Validators
198 #define VALID_SECSIZE(s) \
199 (s == 512 || s == 1024 || s == 2048 || s == 4096)
200 #define VALID_SPCL(s) (ISP2((s)) && (unsigned int)(s) <= 128)
201 #define VALID_CLSIZE(s) (ISP2((s)) && (unsigned int)(s) <= (64 * 1024))
202 #define VALID_NUMFATS(n) ((n) > 0 && (n) < 8)
203 #define VALID_RSVDSEC(s) ((s) > 0)
204 #define VALID_BPBSIG(sig) ((sig) == MBB_MAGIC)
205 #define VALID_BOOTSIG(sig) ((sig) == 0x29)
206 #define VALID_MEDIA(m) ((m) == 0xF0 || ((m) >= 0xF8 && (m) <= 0xFF))
209 * this might require a change for codepage support. In particular,
210 * pc_validchar() cannot be a macro anymore if codepages get involved.
212 #define VALID_VOLLAB(l) ( \
213 pc_validchar((l)[0]) && pc_validchar((l)[1]) && \
214 pc_validchar((l)[2]) && pc_validchar((l)[3]) && \
215 pc_validchar((l)[4]) && pc_validchar((l)[5]) && \
216 pc_validchar((l)[6]) && pc_validchar((l)[7]) && \
217 pc_validchar((l)[8]) && pc_validchar((l)[9]) && \
218 pc_validchar((l)[10]))
221 * We might actually use the 'validchar' checks as well; it only needs
222 * to be printable. Should this ever caused failed media recognition,
223 * we can change it. Many ISVs put different strings into the "oemname"
224 * field.
226 #define VALID_OEMNAME(nm) ( \
227 bcmp((nm), "MSDOS", 5) == 0 || bcmp((nm), "MSWIN", 5) == 0)
228 #define VALID_FSTYPSTR16(typ) (bcmp((typ), "FAT", 3) == 0)
229 #define VALID_FSTYPSTR32(typ) (bcmp((typ), "FAT32", 5) == 0)
230 #define VALID_JMPBOOT(b) ( \
231 ((b)[0] == 0xeb && (b)[2] == 0x90) || (b)[0] == 0xe9)
232 #define VALID_FSVER32(v) ((v) == PCFS_SUPPORTED_FSVER)
234 * Can we check this properly somehow ? There should be a better way.
235 * The FAT spec doesn't mention reserved bits need to be zero ...
237 #define VALID_EXTFLAGS(flags) (((flags) & 0x8f) == (flags))
240 * Validation results
242 #define BPB_SECSIZE_OK (1 << 0) /* ok: 512/1024/2048/4096 */
243 #define BPB_OEMNAME_OK (1 << 1) /* "MSDOS" or "MSWIN" */
244 #define BPB_JMPBOOT_OK (1 << 2) /* 16bit "jmp" / "call" */
245 #define BPB_SECPERCLUS_OK (1 << 3) /* power of 2, [1 .. 128] */
246 #define BPB_RSVDSECCNT_OK (1 << 4) /* cannot be zero */
247 #define BPB_NUMFAT_OK (1 << 5) /* >= 1, <= 8 */
248 #define BPB_ROOTENTCNT_OK (1 << 6) /* 0 on FAT32, != 0 else */
249 #define BPB_TOTSEC_OK (1 << 7) /* smaller than volume */
250 #define BPB_TOTSEC16_OK (1 << 8) /* 0 on FAT32, != 0 on FAT12 */
251 #define BPB_TOTSEC32_OK (1 << 9) /* 0 on FAT12, != 0 on FAT32 */
252 #define BPB_MEDIADESC_OK (1 << 10) /* 0xf0 or 0xf8..0xff */
253 #define BPB_FATSZ_OK (1 << 11) /* [nclusters], no smaller */
254 #define BPB_FATSZ16_OK (1 << 12) /* 0 on FAT32, != 0 else */
255 #define BPB_FATSZ32_OK (1 << 13) /* non-zero on FAT32 */
256 #define BPB_BPBSIG_OK (1 << 14) /* 0x55, 0xAA */
257 #define BPB_BOOTSIG16_OK (1 << 15) /* 0x29 - if present */
258 #define BPB_BOOTSIG32_OK (1 << 16) /* 0x29 - unless SYSLINUX2.x */
259 #define BPB_FSTYPSTR16_OK (1 << 17) /* At least "FAT" */
260 #define BPB_FSTYPSTR32_OK (1 << 18) /* "FAT32" */
261 #define BPB_EXTFLAGS_OK (1 << 19) /* reserved bits should be 0 */
262 #define BPB_FSVER_OK (1 << 20) /* must be 0 */
263 #define BPB_ROOTCLUSTER_OK (1 << 21) /* must be != 0 and valid */
264 #define BPB_FSISEC_OK (1 << 22) /* != 0, <= reserved */
265 #define BPB_BKBOOTSEC_OK (1 << 23) /* != 0, <= reserved, != fsi */
266 #define BPB_VOLLAB16_OK (1 << 24) /* passes pc_validchar() */
267 #define BPB_VOLLAB32_OK (1 << 25) /* passes pc_validchar() */
268 #define BPB_NCLUSTERS_OK (1 << 26) /* from FAT spec */
269 #define BPB_CLSIZE_OK (1 << 27) /* cluster size */
270 #define BPB_MEDIASZ_OK (1 << 28) /* filesystem fits on device */
272 #define FAT12_VALIDMSK \
273 (BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \
274 BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \
275 BPB_TOTSEC_OK | BPB_TOTSEC16_OK | \
276 BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_BPBSIG_OK)
278 #define FAT16_VALIDMSK \
279 (BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \
280 BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \
281 BPB_TOTSEC_OK | BPB_TOTSEC16_OK | BPB_TOTSEC32_OK | \
282 BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_BPBSIG_OK)
285 * A note on FAT32: According to the FAT spec, FAT32 _must_ have a valid
286 * extended BPB and therefore, as a proof of its existance, the FAT32
287 * boot signature (offset 66) must be valid as well. Why don't we check
288 * for BPB_BOOTSIG32_OK then ?
290 * We don't test for this here first-pass, because there are media out
291 * there that are valid FAT32 structurally but don't have a valid sig.
292 * This happens if older versions of the SYSLINUX bootloader (below 3.x)
293 * are installed on a media with a FAT32 on it. SYSLINUX 2.x and lower
294 * overwrite the BPB past the end of the FAT12/16 extension with its
295 * bootloader code - and the FAT16 extended BPB is 62 Bytes...
296 * All structurally relevant fields of the FAT32 BPB are within the first
297 * 52 Bytes, so the filesystem is accessible - but the signature check
298 * would reject it.
300 #define FAT32_VALIDMSK \
301 (BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \
302 BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \
303 BPB_TOTSEC_OK | BPB_TOTSEC16_OK | BPB_TOTSEC32_OK | \
304 BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_FATSZ32_OK | \
305 BPB_EXTFLAGS_OK | BPB_FSVER_OK | BPB_ROOTCLUSTER_OK | \
306 BPB_BPBSIG_OK)
309 * FAT32 BPB allows 'versioning' via FSVer32. We follow the 'NULL' spec.
311 #define PCFS_SUPPORTED_FSVER 0
315 * Filesystem summary information (introduced originally for FAT32 volumes).
316 * We need to maintain fs_free_clusters or Microsoft Scandisk will be upset.
317 * We keep these values in-core even for FAT12/FAT16 but will never attempt
318 * to write them out to disk then.
320 typedef struct fat_fsinfo {
321 uint32_t fs_free_clusters; /* # free clusters. -1 if unknown */
322 uint32_t fs_next_free; /* search next free after this cn */
323 } fat_fsi_t;
326 * On-disk FSI. All values in little endian. Only FAT32 has this.
328 typedef struct fat_od_fsi {
329 uint32_t fsi_leadsig; /* 0x41615252 */
330 char fsi_reserved1[480];
331 uint32_t fsi_strucsig; /* 0x61417272 */
332 fat_fsi_t fsi_incore; /* free/nextfree */
333 char fsi_reserved2[12];
334 uint32_t fsi_trailsig; /* 0xaa550000 */
335 } fat_od_fsi_t;
337 #define FSI_LEADSIG LE_32(0x41615252)
338 #define FSI_STRUCSIG LE_32(0x61417272)
339 #define FSI_TRAILSIG LE_32(0xaa550000) /* same as MBB_MAGIC */
341 #define FSISIG_OK(fsi) ( \
342 ((fat_od_fsi_t *)(fsi))->fsi_leadsig == FSI_LEADSIG && \
343 ((fat_od_fsi_t *)(fsi))->fsi_strucsig == FSI_STRUCSIG && \
344 ((fat_od_fsi_t *)(fsi))->fsi_trailsig == FSI_TRAILSIG)
346 #define FSINFO_UNKNOWN ((uint32_t)(-1)) /* free/next not valid */
348 typedef enum { FAT12, FAT16, FAT32, FAT_UNKNOWN, FAT_QUESTIONABLE } fattype_t;
351 struct pcfs {
352 struct vfs *pcfs_vfs; /* vfs for this fs */
353 int pcfs_flags; /* flags */
354 fattype_t pcfs_fattype;
355 dev_t pcfs_xdev; /* actual device that is mounted */
356 struct vnode *pcfs_devvp; /* and a vnode for it */
357 int pcfs_secsize; /* sector size in bytes */
358 int pcfs_spcl; /* sectors per cluster */
359 int pcfs_spt; /* sectors per track */
360 int pcfs_sdshift; /* shift to convert sector into */
361 /* DEV_BSIZE "sectors"; assume */
362 /* pcfs_secsize is 2**n times of */
363 /* DEV_BSIZE */
364 int pcfs_fatsec; /* number of sec per FAT */
365 int pcfs_numfat; /* number of FAT copies */
366 int pcfs_rdirsec; /* number of sec in root dir */
367 daddr_t pcfs_dosstart; /* start blkno of DOS partition */
368 daddr_t pcfs_fsistart; /* start blkno of FSI sector */
369 daddr_t pcfs_fatstart; /* start blkno of first FAT */
370 daddr_t pcfs_rdirstart; /* start blkno of root dir */
371 daddr_t pcfs_datastart; /* start blkno of data area */
372 int pcfs_clsize; /* cluster size in bytes */
373 int pcfs_ncluster; /* number of clusters in fs */
374 int pcfs_nrefs; /* number of active pcnodes */
375 int pcfs_frefs; /* number of active file pcnodes */
376 int pcfs_nxfrecls; /* next free cluster */
377 uchar_t *pcfs_fatp; /* ptr to FAT data */
378 uchar_t *pcfs_fat_changemap; /* map of changed fat data */
379 int pcfs_fat_changemapsize; /* size of FAT changemap */
380 time_t pcfs_fattime; /* time FAT becomes invalid */
381 time_t pcfs_verifytime; /* time to reverify disk */
382 kmutex_t pcfs_lock; /* per filesystem lock */
383 kthread_id_t pcfs_owner; /* id of thread locking pcfs */
384 int pcfs_count; /* # of pcfs locks for pcfs_owner */
385 struct fat_fsinfo pcfs_fsinfo; /* in-core fsinfo */
386 struct pcfs *pcfs_nxt; /* linked list of all mounts */
387 int pcfs_fatjustread; /* Used to flag a freshly found FAT */
388 struct vnode *pcfs_root; /* vnode for the root dir of the fs */
389 int pcfs_secondswest; /* recording timezone for this fs */
390 len_t pcfs_mediasize;
391 int pcfs_rootblksize;
392 int pcfs_mediadesc; /* media descriptor */
393 pc_cluster32_t pcfs_lastclmark;
394 pc_cluster32_t pcfs_rootclnum;
395 timestruc_t pcfs_mounttime; /* timestamp for "/" */
399 * flags
401 #define PCFS_FATMOD 0x01 /* FAT has been modified */
402 #define PCFS_LOCKED 0x02 /* fs is locked */
403 #define PCFS_WANTED 0x04 /* locked fs is wanted */
404 #define PCFS_NOCHK 0x800 /* don't resync fat on error */
405 #define PCFS_BOOTPART 0x1000 /* boot partition type */
406 #define PCFS_HIDDEN 0x2000 /* show hidden files */
407 #define PCFS_PCMCIA_NO_CIS 0x4000 /* PCMCIA psuedo floppy */
408 #define PCFS_FOLDCASE 0x8000 /* fold filenames to lowercase */
409 #define PCFS_FSINFO_OK 0x10000 /* valid FAT32 fsinfo sector */
410 #define PCFS_IRRECOV 0x20000 /* FS was messed with during write */
411 #define PCFS_NOCLAMPTIME 0x40000 /* expose full FAT timestamp range */
412 #define PCFS_NOATIME 0x80000 /* disable atime updates */
414 #define IS_FAT12(PCFS) ((PCFS)->pcfs_fattype == FAT12)
415 #define IS_FAT16(PCFS) ((PCFS)->pcfs_fattype == FAT16)
416 #define IS_FAT32(PCFS) ((PCFS)->pcfs_fattype == FAT32)
418 /* for compatibility */
419 struct old_pcfs_args {
420 int secondswest; /* seconds west of Greenwich */
421 int dsttime; /* type of dst correction */
424 struct pcfs_args {
425 int secondswest; /* seconds west of Greenwich */
426 int dsttime; /* type of dst correction */
427 int flags;
431 * pcfs mount options.
433 #define MNTOPT_PCFS_HIDDEN "hidden"
434 #define MNTOPT_PCFS_NOHIDDEN "nohidden"
435 #define MNTOPT_PCFS_FOLDCASE "foldcase"
436 #define MNTOPT_PCFS_NOFOLDCASE "nofoldcase"
437 #define MNTOPT_PCFS_CLAMPTIME "clamptime"
438 #define MNTOPT_PCFS_NOCLAMPTIME "noclamptime"
439 #define MNTOPT_PCFS_TIMEZONE "timezone"
440 #define MNTOPT_PCFS_SECSIZE "secsize"
443 * Disk timeout value in sec.
444 * This is used to time out the in core FAT and to re-verify the disk.
445 * This should be less than the time it takes to change floppys
447 #define PCFS_DISKTIMEOUT 2
449 #define PCFS_MAXOFFSET_T UINT32_MAX /* PCFS max file size */
451 #define VFSTOPCFS(VFSP) ((struct pcfs *)((VFSP)->vfs_data))
452 #define PCFSTOVFS(FSP) ((FSP)->pcfs_vfs)
455 * special cluster numbers in FAT
457 #define PCF_FREECLUSTER 0x00 /* cluster is available */
458 #define PCF_ERRORCLUSTER 0x01 /* error occurred allocating cluster */
459 #define PCF_12BCLUSTER 0xFF0 /* 12-bit version of reserved cluster */
460 #define PCF_RESCLUSTER 0xFFF0 /* 16-bit version of reserved cluster */
461 #define PCF_RESCLUSTER32 0xFFFFFF0 /* 32-bit version */
462 #define PCF_BADCLUSTER 0xFFF7 /* bad cluster, do not use */
463 #define PCF_BADCLUSTER32 0xFFFFFF7 /* 32-bit version */
464 #define PCF_LASTCLUSTER 0xFFF8 /* >= means last cluster in file */
465 #define PCF_LASTCLUSTER32 0xFFFFFF8 /* 32-bit version */
466 #define PCF_LASTCLUSTERMARK 0xFFFF /* value used to mark last cluster */
467 #define PCF_LASTCLUSTERMARK32 0xFFFFFFF /* 32-bit version */
468 #define PCF_FIRSTCLUSTER 2 /* first valid cluster number */
471 * file system constants
473 #define PC_MAXFATSEC 256 /* maximum number of sectors in FAT */
476 * file system parameter macros
479 #define pc_clear_fatchanges(PCFS) \
480 bzero((PCFS)->pcfs_fat_changemap, (PCFS)->pcfs_fat_changemapsize)
482 #define pc_blksize(PCFS, PCP, OFF) /* file system block size */ \
483 (((PCTOV(PCP)->v_flag & VROOT) && !IS_FAT32(PCFS)) ? \
484 ((OFF) >= \
485 ((PCFS)->pcfs_rdirsec & \
486 ~((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize)? \
487 ((PCFS)->pcfs_rdirsec & \
488 ((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize): \
489 (PCFS)->pcfs_clsize): \
490 (PCFS)->pcfs_clsize)
492 #define pc_blkoff(PCFS, OFF) /* offset within block */ \
493 ((int)((OFF) & ((PCFS)->pcfs_clsize - 1)))
495 #define pc_lblkno(PCFS, OFF) /* logical block (cluster) no */ \
496 ((daddr_t)((OFF) / (PCFS)->pcfs_clsize))
498 #define pc_dbtocl(PCFS, DB) /* disk blks to clusters */ \
499 ((int)((DB) / (PCFS)->pcfs_spcl))
501 #define pc_cltodb(PCFS, CL) /* clusters to disk blks */ \
502 ((daddr_t)((CL) * (PCFS)->pcfs_spcl))
504 #define pc_dbdaddr(PCFS, DB) /* sector to DEV_BSIZE "sector" addr */ \
505 ((DB) << (PCFS)->pcfs_sdshift)
507 #define pc_daddrdb(PCFS, DADDR) /* DEV_BSIZE "sector" addr to sector addr */ \
508 ((DADDR) >> (PCFS)->pcfs_sdshift)
510 #define pc_cldaddr(PCFS, CL) /* DEV_BSIZE "sector" addr for cluster */ \
511 pc_dbdaddr(PCFS, ((daddr_t)((PCFS)->pcfs_datastart + \
512 pc_cltodb(PCFS, (CL) - PCF_FIRSTCLUSTER))))
514 #define pc_daddrcl(PCFS, DADDR) /* cluster for disk address */ \
515 ((int)(PCF_FIRSTCLUSTER + \
516 pc_dbtocl(pc_daddrdb(PCFS, DADDR) - (PCFS)->pcfs_datastart)))
519 * Number of directory entries per sector / cluster
521 #define pc_direntpersec(PCFS) \
522 ((int)((PCFS)->pcfs_secsize / sizeof (struct pcdir)))
524 #define pc_direntpercl(PCFS) \
525 ((int)((PCFS)->pcfs_clsize / sizeof (struct pcdir)))
528 * out-of-range check for cluster numbers.
530 #define pc_validcl(PCFS, CL) /* check that cluster no is legit */ \
531 ((int)(CL) >= PCF_FIRSTCLUSTER && \
532 (int)(CL) < (PCFS)->pcfs_ncluster + PCF_FIRSTCLUSTER)
535 * external routines.
537 extern int pc_lockfs(struct pcfs *, int, int); /* lock fs and get fat */
538 extern void pc_unlockfs(struct pcfs *); /* ulock the fs */
539 extern int pc_getfat(struct pcfs *); /* get fat from disk */
540 extern void pc_invalfat(struct pcfs *); /* invalidate incore fat */
541 extern int pc_syncfat(struct pcfs *); /* sync fat to disk */
542 extern int pc_freeclusters(struct pcfs *); /* num free clusters in fs */
543 extern pc_cluster32_t pc_alloccluster(struct pcfs *, int);
544 extern void pc_setcluster(struct pcfs *, pc_cluster32_t, pc_cluster32_t);
545 extern void pc_mark_fat_updated(struct pcfs *fsp, pc_cluster32_t cn);
546 extern int pc_fat_is_changed(struct pcfs *fsp, pc_cluster32_t bn);
549 * debugging
551 extern int pcfsdebuglevel;
552 #define PC_DPRINTF0(level, A) \
553 if (pcfsdebuglevel >= level) \
554 cmn_err(CE_CONT, (A))
555 #define PC_DPRINTF1(level, A, B) \
556 if (pcfsdebuglevel >= level) \
557 cmn_err(CE_CONT, (A), (B))
558 #define PC_DPRINTF2(level, A, B, C) \
559 if (pcfsdebuglevel >= level) \
560 cmn_err(CE_CONT, (A), (B), (C))
561 #define PC_DPRINTF3(level, A, B, C, D) \
562 if (pcfsdebuglevel >= level) \
563 cmn_err(CE_CONT, (A), (B), (C), (D))
564 #define PC_DPRINTF4(level, A, B, C, D, E) \
565 if (pcfsdebuglevel >= level) \
566 cmn_err(CE_CONT, (A), (B), (C), (D), (E))
568 #ifdef __cplusplus
570 #endif
572 #endif /* _SYS_FS_PC_FS_H */