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