17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50e42dee6Sartem * Common Development and Distribution License (the "License"). 60e42dee6Sartem * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*32d46495SMichael Bergknoff * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #ifndef _SYS_FS_PC_FS_H 277c478bd9Sstevel@tonic-gate #define _SYS_FS_PC_FS_H 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <sys/thread.h> 30f127cb91Sfrankho #include <sys/ksynch.h> 31f127cb91Sfrankho #include <sys/sysmacros.h> 32f127cb91Sfrankho #include <sys/byteorder.h> 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #ifdef __cplusplus 357c478bd9Sstevel@tonic-gate extern "C" { 367c478bd9Sstevel@tonic-gate #endif 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate typedef uint16_t pc_cluster16_t; 397c478bd9Sstevel@tonic-gate typedef uint32_t pc_cluster32_t; 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* 427c478bd9Sstevel@tonic-gate * PC (MSDOS) compatible virtual file system. 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * A main goal of the implementation was to maintain statelessness 457c478bd9Sstevel@tonic-gate * except while files are open. Thus mounting and unmounting merely 467c478bd9Sstevel@tonic-gate * declared the file system name. The user may change disks at almost 477c478bd9Sstevel@tonic-gate * any time without concern (just like the PC). It is assumed that when 487c478bd9Sstevel@tonic-gate * files are open for writing the disk access light will be on, as a 497c478bd9Sstevel@tonic-gate * warning not to change disks. The implementation must, however, detect 507c478bd9Sstevel@tonic-gate * disk change and recover gracefully. It does this by comparing the 517c478bd9Sstevel@tonic-gate * in core entry for a directory to the on disk entry whenever a directory 527c478bd9Sstevel@tonic-gate * is searched. If a discrepancy is found active directories become root and 537c478bd9Sstevel@tonic-gate * active files are marked invalid. 547c478bd9Sstevel@tonic-gate * 557c478bd9Sstevel@tonic-gate * There are only two type of nodes on the PC file system; files and 567c478bd9Sstevel@tonic-gate * directories. These are represented by two separate vnode op vectors, 577c478bd9Sstevel@tonic-gate * and they are kept in two separate tables. Files are known by the 587c478bd9Sstevel@tonic-gate * disk block number and block (cluster) offset of the files directory 597c478bd9Sstevel@tonic-gate * entry. Directories are known by the starting cluster number. 607c478bd9Sstevel@tonic-gate * 617c478bd9Sstevel@tonic-gate * The file system is locked for during each user operation. This is 627c478bd9Sstevel@tonic-gate * done to simplify disk verification error conditions. 637c478bd9Sstevel@tonic-gate * 647c478bd9Sstevel@tonic-gate * Notes on FAT32 support 657c478bd9Sstevel@tonic-gate * ---------------------- 667c478bd9Sstevel@tonic-gate * The basic difference between FAT32 and FAT16 is that cluster numbers are now 677c478bd9Sstevel@tonic-gate * 32-bit instead of 16-bit. The FAT is thus an array of 32-bit cluster numbers, 687c478bd9Sstevel@tonic-gate * and because of this the cluster size can be much smaller on a large disk 697c478bd9Sstevel@tonic-gate * (4k, say, on a 1 Gig drive instead of 16k). Unfortunately, the FAT is not 707c478bd9Sstevel@tonic-gate * the only place cluster numbers are stored - the starting cluster is stored 717c478bd9Sstevel@tonic-gate * in the directory entry for a file, and of course it's only 16-bit. Luckily, 727c478bd9Sstevel@tonic-gate * there's a 16-bit OS/2 Extended Attribute field that is now used to store the 737c478bd9Sstevel@tonic-gate * upper 16-bits of the starting cluster number. 747c478bd9Sstevel@tonic-gate * 757c478bd9Sstevel@tonic-gate * Most of the FAT32 changes to pcfs are under 'if it's FAT32' to minimize the 767c478bd9Sstevel@tonic-gate * effect on non-FAT32 filesystems (and still share the code), except for the 777c478bd9Sstevel@tonic-gate * starting cluster changes. It seemed easier to make common functions to 787c478bd9Sstevel@tonic-gate * handle that. 797c478bd9Sstevel@tonic-gate * 807c478bd9Sstevel@tonic-gate * Other changes: 817c478bd9Sstevel@tonic-gate * 827c478bd9Sstevel@tonic-gate * 1. FAT32 partitions are indicated by partition types 0xB and 0xC. 837c478bd9Sstevel@tonic-gate * 2. The boot sector is now 2 sectors, to make room for FAT32 extensions. 847c478bd9Sstevel@tonic-gate * 3. The root directory is no longer stored in a fixed location. Its' 857c478bd9Sstevel@tonic-gate * starting cluster is stored in the extended boot sector. 867c478bd9Sstevel@tonic-gate * 4. "Summary information" is now stored and we need to (at least) maintain 877c478bd9Sstevel@tonic-gate * the number of free clusters or scandisk will be upset. Though the 887c478bd9Sstevel@tonic-gate * sector this info is in is pointed to by the extensions in the boot 897c478bd9Sstevel@tonic-gate * sector, the magic offset of this information is just that so 907c478bd9Sstevel@tonic-gate * far - magic. 0x1e0. 917c478bd9Sstevel@tonic-gate * 5. FAT32 can use the alternate FAT. But we don't. 927c478bd9Sstevel@tonic-gate * 937c478bd9Sstevel@tonic-gate * FAT32 also exposed a latent bug: we bread() each copy of the FAT in one 947c478bd9Sstevel@tonic-gate * big chunk. This is not good on a large FAT32 drive, such as a 1 Gig 957c478bd9Sstevel@tonic-gate * Jaz drive that has 4k clusters, since the FAT becomes 1 Meg in size and 967c478bd9Sstevel@tonic-gate * bread blocks forever. So now we read the FAT in chunks. 977c478bd9Sstevel@tonic-gate */ 987c478bd9Sstevel@tonic-gate 99f127cb91Sfrankho 1007c478bd9Sstevel@tonic-gate /* 101f127cb91Sfrankho * The FAT bootsector uses little-endian multibyte values not aligned at 102f127cb91Sfrankho * a 'native' wordsize. Instead of defining a strange data structure and 103f127cb91Sfrankho * odd accessor methods for some members while using standard C accesses 104f127cb91Sfrankho * for others, we don't bother and just define the structure offsets, and 105f127cb91Sfrankho * a common set of misaligned-littleendian accessor macros. 106f127cb91Sfrankho * 107f127cb91Sfrankho * The "bootsec" and "fat32_bootsec" structures are only provided for 108f127cb91Sfrankho * compatibility with old code including <sys/fs/pc_fs.h> but not used 109f127cb91Sfrankho * by the PCFS kernel driver anymore. 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate struct bootsec { 1127c478bd9Sstevel@tonic-gate uchar_t instr[3]; 1137c478bd9Sstevel@tonic-gate uchar_t version[8]; 1147c478bd9Sstevel@tonic-gate uchar_t bps[2]; /* bytes per sector */ 1157c478bd9Sstevel@tonic-gate uchar_t spcl; /* sectors per allocation unit */ 1167c478bd9Sstevel@tonic-gate uchar_t res_sec[2]; /* reserved sectors, starting at 0 */ 1177c478bd9Sstevel@tonic-gate uchar_t nfat; /* number of FATs */ 1187c478bd9Sstevel@tonic-gate uchar_t rdirents[2]; /* number of root directory entries */ 1197c478bd9Sstevel@tonic-gate uchar_t numsect[2]; /* old total sectors in logical image */ 1207c478bd9Sstevel@tonic-gate uchar_t mediadesriptor; /* media descriptor byte */ 1217c478bd9Sstevel@tonic-gate ushort_t fatsec; /* number of sectors per FAT */ 1227c478bd9Sstevel@tonic-gate ushort_t spt; /* sectors per track */ 1237c478bd9Sstevel@tonic-gate ushort_t nhead; /* number of heads */ 1240e42dee6Sartem uint_t hiddensec; /* number of hidden sectors */ 1257c478bd9Sstevel@tonic-gate uint_t totalsec; /* total sectors in logical image */ 1267c478bd9Sstevel@tonic-gate }; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate /* 1297c478bd9Sstevel@tonic-gate * FAT32 volumes have a bigger boot sector. They include the normal 1307c478bd9Sstevel@tonic-gate * boot sector. 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate struct fat32_bootsec { 1337c478bd9Sstevel@tonic-gate struct bootsec f_bs; 1347c478bd9Sstevel@tonic-gate uint32_t f_fatlength; /* size of FAT */ 1357c478bd9Sstevel@tonic-gate uint16_t f_flags; 1367c478bd9Sstevel@tonic-gate uint8_t f_major; /* major filesystem version #? */ 1377c478bd9Sstevel@tonic-gate uint8_t f_minor; /* minor filesystem version #? */ 1387c478bd9Sstevel@tonic-gate uint32_t f_rootcluster; /* first cluster in root directory */ 1397c478bd9Sstevel@tonic-gate uint16_t f_infosector; /* where summary info is */ 1407c478bd9Sstevel@tonic-gate uint16_t f_backupboot; /* backup boot sector */ 1417c478bd9Sstevel@tonic-gate uint16_t f_reserved2[6]; 1427c478bd9Sstevel@tonic-gate }; 1437c478bd9Sstevel@tonic-gate 144f127cb91Sfrankho 145f127cb91Sfrankho #define OFF_JMPBOOT 0 146f127cb91Sfrankho #define OFF_OEMNAME 3 147f127cb91Sfrankho #define OFF_BYTESPERSEC 11 148f127cb91Sfrankho #define OFF_SECPERCLUS 13 149f127cb91Sfrankho #define OFF_RSVDSECCNT 14 150f127cb91Sfrankho #define OFF_NUMFATS 16 151f127cb91Sfrankho #define OFF_ROOTENTCNT 17 152f127cb91Sfrankho #define OFF_TOTSEC16 19 153f127cb91Sfrankho #define OFF_MEDIA 21 154f127cb91Sfrankho #define OFF_FATSZ16 22 155f127cb91Sfrankho #define OFF_SECPERTRK 24 156f127cb91Sfrankho #define OFF_NUMHEADS 26 157f127cb91Sfrankho #define OFF_HIDDSEC 28 158f127cb91Sfrankho #define OFF_TOTSEC32 32 159f127cb91Sfrankho #define OFF_BPBSIG 510 160f127cb91Sfrankho 161f127cb91Sfrankho #define OFF_DRVNUM16 36 162f127cb91Sfrankho #define OFF_BOOTSIG16 38 163f127cb91Sfrankho #define OFF_VOLID16 39 164f127cb91Sfrankho #define OFF_VOLLAB16 43 165f127cb91Sfrankho #define OFF_FILSYSTYP16 54 166f127cb91Sfrankho 167f127cb91Sfrankho #define OFF_FATSZ32 36 168f127cb91Sfrankho #define OFF_EXTFLAGS32 40 169f127cb91Sfrankho #define OFF_FSVER32 42 170f127cb91Sfrankho #define OFF_ROOTCLUS32 44 171f127cb91Sfrankho #define OFF_FSINFO32 48 172f127cb91Sfrankho #define OFF_BKBOOTSEC32 50 173f127cb91Sfrankho #define OFF_DRVNUM32 64 174f127cb91Sfrankho #define OFF_BOOTSIG32 66 175f127cb91Sfrankho #define OFF_VOLID32 67 176f127cb91Sfrankho #define OFF_VOLLAB32 71 177f127cb91Sfrankho #define OFF_FILSYSTYP32 82 178f127cb91Sfrankho 179f127cb91Sfrankho #define LE_16_NA(addr) \ 180f127cb91Sfrankho (((uint16_t)*((uint8_t *)(addr))) + \ 181f127cb91Sfrankho ((uint16_t)*((uint8_t *)(addr) + 1) << 8)) 182f127cb91Sfrankho 183f127cb91Sfrankho #define LE_32_NA(addr) \ 184f127cb91Sfrankho (((uint32_t)*((uint8_t *)(addr))) + \ 185f127cb91Sfrankho ((uint32_t)*((uint8_t *)(addr) + 1) << 8) + \ 186f127cb91Sfrankho ((uint32_t)*((uint8_t *)(addr) + 2) << 16) + \ 187f127cb91Sfrankho ((uint32_t)*((uint8_t *)(addr) + 3) << 24)) 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 190f127cb91Sfrankho * Generic FAT BPB fields 1917c478bd9Sstevel@tonic-gate */ 192f127cb91Sfrankho #define bpb_jmpBoot(bpb) ((unsigned char *)(bpb)) 193f127cb91Sfrankho #define bpb_OEMName(bpb) ((char *)(bpb) + OFF_OEMNAME) 194f127cb91Sfrankho #define bpb_get_BytesPerSec(bpb) LE_16_NA((bpb) + OFF_BYTESPERSEC) 195f127cb91Sfrankho #define bpb_get_SecPerClus(bpb) (((uint8_t *)(bpb))[OFF_SECPERCLUS]) 196f127cb91Sfrankho #define bpb_get_RsvdSecCnt(bpb) LE_16_NA((bpb) + OFF_RSVDSECCNT) 197f127cb91Sfrankho #define bpb_get_NumFATs(bpb) (((uint8_t *)(bpb))[OFF_NUMFATS]) 198f127cb91Sfrankho #define bpb_get_RootEntCnt(bpb) LE_16_NA((bpb) + OFF_ROOTENTCNT) 199f127cb91Sfrankho #define bpb_get_TotSec16(bpb) LE_16_NA((bpb) + OFF_TOTSEC16) 200f127cb91Sfrankho #define bpb_get_Media(bpb) (((uint8_t *)(bpb))[OFF_MEDIA]) 201f127cb91Sfrankho #define bpb_get_FatSz16(bpb) LE_16_NA((bpb) + OFF_FATSZ16) 202f127cb91Sfrankho #define bpb_get_SecPerTrk(bpb) LE_16_NA((bpb) + OFF_SECPERTRK) 203f127cb91Sfrankho #define bpb_get_NumHeads(bpb) LE_16_NA((bpb) + OFF_NUMHEADS) 204f127cb91Sfrankho #define bpb_get_HiddSec(bpb) LE_32_NA((bpb) + OFF_HIDDSEC) 205f127cb91Sfrankho #define bpb_get_TotSec32(bpb) LE_32_NA((bpb) + OFF_TOTSEC32) 206f127cb91Sfrankho #define bpb_get_BPBSig(bpb) LE_16_NA((bpb) + OFF_BPBSIG) 2077c478bd9Sstevel@tonic-gate 208f127cb91Sfrankho /* 209f127cb91Sfrankho * FAT12/16 extended BPB fields 210f127cb91Sfrankho */ 211f127cb91Sfrankho #define bpb_get_DrvNum16(bpb) (((uint8_t *)(bpb))[OFF_DRVNUM16]) 212f127cb91Sfrankho #define bpb_get_BootSig16(bpb) (((uint8_t *)(bpb))[OFF_BOOTSIG16]) 213f127cb91Sfrankho #define bpb_VolLab16(bpb) ((char *)(bpb) + OFF_VOLLAB16) 214f127cb91Sfrankho #define bpb_FilSysType16(bpb) ((char *)(bpb) + OFF_FILSYSTYP16) 215f127cb91Sfrankho #define bpb_get_VolID16(bpb) LE_32_NA((bpb) + OFF_VOLID16) 216f127cb91Sfrankho 217f127cb91Sfrankho /* 218f127cb91Sfrankho * FAT32 extended BPB fields 219f127cb91Sfrankho */ 220f127cb91Sfrankho #define bpb_get_FatSz32(bpb) LE_32_NA((bpb) + OFF_FATSZ32) 221f127cb91Sfrankho #define bpb_get_ExtFlags32(bpb) LE_16_NA((bpb) + OFF_EXTFLAGS32) 222f127cb91Sfrankho #define bpb_get_FSVer32(bpb) LE_16_NA((bpb) + OFF_FSVER32) 223f127cb91Sfrankho #define bpb_get_RootClus32(bpb) LE_32_NA((bpb) + OFF_ROOTCLUS32) 224f127cb91Sfrankho #define bpb_get_FSInfo32(bpb) LE_16_NA((bpb) + OFF_FSINFO32) 225f127cb91Sfrankho #define bpb_get_BkBootSec32(bpb) LE_16_NA((bpb) + OFF_BKBOOTSEC32) 226f127cb91Sfrankho #define bpb_get_DrvNum32(bpb) (((uint8_t *)(bpb))[OFF_DRVNUM32]) 227f127cb91Sfrankho #define bpb_get_BootSig32(bpb) (((uint8_t *)(bpb))[OFF_BOOTSIG32]) 228f127cb91Sfrankho #define bpb_get_VolID32(bpb) LE_32_NA((bpb) + OFF_VOLID32) 229f127cb91Sfrankho #define bpb_VolLab32(bpb) ((char *)(bpb) + OFF_VOLLAB32) 230f127cb91Sfrankho #define bpb_FilSysType32(bpb) ((char *)(bpb) + OFF_FILSYSTYP32) 231f127cb91Sfrankho 232f127cb91Sfrankho /* 233f127cb91Sfrankho * Validators 234f127cb91Sfrankho */ 235f127cb91Sfrankho #define VALID_SECSIZE(s) \ 236f127cb91Sfrankho (s == 512 || s == 1024 || s == 2048 || s == 4096) 237f127cb91Sfrankho #define VALID_SPCL(s) (ISP2((s)) && (unsigned int)(s) <= 128) 238f127cb91Sfrankho #define VALID_CLSIZE(s) (ISP2((s)) && (unsigned int)(s) <= (64 * 1024)) 239f127cb91Sfrankho #define VALID_NUMFATS(n) ((n) > 0 && (n) < 8) 240f127cb91Sfrankho #define VALID_RSVDSEC(s) ((s) > 0) 241f127cb91Sfrankho #define VALID_BPBSIG(sig) ((sig) == MBB_MAGIC) 242f127cb91Sfrankho #define VALID_BOOTSIG(sig) ((sig) == 0x29) 243f127cb91Sfrankho #define VALID_MEDIA(m) ((m) == 0xF0 || ((m) >= 0xF8 && (m) <= 0xFF)) 244f127cb91Sfrankho 245f127cb91Sfrankho /* 246f127cb91Sfrankho * this might require a change for codepage support. In particular, 247f127cb91Sfrankho * pc_validchar() cannot be a macro anymore if codepages get involved. 248f127cb91Sfrankho */ 249f127cb91Sfrankho #define VALID_VOLLAB(l) ( \ 250f127cb91Sfrankho pc_validchar((l)[0]) && pc_validchar((l)[1]) && \ 251f127cb91Sfrankho pc_validchar((l)[2]) && pc_validchar((l)[3]) && \ 252f127cb91Sfrankho pc_validchar((l)[4]) && pc_validchar((l)[5]) && \ 253f127cb91Sfrankho pc_validchar((l)[6]) && pc_validchar((l)[7]) && \ 254f127cb91Sfrankho pc_validchar((l)[8]) && pc_validchar((l)[9]) && \ 255f127cb91Sfrankho pc_validchar((l)[10])) 256f127cb91Sfrankho 257f127cb91Sfrankho /* 258f127cb91Sfrankho * We might actually use the 'validchar' checks as well; it only needs 259f127cb91Sfrankho * to be printable. Should this ever caused failed media recognition, 260f127cb91Sfrankho * we can change it. Many ISVs put different strings into the "oemname" 261f127cb91Sfrankho * field. 262f127cb91Sfrankho */ 263f127cb91Sfrankho #define VALID_OEMNAME(nm) ( \ 264f127cb91Sfrankho bcmp((nm), "MSDOS", 5) == 0 || bcmp((nm), "MSWIN", 5) == 0) 265f127cb91Sfrankho #define VALID_FSTYPSTR16(typ) (bcmp((typ), "FAT", 3) == 0) 266f127cb91Sfrankho #define VALID_FSTYPSTR32(typ) (bcmp((typ), "FAT32", 5) == 0) 267f127cb91Sfrankho #define VALID_JMPBOOT(b) ( \ 268f127cb91Sfrankho ((b)[0] == 0xeb && (b)[2] == 0x90) || (b)[0] == 0xe9) 269f127cb91Sfrankho #define VALID_FSVER32(v) ((v) == PCFS_SUPPORTED_FSVER) 270f127cb91Sfrankho /* 271f127cb91Sfrankho * Can we check this properly somehow ? There should be a better way. 272f127cb91Sfrankho * The FAT spec doesn't mention reserved bits need to be zero ... 273f127cb91Sfrankho */ 274f127cb91Sfrankho #define VALID_EXTFLAGS(flags) (((flags) & 0x8f) == (flags)) 275f127cb91Sfrankho 276f127cb91Sfrankho /* 277f127cb91Sfrankho * Validation results 278f127cb91Sfrankho */ 279f127cb91Sfrankho #define BPB_SECSIZE_OK (1 << 0) /* ok: 512/1024/2048/4096 */ 280f127cb91Sfrankho #define BPB_OEMNAME_OK (1 << 1) /* "MSDOS" or "MSWIN" */ 281f127cb91Sfrankho #define BPB_JMPBOOT_OK (1 << 2) /* 16bit "jmp" / "call" */ 282f127cb91Sfrankho #define BPB_SECPERCLUS_OK (1 << 3) /* power of 2, [1 .. 128] */ 283f127cb91Sfrankho #define BPB_RSVDSECCNT_OK (1 << 4) /* cannot be zero */ 284f127cb91Sfrankho #define BPB_NUMFAT_OK (1 << 5) /* >= 1, <= 8 */ 285f127cb91Sfrankho #define BPB_ROOTENTCNT_OK (1 << 6) /* 0 on FAT32, != 0 else */ 286f127cb91Sfrankho #define BPB_TOTSEC_OK (1 << 7) /* smaller than volume */ 287f127cb91Sfrankho #define BPB_TOTSEC16_OK (1 << 8) /* 0 on FAT32, != 0 on FAT12 */ 288f127cb91Sfrankho #define BPB_TOTSEC32_OK (1 << 9) /* 0 on FAT12, != 0 on FAT32 */ 289f127cb91Sfrankho #define BPB_MEDIADESC_OK (1 << 10) /* 0xf0 or 0xf8..0xff */ 290f127cb91Sfrankho #define BPB_FATSZ_OK (1 << 11) /* [nclusters], no smaller */ 291f127cb91Sfrankho #define BPB_FATSZ16_OK (1 << 12) /* 0 on FAT32, != 0 else */ 292f127cb91Sfrankho #define BPB_FATSZ32_OK (1 << 13) /* non-zero on FAT32 */ 293f127cb91Sfrankho #define BPB_BPBSIG_OK (1 << 14) /* 0x55, 0xAA */ 294f127cb91Sfrankho #define BPB_BOOTSIG16_OK (1 << 15) /* 0x29 - if present */ 295f127cb91Sfrankho #define BPB_BOOTSIG32_OK (1 << 16) /* 0x29 - unless SYSLINUX2.x */ 296f127cb91Sfrankho #define BPB_FSTYPSTR16_OK (1 << 17) /* At least "FAT" */ 297f127cb91Sfrankho #define BPB_FSTYPSTR32_OK (1 << 18) /* "FAT32" */ 298f127cb91Sfrankho #define BPB_EXTFLAGS_OK (1 << 19) /* reserved bits should be 0 */ 299f127cb91Sfrankho #define BPB_FSVER_OK (1 << 20) /* must be 0 */ 300f127cb91Sfrankho #define BPB_ROOTCLUSTER_OK (1 << 21) /* must be != 0 and valid */ 301f127cb91Sfrankho #define BPB_FSISEC_OK (1 << 22) /* != 0, <= reserved */ 302f127cb91Sfrankho #define BPB_BKBOOTSEC_OK (1 << 23) /* != 0, <= reserved, != fsi */ 303f127cb91Sfrankho #define BPB_VOLLAB16_OK (1 << 24) /* passes pc_validchar() */ 304f127cb91Sfrankho #define BPB_VOLLAB32_OK (1 << 25) /* passes pc_validchar() */ 305f127cb91Sfrankho #define BPB_NCLUSTERS_OK (1 << 26) /* from FAT spec */ 306f127cb91Sfrankho #define BPB_CLSIZE_OK (1 << 27) /* cluster size */ 307f127cb91Sfrankho #define BPB_MEDIASZ_OK (1 << 28) /* filesystem fits on device */ 308f127cb91Sfrankho 309f127cb91Sfrankho #define FAT12_VALIDMSK \ 310f127cb91Sfrankho (BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \ 311f127cb91Sfrankho BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \ 312f127cb91Sfrankho BPB_TOTSEC_OK | BPB_TOTSEC16_OK | \ 313f127cb91Sfrankho BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_BPBSIG_OK) 314f127cb91Sfrankho 315f127cb91Sfrankho #define FAT16_VALIDMSK \ 316f127cb91Sfrankho (BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \ 317f127cb91Sfrankho BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \ 318f127cb91Sfrankho BPB_TOTSEC_OK | BPB_TOTSEC16_OK | BPB_TOTSEC32_OK | \ 319f127cb91Sfrankho BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_BPBSIG_OK) 320f127cb91Sfrankho 321f127cb91Sfrankho /* 322f127cb91Sfrankho * A note on FAT32: According to the FAT spec, FAT32 _must_ have a valid 323f127cb91Sfrankho * extended BPB and therefore, as a proof of its existance, the FAT32 324f127cb91Sfrankho * boot signature (offset 66) must be valid as well. Why don't we check 325f127cb91Sfrankho * for BPB_BOOTSIG32_OK then ? 326f127cb91Sfrankho * 327f127cb91Sfrankho * We don't test for this here first-pass, because there are media out 328f127cb91Sfrankho * there that are valid FAT32 structurally but don't have a valid sig. 329f127cb91Sfrankho * This happens if older versions of the SYSLINUX bootloader (below 3.x) 330f127cb91Sfrankho * are installed on a media with a FAT32 on it. SYSLINUX 2.x and lower 331f127cb91Sfrankho * overwrite the BPB past the end of the FAT12/16 extension with its 332f127cb91Sfrankho * bootloader code - and the FAT16 extended BPB is 62 Bytes... 333f127cb91Sfrankho * All structurally relevant fields of the FAT32 BPB are within the first 334f127cb91Sfrankho * 52 Bytes, so the filesystem is accessible - but the signature check 335f127cb91Sfrankho * would reject it. 336f127cb91Sfrankho */ 337f127cb91Sfrankho #define FAT32_VALIDMSK \ 338f127cb91Sfrankho (BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \ 339f127cb91Sfrankho BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \ 340f127cb91Sfrankho BPB_TOTSEC_OK | BPB_TOTSEC16_OK | BPB_TOTSEC32_OK | \ 341f127cb91Sfrankho BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_FATSZ32_OK | \ 342f127cb91Sfrankho BPB_EXTFLAGS_OK | BPB_FSVER_OK | BPB_ROOTCLUSTER_OK | \ 343f127cb91Sfrankho BPB_BPBSIG_OK) 344f127cb91Sfrankho 345f127cb91Sfrankho /* 346f127cb91Sfrankho * FAT32 BPB allows 'versioning' via FSVer32. We follow the 'NULL' spec. 347f127cb91Sfrankho */ 348f127cb91Sfrankho #define PCFS_SUPPORTED_FSVER 0 349f127cb91Sfrankho 350f127cb91Sfrankho 351f127cb91Sfrankho /* 352f127cb91Sfrankho * Filesystem summary information (introduced originally for FAT32 volumes). 353f127cb91Sfrankho * We need to maintain fs_free_clusters or Microsoft Scandisk will be upset. 354f127cb91Sfrankho * We keep these values in-core even for FAT12/FAT16 but will never attempt 355f127cb91Sfrankho * to write them out to disk then. 356f127cb91Sfrankho */ 357f127cb91Sfrankho typedef struct fat_fsinfo { 358f127cb91Sfrankho uint32_t fs_free_clusters; /* # free clusters. -1 if unknown */ 359f127cb91Sfrankho uint32_t fs_next_free; /* search next free after this cn */ 360f127cb91Sfrankho } fat_fsi_t; 361f127cb91Sfrankho 362f127cb91Sfrankho /* 363f127cb91Sfrankho * On-disk FSI. All values in little endian. Only FAT32 has this. 364f127cb91Sfrankho */ 365f127cb91Sfrankho typedef struct fat_od_fsi { 366f127cb91Sfrankho uint32_t fsi_leadsig; /* 0x41615252 */ 367f127cb91Sfrankho char fsi_reserved1[480]; 368f127cb91Sfrankho uint32_t fsi_strucsig; /* 0x61417272 */ 369f127cb91Sfrankho fat_fsi_t fsi_incore; /* free/nextfree */ 370f127cb91Sfrankho char fsi_reserved2[12]; 371f127cb91Sfrankho uint32_t fsi_trailsig; /* 0xaa550000 */ 372f127cb91Sfrankho } fat_od_fsi_t; 373f127cb91Sfrankho 374f127cb91Sfrankho #define FSI_LEADSIG LE_32(0x41615252) 375f127cb91Sfrankho #define FSI_STRUCSIG LE_32(0x61417272) 376f127cb91Sfrankho #define FSI_TRAILSIG LE_32(0xaa550000) /* same as MBB_MAGIC */ 377f127cb91Sfrankho 378f127cb91Sfrankho #define FSISIG_OK(fsi) ( \ 379f127cb91Sfrankho ((fat_od_fsi_t *)(fsi))->fsi_leadsig == FSI_LEADSIG && \ 380f127cb91Sfrankho ((fat_od_fsi_t *)(fsi))->fsi_strucsig == FSI_STRUCSIG && \ 381f127cb91Sfrankho ((fat_od_fsi_t *)(fsi))->fsi_trailsig == FSI_TRAILSIG) 382f127cb91Sfrankho 383f127cb91Sfrankho #define FSINFO_UNKNOWN ((uint32_t)(-1)) /* free/next not valid */ 384f127cb91Sfrankho 385f127cb91Sfrankho typedef enum { FAT12, FAT16, FAT32, FAT_UNKNOWN, FAT_QUESTIONABLE } fattype_t; 386f127cb91Sfrankho 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate struct pcfs { 3897c478bd9Sstevel@tonic-gate struct vfs *pcfs_vfs; /* vfs for this fs */ 3907c478bd9Sstevel@tonic-gate int pcfs_flags; /* flags */ 391f127cb91Sfrankho int pcfs_ldrive; /* logical DOS drive number */ 392f127cb91Sfrankho fattype_t pcfs_fattype; 3937c478bd9Sstevel@tonic-gate dev_t pcfs_xdev; /* actual device that is mounted */ 3947c478bd9Sstevel@tonic-gate struct vnode *pcfs_devvp; /* and a vnode for it */ 3957c478bd9Sstevel@tonic-gate int pcfs_secsize; /* sector size in bytes */ 3967c478bd9Sstevel@tonic-gate int pcfs_spcl; /* sectors per cluster */ 3977c478bd9Sstevel@tonic-gate int pcfs_spt; /* sectors per track */ 3987c478bd9Sstevel@tonic-gate int pcfs_sdshift; /* shift to convert sector into */ 3997c478bd9Sstevel@tonic-gate /* DEV_BSIZE "sectors"; assume */ 4007c478bd9Sstevel@tonic-gate /* pcfs_secsize is 2**n times of */ 4017c478bd9Sstevel@tonic-gate /* DEV_BSIZE */ 4027c478bd9Sstevel@tonic-gate int pcfs_fatsec; /* number of sec per FAT */ 4037c478bd9Sstevel@tonic-gate int pcfs_numfat; /* number of FAT copies */ 4047c478bd9Sstevel@tonic-gate int pcfs_rdirsec; /* number of sec in root dir */ 4057c478bd9Sstevel@tonic-gate daddr_t pcfs_dosstart; /* start blkno of DOS partition */ 406f127cb91Sfrankho daddr_t pcfs_fsistart; /* start blkno of FSI sector */ 4077c478bd9Sstevel@tonic-gate daddr_t pcfs_fatstart; /* start blkno of first FAT */ 4087c478bd9Sstevel@tonic-gate daddr_t pcfs_rdirstart; /* start blkno of root dir */ 4097c478bd9Sstevel@tonic-gate daddr_t pcfs_datastart; /* start blkno of data area */ 4107c478bd9Sstevel@tonic-gate int pcfs_clsize; /* cluster size in bytes */ 4117c478bd9Sstevel@tonic-gate int pcfs_ncluster; /* number of clusters in fs */ 4127c478bd9Sstevel@tonic-gate int pcfs_nrefs; /* number of active pcnodes */ 4137c478bd9Sstevel@tonic-gate int pcfs_frefs; /* number of active file pcnodes */ 4147c478bd9Sstevel@tonic-gate int pcfs_nxfrecls; /* next free cluster */ 4157c478bd9Sstevel@tonic-gate uchar_t *pcfs_fatp; /* ptr to FAT data */ 4167c478bd9Sstevel@tonic-gate uchar_t *pcfs_fat_changemap; /* map of changed fat data */ 4177c478bd9Sstevel@tonic-gate int pcfs_fat_changemapsize; /* size of FAT changemap */ 4187c478bd9Sstevel@tonic-gate time_t pcfs_fattime; /* time FAT becomes invalid */ 4197c478bd9Sstevel@tonic-gate time_t pcfs_verifytime; /* time to reverify disk */ 4207c478bd9Sstevel@tonic-gate kmutex_t pcfs_lock; /* per filesystem lock */ 4217c478bd9Sstevel@tonic-gate kthread_id_t pcfs_owner; /* id of thread locking pcfs */ 4227c478bd9Sstevel@tonic-gate int pcfs_count; /* # of pcfs locks for pcfs_owner */ 423f127cb91Sfrankho struct fat_fsinfo pcfs_fsinfo; /* in-core fsinfo */ 4247c478bd9Sstevel@tonic-gate struct pcfs *pcfs_nxt; /* linked list of all mounts */ 4257c478bd9Sstevel@tonic-gate int pcfs_fatjustread; /* Used to flag a freshly found FAT */ 426264a6e74Sfrankho struct vnode *pcfs_root; /* vnode for the root dir of the fs */ 427f127cb91Sfrankho int pcfs_secondswest; /* recording timezone for this fs */ 428f127cb91Sfrankho len_t pcfs_mediasize; 429f127cb91Sfrankho int pcfs_rootblksize; 430f127cb91Sfrankho int pcfs_mediadesc; /* media descriptor */ 431f127cb91Sfrankho pc_cluster32_t pcfs_lastclmark; 432f127cb91Sfrankho pc_cluster32_t pcfs_rootclnum; 433f127cb91Sfrankho timestruc_t pcfs_mounttime; /* timestamp for "/" */ 4347c478bd9Sstevel@tonic-gate }; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * flags 4387c478bd9Sstevel@tonic-gate */ 4397c478bd9Sstevel@tonic-gate #define PCFS_FATMOD 0x01 /* FAT has been modified */ 4407c478bd9Sstevel@tonic-gate #define PCFS_LOCKED 0x02 /* fs is locked */ 4417c478bd9Sstevel@tonic-gate #define PCFS_WANTED 0x04 /* locked fs is wanted */ 4427c478bd9Sstevel@tonic-gate #define PCFS_NOCHK 0x800 /* don't resync fat on error */ 4437c478bd9Sstevel@tonic-gate #define PCFS_BOOTPART 0x1000 /* boot partition type */ 4447c478bd9Sstevel@tonic-gate #define PCFS_HIDDEN 0x2000 /* show hidden files */ 4457c478bd9Sstevel@tonic-gate #define PCFS_PCMCIA_NO_CIS 0x4000 /* PCMCIA psuedo floppy */ 446264a6e74Sfrankho #define PCFS_FOLDCASE 0x8000 /* fold filenames to lowercase */ 447f127cb91Sfrankho #define PCFS_FSINFO_OK 0x10000 /* valid FAT32 fsinfo sector */ 4487c478bd9Sstevel@tonic-gate #define PCFS_IRRECOV 0x20000 /* FS was messed with during write */ 449264a6e74Sfrankho #define PCFS_NOCLAMPTIME 0x40000 /* expose full FAT timestamp range */ 450f127cb91Sfrankho #define PCFS_NOATIME 0x80000 /* disable atime updates */ 451f127cb91Sfrankho 452f127cb91Sfrankho #define IS_FAT12(PCFS) ((PCFS)->pcfs_fattype == FAT12) 453f127cb91Sfrankho #define IS_FAT16(PCFS) ((PCFS)->pcfs_fattype == FAT16) 454f127cb91Sfrankho #define IS_FAT32(PCFS) ((PCFS)->pcfs_fattype == FAT32) 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* for compatibility */ 4577c478bd9Sstevel@tonic-gate struct old_pcfs_args { 4587c478bd9Sstevel@tonic-gate int secondswest; /* seconds west of Greenwich */ 4597c478bd9Sstevel@tonic-gate int dsttime; /* type of dst correction */ 4607c478bd9Sstevel@tonic-gate }; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate struct pcfs_args { 4637c478bd9Sstevel@tonic-gate int secondswest; /* seconds west of Greenwich */ 4647c478bd9Sstevel@tonic-gate int dsttime; /* type of dst correction */ 4657c478bd9Sstevel@tonic-gate int flags; 4667c478bd9Sstevel@tonic-gate }; 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate /* 4697c478bd9Sstevel@tonic-gate * pcfs mount options. 4707c478bd9Sstevel@tonic-gate */ 4717c478bd9Sstevel@tonic-gate #define MNTOPT_PCFS_HIDDEN "hidden" 4727c478bd9Sstevel@tonic-gate #define MNTOPT_PCFS_NOHIDDEN "nohidden" 4737c478bd9Sstevel@tonic-gate #define MNTOPT_PCFS_FOLDCASE "foldcase" 4747c478bd9Sstevel@tonic-gate #define MNTOPT_PCFS_NOFOLDCASE "nofoldcase" 475264a6e74Sfrankho #define MNTOPT_PCFS_CLAMPTIME "clamptime" 476264a6e74Sfrankho #define MNTOPT_PCFS_NOCLAMPTIME "noclamptime" 477f127cb91Sfrankho #define MNTOPT_PCFS_TIMEZONE "timezone" 478f127cb91Sfrankho #define MNTOPT_PCFS_SECSIZE "secsize" 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate /* 4817c478bd9Sstevel@tonic-gate * Disk timeout value in sec. 4827c478bd9Sstevel@tonic-gate * This is used to time out the in core FAT and to re-verify the disk. 4837c478bd9Sstevel@tonic-gate * This should be less than the time it takes to change floppys 4847c478bd9Sstevel@tonic-gate */ 4857c478bd9Sstevel@tonic-gate #define PCFS_DISKTIMEOUT 2 4867c478bd9Sstevel@tonic-gate 487f127cb91Sfrankho #define PCFS_MAXOFFSET_T UINT32_MAX /* PCFS max file size */ 488f127cb91Sfrankho 4897c478bd9Sstevel@tonic-gate #define VFSTOPCFS(VFSP) ((struct pcfs *)((VFSP)->vfs_data)) 4907c478bd9Sstevel@tonic-gate #define PCFSTOVFS(FSP) ((FSP)->pcfs_vfs) 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate /* 4937c478bd9Sstevel@tonic-gate * special cluster numbers in FAT 4947c478bd9Sstevel@tonic-gate */ 4957c478bd9Sstevel@tonic-gate #define PCF_FREECLUSTER 0x00 /* cluster is available */ 4967c478bd9Sstevel@tonic-gate #define PCF_ERRORCLUSTER 0x01 /* error occurred allocating cluster */ 4977c478bd9Sstevel@tonic-gate #define PCF_12BCLUSTER 0xFF0 /* 12-bit version of reserved cluster */ 4987c478bd9Sstevel@tonic-gate #define PCF_RESCLUSTER 0xFFF0 /* 16-bit version of reserved cluster */ 4997c478bd9Sstevel@tonic-gate #define PCF_RESCLUSTER32 0xFFFFFF0 /* 32-bit version */ 5007c478bd9Sstevel@tonic-gate #define PCF_BADCLUSTER 0xFFF7 /* bad cluster, do not use */ 5017c478bd9Sstevel@tonic-gate #define PCF_BADCLUSTER32 0xFFFFFF7 /* 32-bit version */ 5027c478bd9Sstevel@tonic-gate #define PCF_LASTCLUSTER 0xFFF8 /* >= means last cluster in file */ 5037c478bd9Sstevel@tonic-gate #define PCF_LASTCLUSTER32 0xFFFFFF8 /* 32-bit version */ 5047c478bd9Sstevel@tonic-gate #define PCF_LASTCLUSTERMARK 0xFFFF /* value used to mark last cluster */ 5057c478bd9Sstevel@tonic-gate #define PCF_LASTCLUSTERMARK32 0xFFFFFFF /* 32-bit version */ 5067c478bd9Sstevel@tonic-gate #define PCF_FIRSTCLUSTER 2 /* first valid cluster number */ 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate /* 5097c478bd9Sstevel@tonic-gate * file system constants 5107c478bd9Sstevel@tonic-gate */ 5117c478bd9Sstevel@tonic-gate #define PC_MAXFATSEC 256 /* maximum number of sectors in FAT */ 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate /* 5147c478bd9Sstevel@tonic-gate * file system parameter macros 5157c478bd9Sstevel@tonic-gate */ 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate #define pc_clear_fatchanges(PCFS) \ 5187c478bd9Sstevel@tonic-gate bzero((PCFS)->pcfs_fat_changemap, (PCFS)->pcfs_fat_changemapsize) 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate #define pc_blksize(PCFS, PCP, OFF) /* file system block size */ \ 5217c478bd9Sstevel@tonic-gate (((PCTOV(PCP)->v_flag & VROOT) && !IS_FAT32(PCFS)) ? \ 5227c478bd9Sstevel@tonic-gate ((OFF) >= \ 5237c478bd9Sstevel@tonic-gate ((PCFS)->pcfs_rdirsec & \ 5247c478bd9Sstevel@tonic-gate ~((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize)? \ 5257c478bd9Sstevel@tonic-gate ((PCFS)->pcfs_rdirsec & \ 5267c478bd9Sstevel@tonic-gate ((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize): \ 5277c478bd9Sstevel@tonic-gate (PCFS)->pcfs_clsize): \ 5287c478bd9Sstevel@tonic-gate (PCFS)->pcfs_clsize) 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate #define pc_blkoff(PCFS, OFF) /* offset within block */ \ 5317c478bd9Sstevel@tonic-gate ((int)((OFF) & ((PCFS)->pcfs_clsize - 1))) 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate #define pc_lblkno(PCFS, OFF) /* logical block (cluster) no */ \ 5347c478bd9Sstevel@tonic-gate ((daddr_t)((OFF) / (PCFS)->pcfs_clsize)) 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate #define pc_dbtocl(PCFS, DB) /* disk blks to clusters */ \ 5377c478bd9Sstevel@tonic-gate ((int)((DB) / (PCFS)->pcfs_spcl)) 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate #define pc_cltodb(PCFS, CL) /* clusters to disk blks */ \ 5407c478bd9Sstevel@tonic-gate ((daddr_t)((CL) * (PCFS)->pcfs_spcl)) 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate #define pc_dbdaddr(PCFS, DB) /* sector to DEV_BSIZE "sector" addr */ \ 5437c478bd9Sstevel@tonic-gate ((DB) << (PCFS)->pcfs_sdshift) 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate #define pc_daddrdb(PCFS, DADDR) /* DEV_BSIZE "sector" addr to sector addr */ \ 5467c478bd9Sstevel@tonic-gate ((DADDR) >> (PCFS)->pcfs_sdshift) 5477c478bd9Sstevel@tonic-gate 548f127cb91Sfrankho #define pc_cldaddr(PCFS, CL) /* DEV_BSIZE "sector" addr for cluster */ \ 549f127cb91Sfrankho pc_dbdaddr(PCFS, ((daddr_t)((PCFS)->pcfs_datastart + \ 550f127cb91Sfrankho pc_cltodb(PCFS, (CL) - PCF_FIRSTCLUSTER)))) 551f127cb91Sfrankho 552f127cb91Sfrankho #define pc_daddrcl(PCFS, DADDR) /* cluster for disk address */ \ 553f127cb91Sfrankho ((int)(PCF_FIRSTCLUSTER + \ 554f127cb91Sfrankho pc_dbtocl(pc_daddrdb(PCFS, DADDR) - (PCFS)->pcfs_datastart))) 555f127cb91Sfrankho 556f127cb91Sfrankho /* 557f127cb91Sfrankho * Number of directory entries per sector / cluster 558f127cb91Sfrankho */ 559f127cb91Sfrankho #define pc_direntpersec(PCFS) \ 560f127cb91Sfrankho ((int)((PCFS)->pcfs_secsize / sizeof (struct pcdir))) 561f127cb91Sfrankho 562f127cb91Sfrankho #define pc_direntpercl(PCFS) \ 563f127cb91Sfrankho ((int)((PCFS)->pcfs_clsize / sizeof (struct pcdir))) 564f127cb91Sfrankho 565f127cb91Sfrankho /* 566f127cb91Sfrankho * out-of-range check for cluster numbers. 567f127cb91Sfrankho */ 5687c478bd9Sstevel@tonic-gate #define pc_validcl(PCFS, CL) /* check that cluster no is legit */ \ 5697c478bd9Sstevel@tonic-gate ((int)(CL) >= PCF_FIRSTCLUSTER && \ 570*32d46495SMichael Bergknoff (int)(CL) < (PCFS)->pcfs_ncluster + PCF_FIRSTCLUSTER) 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate /* 5737c478bd9Sstevel@tonic-gate * external routines. 5747c478bd9Sstevel@tonic-gate */ 5757c478bd9Sstevel@tonic-gate extern int pc_lockfs(struct pcfs *, int, int); /* lock fs and get fat */ 5767c478bd9Sstevel@tonic-gate extern void pc_unlockfs(struct pcfs *); /* ulock the fs */ 5777c478bd9Sstevel@tonic-gate extern int pc_getfat(struct pcfs *); /* get fat from disk */ 5787c478bd9Sstevel@tonic-gate extern void pc_invalfat(struct pcfs *); /* invalidate incore fat */ 5797c478bd9Sstevel@tonic-gate extern int pc_syncfat(struct pcfs *); /* sync fat to disk */ 5807c478bd9Sstevel@tonic-gate extern int pc_freeclusters(struct pcfs *); /* num free clusters in fs */ 5817c478bd9Sstevel@tonic-gate extern pc_cluster32_t pc_alloccluster(struct pcfs *, int); 5827c478bd9Sstevel@tonic-gate extern void pc_setcluster(struct pcfs *, pc_cluster32_t, pc_cluster32_t); 5837c478bd9Sstevel@tonic-gate extern void pc_mark_fat_updated(struct pcfs *fsp, pc_cluster32_t cn); 5847c478bd9Sstevel@tonic-gate extern int pc_fat_is_changed(struct pcfs *fsp, pc_cluster32_t bn); 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate /* 5877c478bd9Sstevel@tonic-gate * debugging 5887c478bd9Sstevel@tonic-gate */ 5897c478bd9Sstevel@tonic-gate extern int pcfsdebuglevel; 5907c478bd9Sstevel@tonic-gate #define PC_DPRINTF0(level, A) \ 5917c478bd9Sstevel@tonic-gate if (pcfsdebuglevel >= level) \ 5927c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, (A)) 5937c478bd9Sstevel@tonic-gate #define PC_DPRINTF1(level, A, B) \ 5947c478bd9Sstevel@tonic-gate if (pcfsdebuglevel >= level) \ 5957c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, (A), (B)) 5967c478bd9Sstevel@tonic-gate #define PC_DPRINTF2(level, A, B, C) \ 5977c478bd9Sstevel@tonic-gate if (pcfsdebuglevel >= level) \ 5987c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, (A), (B), (C)) 5997c478bd9Sstevel@tonic-gate #define PC_DPRINTF3(level, A, B, C, D) \ 6007c478bd9Sstevel@tonic-gate if (pcfsdebuglevel >= level) \ 6017c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, (A), (B), (C), (D)) 6027c478bd9Sstevel@tonic-gate #define PC_DPRINTF4(level, A, B, C, D, E) \ 6037c478bd9Sstevel@tonic-gate if (pcfsdebuglevel >= level) \ 6047c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, (A), (B), (C), (D), (E)) 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate #ifdef __cplusplus 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate #endif 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate #endif /* _SYS_FS_PC_FS_H */ 611