diff options
38 files changed, 69 insertions, 8021 deletions
diff --git a/contrib/amd/include/am_defs.h b/contrib/amd/include/am_defs.h index 36c695e..203dcad 100644 --- a/contrib/amd/include/am_defs.h +++ b/contrib/amd/include/am_defs.h @@ -743,7 +743,11 @@ struct sockaddr_dl; */ #ifdef HAVE_MSDOSFS_MSDOSFSMOUNT_H # include <msdosfs/msdosfsmount.h> -#endif /* HAVE_MSDOSFS_MSDOSFSMOUNT_H */ +#else /* not HAVE_MSDOSFS_MSDOSFSMOUNT_H */ +# ifdef HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H +# include <fs/msdosfs/msdosfsmount.h> +# endif /* HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H */ +#endif /* not HAVE_MSDOSFS_MSDOSFSMOUNT_H */ /* * Actions to take if <sys/fs/tmp.h> exists. diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 05a2ed1..7028770 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -24,6 +24,8 @@ .. fifofs .. + msdosfs + .. nullfs .. portalfs @@ -49,8 +51,6 @@ .. machine .. - msdosfs - .. net .. netatalk diff --git a/include/Makefile b/include/Makefile index 4f2b4fb..4b68b53 100644 --- a/include/Makefile +++ b/include/Makefile @@ -39,15 +39,16 @@ SFILES= soundcard.h joystick.h LFILES= aio.h errno.h fcntl.h inttypes.h linker_set.h poll.h syslog.h \ termios.h ucontext.h -LDIRS= cam msdosfs net netatalk netatm netgraph netinet netinet6 \ +LDIRS= cam net netatalk netatm netgraph netinet netinet6 \ netipx netkey netnatm netncp netns netsmb nfs ntfs nwfs pccard posix4 \ sys vm LNOHEADERDIRS= fs isofs ufs dev LSUBDIRS= cam/scsi dev/ppbus dev/usb dev/wi \ - fs/fdescfs fs/fifofs fs/nullfs fs/portalfs fs/procfs fs/smbfs \ - fs/umapfs fs/unionfs isofs/cd9660 ufs/ffs ufs/mfs ufs/ufs + fs/fdescfs fs/fifofs fs/msdosfs fs/nullfs fs/portalfs \ + fs/procfs fs/smbfs fs/umapfs fs/unionfs isofs/cd9660 \ + ufs/ffs ufs/mfs ufs/ufs # For SHARED=symlinks, cam is a symlink, so cam/scsi is taken care of LSYMSUBDIRS= ${LSUBDIRS:Ncam/scsi} diff --git a/sbin/mount_msdos/mount_msdos.c b/sbin/mount_msdos/mount_msdos.c index 8265826..a758d3d 100644 --- a/sbin/mount_msdos/mount_msdos.c +++ b/sbin/mount_msdos/mount_msdos.c @@ -39,7 +39,7 @@ static const char rcsid[] = #include <sys/mount.h> #include <sys/stat.h> -#include <msdosfs/msdosfsmount.h> +#include <fs/msdosfs/msdosfsmount.h> #include <ctype.h> #include <err.h> diff --git a/sbin/mount_msdosfs/mount_msdosfs.c b/sbin/mount_msdosfs/mount_msdosfs.c index 8265826..a758d3d 100644 --- a/sbin/mount_msdosfs/mount_msdosfs.c +++ b/sbin/mount_msdosfs/mount_msdosfs.c @@ -39,7 +39,7 @@ static const char rcsid[] = #include <sys/mount.h> #include <sys/stat.h> -#include <msdosfs/msdosfsmount.h> +#include <fs/msdosfs/msdosfsmount.h> #include <ctype.h> #include <err.h> diff --git a/sbin/mountd/mountd.c b/sbin/mountd/mountd.c index cab8bc0..2d198e6 100644 --- a/sbin/mountd/mountd.c +++ b/sbin/mountd/mountd.c @@ -63,7 +63,7 @@ static const char rcsid[] = #include <nfs/nfsproto.h> #include <nfs/nfs.h> #include <ufs/ufs/ufsmount.h> -#include <msdosfs/msdosfsmount.h> +#include <fs/msdosfs/msdosfsmount.h> #include <ntfs/ntfsmount.h> #include <isofs/cd9660/cd9660_mount.h> /* XXX need isofs in include */ diff --git a/share/man/man7/hier.7 b/share/man/man7/hier.7 index 5d0d627..5197b80 100644 --- a/share/man/man7/hier.7 +++ b/share/man/man7/hier.7 @@ -179,6 +179,8 @@ per-process file descriptors file system .It Pa fifofs/ .St -p1003.1 FIFOs file system +.It Pa msdosfs/ +MS-DOS file system .It Pa nullfs/ loopback file system .It Pa portalfs/ @@ -211,8 +213,6 @@ see .Xr kerberos 1 .It Pa machine/ machine-specific C include files -.It Pa msdosfs/ -MS-DOS file system .It Pa net/ misc network C include files .It Pa netatalk/ diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf index 65a8c10..bedc201 100644 --- a/sys/boot/forth/loader.conf +++ b/sys/boot/forth/loader.conf @@ -89,7 +89,7 @@ cd9660_load="NO" # ISO 9660 filesystem coda_load="NO" # CODA filesystem fdescfs_load="NO" # Filedescriptors filesystem mfs_load="NO" # Memory filesystem -msdos_load="NO" # FAT-12/16/32 +msdosfs_load="NO" # FAT-12/16/32 nfs_load="NO" # NFS ntfs_load="NO" # NTFS nullfs_load="NO" # Null filesystem diff --git a/sys/conf/files b/sys/conf/files index 9d11055..ec8ae7b 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -598,6 +598,12 @@ fs/hpfs/hpfs_lookup.c optional hpfs fs/hpfs/hpfs_subr.c optional hpfs fs/hpfs/hpfs_vfsops.c optional hpfs fs/hpfs/hpfs_vnops.c optional hpfs +fs/msdosfs/msdosfs_conv.c optional msdosfs +fs/msdosfs/msdosfs_denode.c optional msdosfs +fs/msdosfs/msdosfs_fat.c optional msdosfs +fs/msdosfs/msdosfs_lookup.c optional msdosfs +fs/msdosfs/msdosfs_vfsops.c optional msdosfs +fs/msdosfs/msdosfs_vnops.c optional msdosfs fs/nullfs/null_subr.c optional nullfs fs/nullfs/null_vfsops.c optional nullfs fs/nullfs/null_vnops.c optional nullfs @@ -833,12 +839,6 @@ libkern/strtol.c standard libkern/strtoq.c standard libkern/strtoul.c standard libkern/strtouq.c standard -msdosfs/msdosfs_conv.c optional msdosfs -msdosfs/msdosfs_denode.c optional msdosfs -msdosfs/msdosfs_fat.c optional msdosfs -msdosfs/msdosfs_lookup.c optional msdosfs -msdosfs/msdosfs_vfsops.c optional msdosfs -msdosfs/msdosfs_vnops.c optional msdosfs net/bpf.c standard net/bpf_filter.c optional bpf bpf.h standard \ diff --git a/sys/fs/msdosfs/msdosfs_conv.c b/sys/fs/msdosfs/msdosfs_conv.c index 8c43f93..1cfe6a4 100644 --- a/sys/fs/msdosfs/msdosfs_conv.c +++ b/sys/fs/msdosfs/msdosfs_conv.c @@ -61,7 +61,7 @@ /* * MSDOSFS include files. */ -#include <msdosfs/direntry.h> +#include <fs/msdosfs/direntry.h> /* * Total number of days that have passed for each month in a regular year. diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c index dbdf554..bf176bd 100644 --- a/sys/fs/msdosfs/msdosfs_denode.c +++ b/sys/fs/msdosfs/msdosfs_denode.c @@ -61,11 +61,11 @@ #include <vm/vm.h> #include <vm/vm_extern.h> -#include <msdosfs/bpb.h> -#include <msdosfs/msdosfsmount.h> -#include <msdosfs/direntry.h> -#include <msdosfs/denode.h> -#include <msdosfs/fat.h> +#include <fs/msdosfs/bpb.h> +#include <fs/msdosfs/msdosfsmount.h> +#include <fs/msdosfs/direntry.h> +#include <fs/msdosfs/denode.h> +#include <fs/msdosfs/fat.h> static MALLOC_DEFINE(M_MSDOSFSNODE, "MSDOSFS node", "MSDOSFS vnode private part"); diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c index 38abc16..828edb70 100644 --- a/sys/fs/msdosfs/msdosfs_fat.c +++ b/sys/fs/msdosfs/msdosfs_fat.c @@ -61,11 +61,11 @@ /* * msdosfs include files. */ -#include <msdosfs/bpb.h> -#include <msdosfs/msdosfsmount.h> -#include <msdosfs/direntry.h> -#include <msdosfs/denode.h> -#include <msdosfs/fat.h> +#include <fs/msdosfs/bpb.h> +#include <fs/msdosfs/msdosfsmount.h> +#include <fs/msdosfs/direntry.h> +#include <fs/msdosfs/denode.h> +#include <fs/msdosfs/fat.h> /* * Fat cache stats. diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c index 776559d..987ac3b 100644 --- a/sys/fs/msdosfs/msdosfs_lookup.c +++ b/sys/fs/msdosfs/msdosfs_lookup.c @@ -56,11 +56,11 @@ #include <sys/vnode.h> #include <sys/mount.h> -#include <msdosfs/bpb.h> -#include <msdosfs/direntry.h> -#include <msdosfs/denode.h> -#include <msdosfs/msdosfsmount.h> -#include <msdosfs/fat.h> +#include <fs/msdosfs/bpb.h> +#include <fs/msdosfs/direntry.h> +#include <fs/msdosfs/denode.h> +#include <fs/msdosfs/msdosfsmount.h> +#include <fs/msdosfs/fat.h> /* * When we search a directory the blocks containing directory entries are diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c index abaeb7f..962632a 100644 --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -63,12 +63,12 @@ #include <sys/stat.h> /* defines ALLPERMS */ #include <sys/mutex.h> -#include <msdosfs/bpb.h> -#include <msdosfs/bootsect.h> -#include <msdosfs/direntry.h> -#include <msdosfs/denode.h> -#include <msdosfs/msdosfsmount.h> -#include <msdosfs/fat.h> +#include <fs/msdosfs/bpb.h> +#include <fs/msdosfs/bootsect.h> +#include <fs/msdosfs/direntry.h> +#include <fs/msdosfs/denode.h> +#include <fs/msdosfs/msdosfsmount.h> +#include <fs/msdosfs/fat.h> #define MSDOSFS_DFLTBSIZE 4096 diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index b942d30..29a59ec 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -70,11 +70,11 @@ #include <machine/mutex.h> -#include <msdosfs/bpb.h> -#include <msdosfs/direntry.h> -#include <msdosfs/denode.h> -#include <msdosfs/msdosfsmount.h> -#include <msdosfs/fat.h> +#include <fs/msdosfs/bpb.h> +#include <fs/msdosfs/direntry.h> +#include <fs/msdosfs/denode.h> +#include <fs/msdosfs/msdosfsmount.h> +#include <fs/msdosfs/fat.h> #define DOS_FILESIZE_MAX 0xffffffff diff --git a/sys/kern/Make.tags.inc b/sys/kern/Make.tags.inc index 59dd7a7..35ec2ed 100644 --- a/sys/kern/Make.tags.inc +++ b/sys/kern/Make.tags.inc @@ -31,6 +31,7 @@ COMM= ${SYS}/conf/*.[ch] \ ${SYS}/fs/deadfs/*.[ch] \ ${SYS}/fs/fdescfs/*.[ch] \ ${SYS}/fs/fifofs/*.[ch] \ + ${SYS}/fs/msdosfs/*.[ch] \ ${SYS}/fs/nullfs/*.[ch] \ ${SYS}/fs/portalfs/*.[ch] \ ${SYS}/fs/procfs/*.[ch] \ @@ -39,7 +40,6 @@ COMM= ${SYS}/conf/*.[ch] \ ${SYS}/fs/unionfs/*.[ch] \ ${SYS}/isofs/cd9660/*.[ch] \ ${SYS}/kern/*.[ch] \ - ${SYS}/msdosfs/*.[ch] \ ${SYS}/net/*.[ch] \ ${SYS}/netatalk/*.[ch] \ ${SYS}/netatm/*.[ch] \ @@ -59,7 +59,6 @@ COMM= ${SYS}/conf/*.[ch] \ COMMDIR1= ${SYS}/conf \ ${SYS}/kern \ - ${SYS}/msdosfs \ ${SYS}/net \ ${SYS}/netatalk \ ${SYS}/netatm \ @@ -95,6 +94,7 @@ COMMDIR2= ${SYS}/dev/advansys \ ${SYS}/fs/devfs \ ${SYS}/fs/fdescfs \ ${SYS}/fs/fifofs \ + ${SYS}/fs/msdosfs \ ${SYS}/fs/nullfs \ ${SYS}/fs/portalfs \ ${SYS}/fs/procfs \ diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 86a0065..d0753a5 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -9,7 +9,7 @@ _random= random SUBDIR= 3dfx accf_data accf_http agp aha amr an aue \ cam ccd cd9660 coda cue dc de dgm digi ed fdescfs fxp if_disc if_ef \ if_ppp if_sl if_tap if_tun ip6fw ipfilter ipfw ispfw joy kue \ - libmchain linux lnc md mfs mii mlx msdos ncp netgraph nfs nge ntfs \ + libmchain linux lnc md mfs mii mlx msdosfs ncp netgraph nfs nge ntfs \ nullfs nwfs pcn portalfs procfs ${_random} \ rl rp sf sis sk sn snp sound sppp ste sym syscons sysvipc ti tl twe \ tx udbp ugen uhid ukbd ulpt umapfs umass umodem ums unionfs urio usb \ diff --git a/sys/modules/msdos/Makefile b/sys/modules/msdos/Makefile deleted file mode 100644 index fb3b2f8..0000000 --- a/sys/modules/msdos/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../msdosfs - -KMOD= msdos -SRCS= vnode_if.h \ - msdosfs_conv.c msdosfs_denode.c msdosfs_fat.c msdosfs_lookup.c \ - msdosfs_vfsops.c msdosfs_vnops.c -NOMAN= - -.if ${MACHINE} == "pc98" -CFLAGS+= -DPC98 -.endif - -.include <bsd.kmod.mk> diff --git a/sys/modules/msdosfs/Makefile b/sys/modules/msdosfs/Makefile index fb3b2f8..62a9ba9 100644 --- a/sys/modules/msdosfs/Makefile +++ b/sys/modules/msdosfs/Makefile @@ -1,8 +1,8 @@ # $FreeBSD$ -.PATH: ${.CURDIR}/../../msdosfs +.PATH: ${.CURDIR}/../../fs/msdosfs -KMOD= msdos +KMOD= msdosfs SRCS= vnode_if.h \ msdosfs_conv.c msdosfs_denode.c msdosfs_fat.c msdosfs_lookup.c \ msdosfs_vfsops.c msdosfs_vnops.c diff --git a/sys/msdosfs/bootsect.h b/sys/msdosfs/bootsect.h deleted file mode 100644 index c3e3d68..0000000 --- a/sys/msdosfs/bootsect.h +++ /dev/null @@ -1,113 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: bootsect.h,v 1.9 1997/11/17 15:36:17 ws Exp $ */ - -/* - * 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 - */ - -/* - * Format of a boot sector. This is the first sector on a DOS floppy disk - * or the fist sector of a partition on a hard disk. But, it is not the - * first sector of a partitioned hard disk. - */ -struct bootsector33 { - u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ - int8_t bsOemName[8]; /* OEM name and version */ - int8_t bsBPB[19]; /* BIOS parameter block */ - int8_t bsDriveNumber; /* drive number (0x80) */ - int8_t bsBootCode[479]; /* pad so struct is 512b */ - u_int8_t bsBootSectSig0; - u_int8_t bsBootSectSig1; -#define BOOTSIG0 0x55 -#define BOOTSIG1 0xaa -}; - -struct extboot { - int8_t exDriveNumber; /* drive number (0x80) */ - int8_t exReserved1; /* reserved */ - int8_t exBootSignature; /* ext. boot signature (0x29) */ -#define EXBOOTSIG 0x29 - int8_t exVolumeID[4]; /* volume ID number */ - int8_t exVolumeLabel[11]; /* volume label */ - int8_t exFileSysType[8]; /* fs type (FAT12 or FAT16) */ -}; - -struct bootsector50 { - u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ - int8_t bsOemName[8]; /* OEM name and version */ - int8_t bsBPB[25]; /* BIOS parameter block */ - int8_t bsExt[26]; /* Bootsector Extension */ - int8_t bsBootCode[448]; /* pad so structure is 512b */ - u_int8_t bsBootSectSig0; - u_int8_t bsBootSectSig1; -#define BOOTSIG0 0x55 -#define BOOTSIG1 0xaa -}; - -struct bootsector710 { - u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ - int8_t bsOEMName[8]; /* OEM name and version */ - int8_t bsPBP[53]; /* BIOS parameter block */ - int8_t bsExt[26]; /* Bootsector Extension */ - int8_t bsBootCode[418]; /* pad so structure is 512b */ - u_int8_t bsBootSectSig2; /* 2 & 3 are only defined for FAT32? */ - u_int8_t bsBootSectSig3; - u_int8_t bsBootSectSig0; - u_int8_t bsBootSectSig1; -#define BOOTSIG0 0x55 -#define BOOTSIG1 0xaa -#define BOOTSIG2 0 -#define BOOTSIG3 0 -}; -#ifdef atari -/* - * The boot sector on a gemdos fs is a little bit different from the msdos fs - * format. Currently there is no need to declare a separate structure, the - * bootsector33 struct will do. - */ -#if 0 -struct bootsec_atari { - u_int8_t bsBranch[2]; /* branch inst if auto-boot */ - int8_t bsFiller[6]; /* anything or nothing */ - int8_t bsSerial[3]; /* serial no. for mediachange */ - int8_t bsBPB[19]; /* BIOS parameter block */ - int8_t bsBootCode[482]; /* pad so struct is 512b */ -}; -#endif -#endif /* atari */ - -union bootsector { - struct bootsector33 bs33; - struct bootsector50 bs50; - struct bootsector710 bs710; -}; - -#if 0 -/* - * Shorthand for fields in the bpb. - */ -#define bsBytesPerSec bsBPB.bpbBytesPerSec -#define bsSectPerClust bsBPB.bpbSectPerClust -#define bsResSectors bsBPB.bpbResSectors -#define bsFATS bsBPB.bpbFATS -#define bsRootDirEnts bsBPB.bpbRootDirEnts -#define bsSectors bsBPB.bpbSectors -#define bsMedia bsBPB.bpbMedia -#define bsFATsecs bsBPB.bpbFATsecs -#define bsSectPerTrack bsBPB.bpbSectPerTrack -#define bsHeads bsBPB.bpbHeads -#define bsHiddenSecs bsBPB.bpbHiddenSecs -#define bsHugeSectors bsBPB.bpbHugeSectors -#endif diff --git a/sys/msdosfs/bpb.h b/sys/msdosfs/bpb.h deleted file mode 100644 index 42c941b..0000000 --- a/sys/msdosfs/bpb.h +++ /dev/null @@ -1,215 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: bpb.h,v 1.7 1997/11/17 15:36:24 ws Exp $ */ - -/* - * 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 - */ - -/* - * BIOS Parameter Block (BPB) for DOS 3.3 - */ -struct bpb33 { - u_int16_t bpbBytesPerSec; /* bytes per sector */ - u_int8_t bpbSecPerClust; /* sectors per cluster */ - u_int16_t bpbResSectors; /* number of reserved sectors */ - u_int8_t bpbFATs; /* number of FATs */ - u_int16_t bpbRootDirEnts; /* number of root directory entries */ - u_int16_t bpbSectors; /* total number of sectors */ - u_int8_t bpbMedia; /* media descriptor */ - u_int16_t bpbFATsecs; /* number of sectors per FAT */ - u_int16_t bpbSecPerTrack; /* sectors per track */ - u_int16_t bpbHeads; /* number of heads */ - u_int16_t bpbHiddenSecs; /* number of hidden sectors */ -}; - -/* - * BPB for DOS 5.0 The difference is bpbHiddenSecs is a short for DOS 3.3, - * and bpbHugeSectors is not in the 3.3 bpb. - */ -struct bpb50 { - u_int16_t bpbBytesPerSec; /* bytes per sector */ - u_int8_t bpbSecPerClust; /* sectors per cluster */ - u_int16_t bpbResSectors; /* number of reserved sectors */ - u_int8_t bpbFATs; /* number of FATs */ - u_int16_t bpbRootDirEnts; /* number of root directory entries */ - u_int16_t bpbSectors; /* total number of sectors */ - u_int8_t bpbMedia; /* media descriptor */ - u_int16_t bpbFATsecs; /* number of sectors per FAT */ - u_int16_t bpbSecPerTrack; /* sectors per track */ - u_int16_t bpbHeads; /* number of heads */ - u_int32_t bpbHiddenSecs; /* # of hidden sectors */ - u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ -}; - -/* - * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. - */ -struct bpb710 { - u_int16_t bpbBytesPerSec; /* bytes per sector */ - u_int8_t bpbSecPerClust; /* sectors per cluster */ - u_int16_t bpbResSectors; /* number of reserved sectors */ - u_int8_t bpbFATs; /* number of FATs */ - u_int16_t bpbRootDirEnts; /* number of root directory entries */ - u_int16_t bpbSectors; /* total number of sectors */ - u_int8_t bpbMedia; /* media descriptor */ - u_int16_t bpbFATsecs; /* number of sectors per FAT */ - u_int16_t bpbSecPerTrack; /* sectors per track */ - u_int16_t bpbHeads; /* number of heads */ - u_int32_t bpbHiddenSecs; /* # of hidden sectors */ - u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ - u_int32_t bpbBigFATsecs; /* like bpbFATsecs for FAT32 */ - u_int16_t bpbExtFlags; /* extended flags: */ -#define FATNUM 0xf /* mask for numbering active FAT */ -#define FATMIRROR 0x80 /* FAT is mirrored (like it always was) */ - u_int16_t bpbFSVers; /* filesystem version */ -#define FSVERS 0 /* currently only 0 is understood */ - u_int32_t bpbRootClust; /* start cluster for root directory */ - u_int16_t bpbFSInfo; /* filesystem info structure sector */ - u_int16_t bpbBackup; /* backup boot sector */ - /* There is a 12 byte filler here, but we ignore it */ -}; - -#ifdef atari -/* - * BPB for gemdos filesystems. Atari leaves the obsolete stuff undefined. - * Currently there is no need for a separate BPB structure. - */ -#if 0 -struct bpb_a { - u_int16_t bpbBytesPerSec; /* bytes per sector */ - u_int8_t bpbSecPerClust; /* sectors per cluster */ - u_int16_t bpbResSectors; /* number of reserved sectors */ - u_int8_t bpbFATs; /* number of FATs */ - u_int16_t bpbRootDirEnts; /* number of root directory entries */ - u_int16_t bpbSectors; /* total number of sectors */ - u_int8_t bpbUseless1; /* meaningless on gemdos fs */ - u_int16_t bpbFATsecs; /* number of sectors per FAT */ - u_int16_t bpbUseless2; /* meaningless for harddisk fs */ - u_int16_t bpbUseless3; /* meaningless for harddisk fs */ - u_int16_t bpbHiddenSecs; /* the TOS-BIOS ignores this */ -}; -#endif -#endif /* atari */ - -/* - * The following structures represent how the bpb's look on disk. shorts - * and longs are just character arrays of the appropriate length. This is - * because the compiler forces shorts and longs to align on word or - * halfword boundaries. - * - * XXX The little-endian code here assumes that the processor can access - * 16-bit and 32-bit quantities on byte boundaries. If this is not true, - * use the macros for the big-endian case. - */ - -#include <machine/endian.h> - -#ifdef __i386__ -#define UNLALIGNED_ACCESS -#endif - -#if (BYTE_ORDER == LITTLE_ENDIAN) && defined(UNALIGNED_ACCESS) -#define getushort(x) *((u_int16_t *)(x)) -#define getulong(x) *((u_int32_t *)(x)) -#define putushort(p, v) (*((u_int16_t *)(p)) = (v)) -#define putulong(p, v) (*((u_int32_t *)(p)) = (v)) -#else -#define getushort(x) (((u_int8_t *)(x))[0] + (((u_int8_t *)(x))[1] << 8)) -#define getulong(x) (((u_int8_t *)(x))[0] + (((u_int8_t *)(x))[1] << 8) \ - + (((u_int8_t *)(x))[2] << 16) \ - + (((u_int8_t *)(x))[3] << 24)) -#define putushort(p, v) (((u_int8_t *)(p))[0] = (v), \ - ((u_int8_t *)(p))[1] = (v) >> 8) -#define putulong(p, v) (((u_int8_t *)(p))[0] = (v), \ - ((u_int8_t *)(p))[1] = (v) >> 8, \ - ((u_int8_t *)(p))[2] = (v) >> 16,\ - ((u_int8_t *)(p))[3] = (v) >> 24) -#endif - -/* - * BIOS Parameter Block (BPB) for DOS 3.3 - */ -struct byte_bpb33 { - int8_t bpbBytesPerSec[2]; /* bytes per sector */ - int8_t bpbSecPerClust; /* sectors per cluster */ - int8_t bpbResSectors[2]; /* number of reserved sectors */ - int8_t bpbFATs; /* number of FATs */ - int8_t bpbRootDirEnts[2]; /* number of root directory entries */ - int8_t bpbSectors[2]; /* total number of sectors */ - int8_t bpbMedia; /* media descriptor */ - int8_t bpbFATsecs[2]; /* number of sectors per FAT */ - int8_t bpbSecPerTrack[2]; /* sectors per track */ - int8_t bpbHeads[2]; /* number of heads */ - int8_t bpbHiddenSecs[2]; /* number of hidden sectors */ -}; - -/* - * BPB for DOS 5.0 The difference is bpbHiddenSecs is a short for DOS 3.3, - * and bpbHugeSectors is not in the 3.3 bpb. - */ -struct byte_bpb50 { - int8_t bpbBytesPerSec[2]; /* bytes per sector */ - int8_t bpbSecPerClust; /* sectors per cluster */ - int8_t bpbResSectors[2]; /* number of reserved sectors */ - int8_t bpbFATs; /* number of FATs */ - int8_t bpbRootDirEnts[2]; /* number of root directory entries */ - int8_t bpbSectors[2]; /* total number of sectors */ - int8_t bpbMedia; /* media descriptor */ - int8_t bpbFATsecs[2]; /* number of sectors per FAT */ - int8_t bpbSecPerTrack[2]; /* sectors per track */ - int8_t bpbHeads[2]; /* number of heads */ - int8_t bpbHiddenSecs[4]; /* number of hidden sectors */ - int8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ -}; - -/* - * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. - */ -struct byte_bpb710 { - u_int8_t bpbBytesPerSec[2]; /* bytes per sector */ - u_int8_t bpbSecPerClust; /* sectors per cluster */ - u_int8_t bpbResSectors[2]; /* number of reserved sectors */ - u_int8_t bpbFATs; /* number of FATs */ - u_int8_t bpbRootDirEnts[2]; /* number of root directory entries */ - u_int8_t bpbSectors[2]; /* total number of sectors */ - u_int8_t bpbMedia; /* media descriptor */ - u_int8_t bpbFATsecs[2]; /* number of sectors per FAT */ - u_int8_t bpbSecPerTrack[2]; /* sectors per track */ - u_int8_t bpbHeads[2]; /* number of heads */ - u_int8_t bpbHiddenSecs[4]; /* # of hidden sectors */ - u_int8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ - u_int8_t bpbBigFATsecs[4]; /* like bpbFATsecs for FAT32 */ - u_int8_t bpbExtFlags[2]; /* extended flags: */ - u_int8_t bpbFSVers[2]; /* filesystem version */ - u_int8_t bpbRootClust[4]; /* start cluster for root directory */ - u_int8_t bpbFSInfo[2]; /* filesystem info structure sector */ - u_int8_t bpbBackup[2]; /* backup boot sector */ - /* There is a 12 byte filler here, but we ignore it */ -}; - -/* - * FAT32 FSInfo block. - */ -struct fsinfo { - u_int8_t fsisig1[4]; - u_int8_t fsifill1[480]; - u_int8_t fsisig2[4]; - u_int8_t fsinfree[4]; - u_int8_t fsinxtfree[4]; - u_int8_t fsifill2[12]; - u_int8_t fsisig3[4]; - u_int8_t fsifill3[508]; - u_int8_t fsisig4[4]; -}; diff --git a/sys/msdosfs/denode.h b/sys/msdosfs/denode.h deleted file mode 100644 index f7ba83b..0000000 --- a/sys/msdosfs/denode.h +++ /dev/null @@ -1,285 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: denode.h,v 1.25 1997/11/17 15:36:28 ws Exp $ */ - -/*- - * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. - * Copyright (C) 1994, 1995, 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 - */ - -/* - * This is the pc filesystem specific portion of the vnode structure. - * - * To describe a file uniquely the de_dirclust, de_diroffset, and - * de_StartCluster fields are used. - * - * de_dirclust contains the cluster number of the directory cluster - * containing the entry for a file or directory. - * de_diroffset is the index into the cluster for the entry describing - * a file or directory. - * de_StartCluster is the number of the first cluster of the file or directory. - * - * Now to describe the quirks of the pc filesystem. - * - Clusters 0 and 1 are reserved. - * - The first allocatable cluster is 2. - * - The root directory is of fixed size and all blocks that make it up - * are contiguous. - * - Cluster 0 refers to the root directory when it is found in the - * startcluster field of a directory entry that points to another directory. - * - Cluster 0 implies a 0 length file when found in the start cluster field - * of a directory entry that points to a file. - * - You can't use the cluster number 0 to derive the address of the root - * directory. - * - Multiple directory entries can point to a directory. The entry in the - * parent directory points to a child directory. Any directories in the - * child directory contain a ".." entry that points back to the parent. - * The child directory itself contains a "." entry that points to itself. - * - The root directory does not contain a "." or ".." entry. - * - Directory entries for directories are never changed once they are created - * (except when removed). The size stays 0, and the last modification time - * is never changed. This is because so many directory entries can point to - * the physical clusters that make up a directory. It would lead to an - * update nightmare. - * - The length field in a directory entry pointing to a directory contains 0 - * (always). The only way to find the end of a directory is to follow the - * cluster chain until the "last cluster" marker is found. - * - * My extensions to make this house of cards work. These apply only to the in - * memory copy of the directory entry. - * - A reference count for each denode will be kept since dos doesn't keep such - * things. - */ - -/* - * Internal pseudo-offset for (nonexistent) directory entry for the root - * dir in the root dir - */ -#define MSDOSFSROOT_OFS 0x1fffffff - -/* - * The fat cache structure. fc_fsrcn is the filesystem relative cluster - * number that corresponds to the file relative cluster number in this - * structure (fc_frcn). - */ -struct fatcache { - u_long fc_frcn; /* file relative cluster number */ - u_long fc_fsrcn; /* filesystem relative cluster number */ -}; - -/* - * The fat entry cache as it stands helps make extending files a "quick" - * operation by avoiding having to scan the fat to discover the last - * cluster of the file. The cache also helps sequential reads by - * remembering the last cluster read from the file. This also prevents us - * from having to rescan the fat to find the next cluster to read. This - * cache is probably pretty worthless if a file is opened by multiple - * processes. - */ -#define FC_SIZE 2 /* number of entries in the cache */ -#define FC_LASTMAP 0 /* entry the last call to pcbmap() resolved - * to */ -#define FC_LASTFC 1 /* entry for the last cluster in the file */ - -#define FCE_EMPTY 0xffffffff /* doesn't represent an actual cluster # */ - -/* - * Set a slot in the fat cache. - */ -#define fc_setcache(dep, slot, frcn, fsrcn) \ - (dep)->de_fc[slot].fc_frcn = frcn; \ - (dep)->de_fc[slot].fc_fsrcn = fsrcn; - -/* - * This is the in memory variant of a dos directory entry. It is usually - * contained within a vnode. - */ -struct denode { - struct denode *de_next; /* Hash chain forward */ - struct denode **de_prev; /* Hash chain back */ - struct vnode *de_vnode; /* addr of vnode we are part of */ - struct vnode *de_devvp; /* vnode of blk dev we live on */ - u_long de_flag; /* flag bits */ - dev_t de_dev; /* device where direntry lives */ - u_long de_dirclust; /* cluster of the directory file containing this entry */ - u_long de_diroffset; /* offset of this entry in the directory cluster */ - u_long de_fndoffset; /* offset of found dir entry */ - int de_fndcnt; /* number of slots before de_fndoffset */ - long de_refcnt; /* reference count */ - struct msdosfsmount *de_pmp; /* addr of our mount struct */ - u_char de_Name[12]; /* name, from DOS directory entry */ - u_char de_Attributes; /* attributes, from directory entry */ - u_char de_LowerCase; /* NT VFAT lower case flags */ - u_char de_CHun; /* Hundredth of second of CTime*/ - u_short de_CTime; /* creation time */ - u_short de_CDate; /* creation date */ - u_short de_ADate; /* access date */ - u_short de_MTime; /* modification time */ - u_short de_MDate; /* modification date */ - u_long de_StartCluster; /* starting cluster of file */ - u_long de_FileSize; /* size of file in bytes */ - struct fatcache de_fc[FC_SIZE]; /* fat cache */ - u_quad_t de_modrev; /* Revision level for lease. */ -}; - -/* - * Values for the de_flag field of the denode. - */ -#define DE_UPDATE 0x0004 /* Modification time update request */ -#define DE_CREATE 0x0008 /* Creation time update */ -#define DE_ACCESS 0x0010 /* Access time update */ -#define DE_MODIFIED 0x0020 /* Denode has been modified */ -#define DE_RENAME 0x0040 /* Denode is in the process of being renamed */ - - -/* - * Transfer directory entries between internal and external form. - * dep is a struct denode * (internal form), - * dp is a struct direntry * (external form). - */ -#define DE_INTERNALIZE32(dep, dp) \ - ((dep)->de_StartCluster |= getushort((dp)->deHighClust) << 16) -#define DE_INTERNALIZE(dep, dp) \ - (bcopy((dp)->deName, (dep)->de_Name, 11), \ - (dep)->de_Attributes = (dp)->deAttributes, \ - (dep)->de_LowerCase = (dp)->deLowerCase, \ - (dep)->de_CHun = (dp)->deCHundredth, \ - (dep)->de_CTime = getushort((dp)->deCTime), \ - (dep)->de_CDate = getushort((dp)->deCDate), \ - (dep)->de_ADate = getushort((dp)->deADate), \ - (dep)->de_MTime = getushort((dp)->deMTime), \ - (dep)->de_MDate = getushort((dp)->deMDate), \ - (dep)->de_StartCluster = getushort((dp)->deStartCluster), \ - (dep)->de_FileSize = getulong((dp)->deFileSize), \ - (FAT32((dep)->de_pmp) ? DE_INTERNALIZE32((dep), (dp)) : 0)) - -#define DE_EXTERNALIZE(dp, dep) \ - (bcopy((dep)->de_Name, (dp)->deName, 11), \ - (dp)->deAttributes = (dep)->de_Attributes, \ - (dp)->deLowerCase = (dep)->de_LowerCase, \ - (dp)->deCHundredth = (dep)->de_CHun, \ - putushort((dp)->deCTime, (dep)->de_CTime), \ - putushort((dp)->deCDate, (dep)->de_CDate), \ - putushort((dp)->deADate, (dep)->de_ADate), \ - putushort((dp)->deMTime, (dep)->de_MTime), \ - putushort((dp)->deMDate, (dep)->de_MDate), \ - putushort((dp)->deStartCluster, (dep)->de_StartCluster), \ - putulong((dp)->deFileSize, \ - ((dep)->de_Attributes & ATTR_DIRECTORY) ? 0 : (dep)->de_FileSize), \ - putushort((dp)->deHighClust, (dep)->de_StartCluster >> 16)) - -#define de_forw de_chain[0] -#define de_back de_chain[1] - -#ifdef _KERNEL - -#define VTODE(vp) ((struct denode *)(vp)->v_data) -#define DETOV(de) ((de)->de_vnode) - -#define DETIMES(dep, acc, mod, cre) do { \ - if ((dep)->de_flag & DE_UPDATE) { \ - (dep)->de_flag |= DE_MODIFIED; \ - unix2dostime((mod), &(dep)->de_MDate, &(dep)->de_MTime, \ - NULL); \ - (dep)->de_Attributes |= ATTR_ARCHIVE; \ - } \ - if ((dep)->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95) { \ - (dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS); \ - break; \ - } \ - if ((dep)->de_flag & DE_ACCESS) { \ - u_int16_t adate; \ - \ - unix2dostime((acc), &adate, NULL, NULL); \ - if (adate != (dep)->de_ADate) { \ - (dep)->de_flag |= DE_MODIFIED; \ - (dep)->de_ADate = adate; \ - } \ - } \ - if ((dep)->de_flag & DE_CREATE) { \ - unix2dostime((cre), &(dep)->de_CDate, &(dep)->de_CTime, \ - &(dep)->de_CHun); \ - (dep)->de_flag |= DE_MODIFIED; \ - } \ - (dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS); \ -} while (0); - -/* - * This overlays the fid structure (see mount.h) - */ -struct defid { - u_short defid_len; /* length of structure */ - u_short defid_pad; /* force long alignment */ - - u_long defid_dirclust; /* cluster this dir entry came from */ - u_long defid_dirofs; /* offset of entry within the cluster */ -#if 0 - u_long defid_gen; /* generation number */ -#endif -}; - -extern vop_t **msdosfs_vnodeop_p; - -int msdosfs_lookup __P((struct vop_cachedlookup_args *)); -int msdosfs_inactive __P((struct vop_inactive_args *)); -int msdosfs_reclaim __P((struct vop_reclaim_args *)); - -/* - * Internal service routine prototypes. - */ -int deget __P((struct msdosfsmount *, u_long, u_long, struct denode **)); -int uniqdosname __P((struct denode *, struct componentname *, u_char *)); -int findwin95 __P((struct denode *)); - -int readep __P((struct msdosfsmount *pmp, u_long dirclu, u_long dirofs, struct buf **bpp, struct direntry **epp)); -int readde __P((struct denode *dep, struct buf **bpp, struct direntry **epp)); -int deextend __P((struct denode *dep, u_long length, struct ucred *cred)); -int fillinusemap __P((struct msdosfsmount *pmp)); -void reinsert __P((struct denode *dep)); -int dosdirempty __P((struct denode *dep)); -int createde __P((struct denode *dep, struct denode *ddep, struct denode **depp, struct componentname *cnp)); -int deupdat __P((struct denode *dep, int waitfor)); -int removede __P((struct denode *pdep, struct denode *dep)); -int detrunc __P((struct denode *dep, u_long length, int flags, struct ucred *cred, struct proc *p)); -int doscheckpath __P(( struct denode *source, struct denode *target)); -#endif /* _KERNEL */ diff --git a/sys/msdosfs/direntry.h b/sys/msdosfs/direntry.h deleted file mode 100644 index fccf58b..0000000 --- a/sys/msdosfs/direntry.h +++ /dev/null @@ -1,143 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: direntry.h,v 1.14 1997/11/17 15:36:32 ws Exp $ */ - -/*- - * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. - * Copyright (C) 1994, 1995, 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 - */ - -/* - * Structure of a dos directory entry. - */ -struct direntry { - u_int8_t deName[8]; /* filename, blank filled */ -#define SLOT_EMPTY 0x00 /* slot has never been used */ -#define SLOT_E5 0x05 /* the real value is 0xe5 */ -#define SLOT_DELETED 0xe5 /* file in this slot deleted */ - u_int8_t deExtension[3]; /* extension, blank filled */ - u_int8_t deAttributes; /* file attributes */ -#define ATTR_NORMAL 0x00 /* normal file */ -#define ATTR_READONLY 0x01 /* file is readonly */ -#define ATTR_HIDDEN 0x02 /* file is hidden */ -#define ATTR_SYSTEM 0x04 /* file is a system file */ -#define ATTR_VOLUME 0x08 /* entry is a volume label */ -#define ATTR_DIRECTORY 0x10 /* entry is a directory name */ -#define ATTR_ARCHIVE 0x20 /* file is new or modified */ - u_int8_t deLowerCase; /* NT VFAT lower case flags */ -#define LCASE_BASE 0x08 /* filename base in lower case */ -#define LCASE_EXT 0x10 /* filename extension in lower case */ - u_int8_t deCHundredth; /* hundredth of seconds in CTime */ - u_int8_t deCTime[2]; /* create time */ - u_int8_t deCDate[2]; /* create date */ - u_int8_t deADate[2]; /* access date */ - u_int8_t deHighClust[2]; /* high bytes of cluster number */ - u_int8_t deMTime[2]; /* last update time */ - u_int8_t deMDate[2]; /* last update date */ - u_int8_t deStartCluster[2]; /* starting cluster of file */ - u_int8_t deFileSize[4]; /* size of file in bytes */ -}; - -/* - * Structure of a Win95 long name directory entry - */ -struct winentry { - u_int8_t weCnt; -#define WIN_LAST 0x40 -#define WIN_CNT 0x3f - u_int8_t wePart1[10]; - u_int8_t weAttributes; -#define ATTR_WIN95 0x0f - u_int8_t weReserved1; - u_int8_t weChksum; - u_int8_t wePart2[12]; - u_int16_t weReserved2; - u_int8_t wePart3[4]; -}; -#define WIN_CHARS 13 /* Number of chars per winentry */ - -/* - * Maximum filename length in Win95 - * Note: Must be < sizeof(dirent.d_name) - */ -#define WIN_MAXLEN 255 - -/* - * This is the format of the contents of the deTime field in the direntry - * structure. - * We don't use bitfields because we don't know how compilers for - * arbitrary machines will lay them out. - */ -#define DT_2SECONDS_MASK 0x1F /* seconds divided by 2 */ -#define DT_2SECONDS_SHIFT 0 -#define DT_MINUTES_MASK 0x7E0 /* minutes */ -#define DT_MINUTES_SHIFT 5 -#define DT_HOURS_MASK 0xF800 /* hours */ -#define DT_HOURS_SHIFT 11 - -/* - * This is the format of the contents of the deDate field in the direntry - * structure. - */ -#define DD_DAY_MASK 0x1F /* day of month */ -#define DD_DAY_SHIFT 0 -#define DD_MONTH_MASK 0x1E0 /* month */ -#define DD_MONTH_SHIFT 5 -#define DD_YEAR_MASK 0xFE00 /* year - 1980 */ -#define DD_YEAR_SHIFT 9 - -#ifdef _KERNEL -struct dirent; -void unix2dostime __P((struct timespec *tsp, u_int16_t *ddp, - u_int16_t *dtp, u_int8_t *dhp)); -void dos2unixtime __P((u_int dd, u_int dt, u_int dh, struct timespec *tsp)); -int dos2unixfn __P((u_char dn[11], u_char *un, int lower, int d2u_loaded, u_int8_t *d2u, int ul_loaded, u_int8_t *ul)); -int unix2dosfn __P((const u_char *un, u_char dn[12], int unlen, u_int gen, int u2d_loaded, u_int8_t *u2d, int lu_loaded, u_int8_t *lu)); -int unix2winfn __P((const u_char *un, int unlen, struct winentry *wep, int cnt, int chksum, int table_loaded, u_int16_t *u2w)); -int winChkName __P((const u_char *un, int unlen, struct winentry *wep, int chksum, int u2w_loaded, u_int16_t *u2w, int ul_loaded, u_int8_t *ul)); -int win2unixfn __P((struct winentry *wep, struct dirent *dp, int chksum, int table_loaded, u_int16_t *u2w)); -u_int8_t winChksum __P((u_int8_t *name)); -int winSlotCnt __P((const u_char *un, int unlen)); -int winLenFixup __P((const u_char *un, int unlen)); -#endif /* _KERNEL */ diff --git a/sys/msdosfs/fat.h b/sys/msdosfs/fat.h deleted file mode 100644 index 7dd5bbf..0000000 --- a/sys/msdosfs/fat.h +++ /dev/null @@ -1,108 +0,0 @@ -/* $FreeBSD$ */ -/* $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 */ - -#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) - -#ifdef _KERNEL -/* - * These are the values for the function argument to the function - * 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 extendfile: - */ -#define DE_CLEAR 1 /* Zero out the blocks allocated */ - -int pcbmap __P((struct denode *dep, u_long findcn, daddr_t *bnp, u_long *cnp, int* sp)); -int clusterfree __P((struct msdosfsmount *pmp, u_long cn, u_long *oldcnp)); -int clusteralloc __P((struct msdosfsmount *pmp, u_long start, u_long count, u_long fillwith, u_long *retcluster, u_long *got)); -int fatentry __P((int function, struct msdosfsmount *pmp, u_long cluster, u_long *oldcontents, u_long newcontents)); -int freeclusterchain __P((struct msdosfsmount *pmp, u_long startchain)); -int extendfile __P((struct denode *dep, u_long count, struct buf **bpp, u_long *ncp, int flags)); -void fc_purge __P((struct denode *dep, u_int frcn)); - -#endif /* _KERNEL */ diff --git a/sys/msdosfs/msdosfs_conv.c b/sys/msdosfs/msdosfs_conv.c deleted file mode 100644 index 8c43f93..0000000 --- a/sys/msdosfs/msdosfs_conv.c +++ /dev/null @@ -1,1041 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: msdosfs_conv.c,v 1.25 1997/11/17 15:36:40 ws Exp $ */ - -/*- - * Copyright (C) 1995, 1997 Wolfgang Solfrank. - * Copyright (C) 1995, 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 - */ - -/* - * System include files. - */ -#include <sys/param.h> -#include <sys/time.h> -#include <sys/kernel.h> /* defines tz */ -#include <sys/systm.h> -#include <machine/clock.h> -#include <sys/dirent.h> - -/* - * MSDOSFS include files. - */ -#include <msdosfs/direntry.h> - -/* - * Total number of days that have passed for each month in a regular year. - */ -static u_short regyear[] = { - 31, 59, 90, 120, 151, 181, - 212, 243, 273, 304, 334, 365 -}; - -/* - * Total number of days that have passed for each month in a leap year. - */ -static u_short leapyear[] = { - 31, 60, 91, 121, 152, 182, - 213, 244, 274, 305, 335, 366 -}; - -/* - * Variables used to remember parts of the last time conversion. Maybe we - * can avoid a full conversion. - */ -static u_long lasttime; -static u_long lastday; -static u_short lastddate; -static u_short lastdtime; - -static __inline u_int8_t find_lcode __P((u_int16_t code, u_int16_t *u2w)); - -/* - * Convert the unix version of time to dos's idea of time to be used in - * file timestamps. The passed in unix time is assumed to be in GMT. - */ -void -unix2dostime(tsp, ddp, dtp, dhp) - struct timespec *tsp; - u_int16_t *ddp; - u_int16_t *dtp; - u_int8_t *dhp; -{ - u_long t; - u_long days; - u_long inc; - u_long year; - u_long month; - u_short *months; - - /* - * If the time from the last conversion is the same as now, then - * skip the computations and use the saved result. - */ - t = tsp->tv_sec - (tz.tz_minuteswest * 60) - - (wall_cmos_clock ? adjkerntz : 0); - /* - daylight savings time correction */ - t &= ~1; - if (lasttime != t) { - lasttime = t; - lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT) - + (((t / 60) % 60) << DT_MINUTES_SHIFT) - + (((t / 3600) % 24) << DT_HOURS_SHIFT); - - /* - * If the number of days since 1970 is the same as the last - * time we did the computation then skip all this leap year - * and month stuff. - */ - days = t / (24 * 60 * 60); - if (days != lastday) { - lastday = days; - for (year = 1970;; year++) { - inc = year & 0x03 ? 365 : 366; - if (days < inc) - break; - days -= inc; - } - months = year & 0x03 ? regyear : leapyear; - for (month = 0; days >= months[month]; month++) - ; - if (month > 0) - days -= months[month - 1]; - lastddate = ((days + 1) << DD_DAY_SHIFT) - + ((month + 1) << DD_MONTH_SHIFT); - /* - * Remember dos's idea of time is relative to 1980. - * unix's is relative to 1970. If somehow we get a - * time before 1980 then don't give totally crazy - * results. - */ - if (year > 1980) - lastddate += (year - 1980) << DD_YEAR_SHIFT; - } - } - if (dtp) - *dtp = lastdtime; - if (dhp) - *dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000; - - *ddp = lastddate; -} - -/* - * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that - * interval there were 8 regular years and 2 leap years. - */ -#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60)) - -static u_short lastdosdate; -static u_long lastseconds; - -/* - * Convert from dos' idea of time to unix'. This will probably only be - * called from the stat(), and fstat() system calls and so probably need - * not be too efficient. - */ -void -dos2unixtime(dd, dt, dh, tsp) - u_int dd; - u_int dt; - u_int dh; - struct timespec *tsp; -{ - u_long seconds; - u_long month; - u_long year; - u_long days; - u_short *months; - - if (dd == 0) { - /* - * Uninitialized field, return the epoch. - */ - tsp->tv_sec = 0; - tsp->tv_nsec = 0; - return; - } - seconds = (((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) << 1) - + ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60 - + ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600 - + dh / 100; - /* - * If the year, month, and day from the last conversion are the - * same then use the saved value. - */ - if (lastdosdate != dd) { - lastdosdate = dd; - days = 0; - year = (dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT; - days = year * 365; - days += year / 4 + 1; /* add in leap days */ - if ((year & 0x03) == 0) - days--; /* if year is a leap year */ - months = year & 0x03 ? regyear : leapyear; - month = (dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT; - if (month < 1 || month > 12) { - printf("dos2unixtime(): month value out of range (%ld)\n", - month); - month = 1; - } - if (month > 1) - days += months[month - 2]; - days += ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT) - 1; - lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980; - } - tsp->tv_sec = seconds + lastseconds + (tz.tz_minuteswest * 60) - + adjkerntz; - /* + daylight savings time correction */ - tsp->tv_nsec = (dh % 100) * 10000000; -} - -/* - * 0 - character disallowed in long file name. - * 1 - character should be replaced by '_' in DOS file name, - * and generation number inserted. - * 2 - character ('.' and ' ') should be skipped in DOS file name, - * and generation number inserted. - */ -static u_char -unix2dos[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, /* 00-07 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 08-0f */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 10-17 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 18-1f */ - 2, 0x21, 0, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20-27 */ - 0x28, 0x29, 0, 1, 1, 0x2d, 2, 0, /* 28-2f */ - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30-37 */ - 0x38, 0x39, 0, 1, 0, 1, 0, 0, /* 38-3f */ - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 40-47 */ - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 48-4f */ - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 50-57 */ - 0x58, 0x59, 0x5a, 1, 0, 1, 0x5e, 0x5f, /* 58-5f */ - 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 60-67 */ - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 68-6f */ - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 70-77 */ - 0x58, 0x59, 0x5a, 0x7b, 0, 0x7d, 0x7e, 0, /* 78-7f */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 80-87 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 88-8f */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 90-97 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 98-9f */ - 0, 0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5, /* a0-a7 */ - 0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee, /* a8-af */ - 0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa, /* b0-b7 */ - 0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8, /* b8-bf */ - 0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* c0-c7 */ - 0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* c8-cf */ - 0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e, /* d0-d7 */ - 0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1, /* d8-df */ - 0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* e0-e7 */ - 0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* e8-ef */ - 0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0xf6, /* f0-f7 */ - 0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0x98, /* f8-ff */ -}; - -static u_char -dos2unix[256] = { - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* 00-07 */ - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* 08-0f */ - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* 10-17 */ - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* 18-1f */ - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20-27 */ - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 28-2f */ - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30-37 */ - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 38-3f */ - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 40-47 */ - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 48-4f */ - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 50-57 */ - 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 58-5f */ - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 60-67 */ - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 68-6f */ - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 70-77 */ - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 78-7f */ - 0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7, /* 80-87 */ - 0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5, /* 88-8f */ - 0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9, /* 90-97 */ - 0xff, 0xd6, 0xdc, 0xf8, 0xa3, 0xd8, 0xd7, 0x3f, /* 98-9f */ - 0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba, /* a0-a7 */ - 0xbf, 0xae, 0xac, 0xbd, 0xbc, 0xa1, 0xab, 0xbb, /* a8-af */ - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xc1, 0xc2, 0xc0, /* b0-b7 */ - 0xa9, 0x3f, 0x3f, 0x3f, 0x3f, 0xa2, 0xa5, 0x3f, /* b8-bf */ - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xe3, 0xc3, /* c0-c7 */ - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xa4, /* c8-cf */ - 0xf0, 0xd0, 0xca, 0xcb, 0xc8, 0x3f, 0xcd, 0xce, /* d0-d7 */ - 0xcf, 0x3f, 0x3f, 0x3f, 0x3f, 0xa6, 0xcc, 0x3f, /* d8-df */ - 0xd3, 0xdf, 0xd4, 0xd2, 0xf5, 0xd5, 0xb5, 0xfe, /* e0-e7 */ - 0xde, 0xda, 0xdb, 0xd9, 0xfd, 0xdd, 0xaf, 0x3f, /* e8-ef */ - 0xad, 0xb1, 0x3f, 0xbe, 0xb6, 0xa7, 0xf7, 0xb8, /* f0-f7 */ - 0xb0, 0xa8, 0xb7, 0xb9, 0xb3, 0xb2, 0x3f, 0x3f, /* f8-ff */ -}; - -static u_char -u2l[256] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 00-07 */ - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 08-0f */ - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */ - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 18-1f */ - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20-27 */ - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 28-2f */ - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30-37 */ - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 38-3f */ - 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 40-47 */ - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 48-4f */ - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 50-57 */ - 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 58-5f */ - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 60-67 */ - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 68-6f */ - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 70-77 */ - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 78-7f */ - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 80-87 */ - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 88-8f */ - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 90-97 */ - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 98-9f */ - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* a0-a7 */ - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* a8-af */ - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* b0-b7 */ - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* b8-bf */ - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* c0-c7 */ - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* c8-cf */ - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* d0-d7 */ - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* d8-df */ - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* e0-e7 */ - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* e8-ef */ - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* f0-f7 */ - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* f8-ff */ -}; - -static u_char -l2u[256] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 00-07 */ - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 08-0f */ - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */ - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 18-1f */ - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20-27 */ - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 28-2f */ - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30-37 */ - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 38-3f */ - 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 40-47 */ - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 48-4f */ - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 50-57 */ - 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 58-5f */ - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 60-67 */ - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 68-6f */ - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 70-77 */ - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 78-7f */ - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 80-87 */ - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 88-8f */ - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 90-97 */ - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 98-9f */ - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* a0-a7 */ - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* a8-af */ - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* b0-b7 */ - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* b8-bf */ - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* c0-c7 */ - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* c8-cf */ - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* d0-d7 */ - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* d8-df */ - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* e0-e7 */ - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* e8-ef */ - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* f0-f7 */ - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* f8-ff */ -}; - -/* - * DOS filenames are made of 2 parts, the name part and the extension part. - * The name part is 8 characters long and the extension part is 3 - * characters long. They may contain trailing blanks if the name or - * extension are not long enough to fill their respective fields. - */ - -/* - * Convert a DOS filename to a unix filename. And, return the number of - * characters in the resulting unix filename excluding the terminating - * null. - */ -int -dos2unixfn(dn, un, lower, d2u_loaded, d2u, ul_loaded, ul) - u_char dn[11]; - u_char *un; - int lower; - int d2u_loaded; - u_int8_t *d2u; - int ul_loaded; - u_int8_t *ul; -{ - int i; - int thislong = 1; - u_char c; - - /* - * If first char of the filename is SLOT_E5 (0x05), then the real - * first char of the filename should be 0xe5. But, they couldn't - * just have a 0xe5 mean 0xe5 because that is used to mean a freed - * directory slot. Another dos quirk. - */ - if (*dn == SLOT_E5) - c = d2u_loaded ? d2u[0xe5 & 0x7f] : dos2unix[0xe5]; - else - c = d2u_loaded && (*dn & 0x80) ? d2u[*dn & 0x7f] : - dos2unix[*dn]; - *un++ = (lower & LCASE_BASE) ? (ul_loaded && (c & 0x80) ? - ul[c & 0x7f] : u2l[c]) : c; - dn++; - - /* - * Copy the name portion into the unix filename string. - */ - for (i = 1; i < 8 && *dn != ' '; i++) { - c = d2u_loaded && (*dn & 0x80) ? d2u[*dn & 0x7f] : - dos2unix[*dn]; - dn++; - *un++ = (lower & LCASE_BASE) ? (ul_loaded && (c & 0x80) ? - ul[c & 0x7f] : u2l[c]) : c; - thislong++; - } - dn += 8 - i; - - /* - * Now, if there is an extension then put in a period and copy in - * the extension. - */ - if (*dn != ' ') { - *un++ = '.'; - thislong++; - for (i = 0; i < 3 && *dn != ' '; i++) { - c = d2u_loaded && (*dn & 0x80) ? d2u[*dn & 0x7f] : - dos2unix[*dn]; - dn++; - *un++ = (lower & LCASE_EXT) ? (ul_loaded && (c & 0x80) ? - ul[c & 0x7f] : u2l[c]) : c; - thislong++; - } - } - *un++ = 0; - - return (thislong); -} - -/* - * Convert a unix filename to a DOS filename according to Win95 rules. - * If applicable and gen is not 0, it is inserted into the converted - * filename as a generation number. - * Returns - * 0 if name couldn't be converted - * 1 if the converted name is the same as the original - * (no long filename entry necessary for Win95) - * 2 if conversion was successful - * 3 if conversion was successful and generation number was inserted - */ -int -unix2dosfn(un, dn, unlen, gen, u2d_loaded, u2d, lu_loaded, lu) - const u_char *un; - u_char dn[12]; - int unlen; - u_int gen; - int u2d_loaded; - u_int8_t *u2d; - int lu_loaded; - u_int8_t *lu; -{ - int i, j, l; - int conv = 1; - const u_char *cp, *dp, *dp1; - u_char gentext[6], *wcp; - u_int8_t c; -#define U2D(c) (u2d_loaded && ((c) & 0x80) ? u2d[(c) & 0x7f] : unix2dos[c]) - - /* - * Fill the dos filename string with blanks. These are DOS's pad - * characters. - */ - for (i = 0; i < 11; i++) - dn[i] = ' '; - dn[11] = 0; - - /* - * The filenames "." and ".." are handled specially, since they - * don't follow dos filename rules. - */ - if (un[0] == '.' && unlen == 1) { - dn[0] = '.'; - return gen <= 1; - } - if (un[0] == '.' && un[1] == '.' && unlen == 2) { - dn[0] = '.'; - dn[1] = '.'; - return gen <= 1; - } - - /* - * Filenames with only blanks and dots are not allowed! - */ - for (cp = un, i = unlen; --i >= 0; cp++) - if (*cp != ' ' && *cp != '.') - break; - if (i < 0) - return 0; - - - /* - * Filenames with some characters are not allowed! - */ - for (cp = un, i = unlen; --i >= 0; cp++) - if (U2D(*cp) == 0) - return 0; - - /* - * Now find the extension - * Note: dot as first char doesn't start extension - * and trailing dots and blanks are ignored - */ - dp = dp1 = 0; - for (cp = un + 1, i = unlen - 1; --i >= 0;) { - switch (*cp++) { - case '.': - if (!dp1) - dp1 = cp; - break; - case ' ': - break; - default: - if (dp1) - dp = dp1; - dp1 = 0; - break; - } - } - - /* - * Now convert it - */ - if (dp) { - if (dp1) - l = dp1 - dp; - else - l = unlen - (dp - un); - for (i = 0, j = 8; i < l && j < 11; i++, j++) { - c = dp[i]; - c = lu_loaded && (c & 0x80) ? - lu[c & 0x7f] : l2u[c]; - c = U2D(c); - if (dp[i] != (dn[j] = c) - && conv != 3) - conv = 2; - if (dn[j] == 1) { - conv = 3; - dn[j] = '_'; - } - if (dn[j] == 2) { - conv = 3; - dn[j--] = ' '; - } - } - if (i < l) - conv = 3; - dp--; - } else { - for (dp = cp; *--dp == ' ' || *dp == '.';); - dp++; - } - - /* - * Now convert the rest of the name - */ - for (i = j = 0; un < dp && j < 8; i++, j++, un++) { - c = lu_loaded && (*un & 0x80) ? - lu[*un & 0x7f] : l2u[*un]; - c = U2D(c); - if (*un != (dn[j] = c) - && conv != 3) - conv = 2; - if (dn[j] == 1) { - conv = 3; - dn[j] = '_'; - } - if (dn[j] == 2) { - conv = 3; - dn[j--] = ' '; - } - } - if (un < dp) - conv = 3; - /* - * If we didn't have any chars in filename, - * generate a default - */ - if (!j) - dn[0] = '_'; - - /* - * The first character cannot be E5, - * because that means a deleted entry - */ - if (dn[0] == 0xe5) - dn[0] = SLOT_E5; - - /* - * If there wasn't any char dropped, - * there is no place for generation numbers - */ - if (conv != 3) { - if (gen > 1) - return 0; - return conv; - } - - /* - * Now insert the generation number into the filename part - */ - if (gen == 0) - return conv; - for (wcp = gentext + sizeof(gentext); wcp > gentext && gen; gen /= 10) - *--wcp = gen % 10 + '0'; - if (gen) - return 0; - for (i = 8; dn[--i] == ' ';); - i++; - if (gentext + sizeof(gentext) - wcp + 1 > 8 - i) - i = 8 - (gentext + sizeof(gentext) - wcp + 1); - dn[i++] = '~'; - while (wcp < gentext + sizeof(gentext)) - dn[i++] = *wcp++; - return 3; -#undef U2D -} - -/* - * Create a Win95 long name directory entry - * Note: assumes that the filename is valid, - * i.e. doesn't consist solely of blanks and dots - */ -int -unix2winfn(un, unlen, wep, cnt, chksum, table_loaded, u2w) - const u_char *un; - int unlen; - struct winentry *wep; - int cnt; - int chksum; - int table_loaded; - u_int16_t *u2w; -{ - const u_int8_t *cp; - u_int8_t *wcp; - int i; - u_int16_t code; - - /* - * Drop trailing blanks and dots - */ - for (cp = un + unlen; *--cp == ' ' || *cp == '.'; unlen--); - - un += (cnt - 1) * WIN_CHARS; - unlen -= (cnt - 1) * WIN_CHARS; - - /* - * Initialize winentry to some useful default - */ - for (wcp = (u_int8_t *)wep, i = sizeof(*wep); --i >= 0; *wcp++ = 0xff); - wep->weCnt = cnt; - wep->weAttributes = ATTR_WIN95; - wep->weReserved1 = 0; - wep->weChksum = chksum; - wep->weReserved2 = 0; - - /* - * Now convert the filename parts - */ - for (wcp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { - if (--unlen < 0) - goto done; - if (table_loaded && (*un & 0x80)) { - code = u2w[*un++ & 0x7f]; - *wcp++ = code; - *wcp++ = code >> 8; - } else { - *wcp++ = *un++; - *wcp++ = 0; - } - } - for (wcp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { - if (--unlen < 0) - goto done; - if (table_loaded && (*un & 0x80)) { - code = u2w[*un++ & 0x7f]; - *wcp++ = code; - *wcp++ = code >> 8; - } else { - *wcp++ = *un++; - *wcp++ = 0; - } - } - for (wcp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) { - if (--unlen < 0) - goto done; - if (table_loaded && (*un & 0x80)) { - code = u2w[*un++ & 0x7f]; - *wcp++ = code; - *wcp++ = code >> 8; - } else { - *wcp++ = *un++; - *wcp++ = 0; - } - } - if (!unlen) - wep->weCnt |= WIN_LAST; - return unlen; - -done: - *wcp++ = 0; - *wcp++ = 0; - wep->weCnt |= WIN_LAST; - return 0; -} - -static __inline u_int8_t -find_lcode(code, u2w) - u_int16_t code; - u_int16_t *u2w; -{ - int i; - - for (i = 0; i < 128; i++) - if (u2w[i] == code) - return (i | 0x80); - return '?'; -} - -/* - * Compare our filename to the one in the Win95 entry - * Returns the checksum or -1 if no match - */ -int -winChkName(un, unlen, wep, chksum, u2w_loaded, u2w, ul_loaded, ul) - const u_char *un; - int unlen; - struct winentry *wep; - int chksum; - int u2w_loaded; - u_int16_t *u2w; - int ul_loaded; - u_int8_t *ul; -{ - u_int8_t *cp; - int i; - u_int16_t code; - u_int8_t c1, c2; - - /* - * First compare checksums - */ - if (wep->weCnt&WIN_LAST) - chksum = wep->weChksum; - else if (chksum != wep->weChksum) - chksum = -1; - if (chksum == -1) - return -1; - - /* - * Offset of this entry - */ - i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS; - un += i; - if ((unlen -= i) <= 0) - return -1; - if ((wep->weCnt&WIN_LAST) && unlen > WIN_CHARS) - return -1; - - /* - * Compare the name parts - */ - for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { - if (--unlen < 0) { - if (!*cp++ && !*cp) - return chksum; - return -1; - } - code = (cp[1] << 8) | cp[0]; - if (code & 0xff80) { - if (u2w_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } - c1 = ul_loaded && (code & 0x80) ? - ul[code & 0x7f] : u2l[code]; - c2 = ul_loaded && (*un & 0x80) ? - ul[*un & 0x7f] : u2l[*un]; - if (c1 != c2) - return -1; - cp += 2; - un++; - } - for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { - if (--unlen < 0) { - if (!*cp++ && !*cp) - return chksum; - return -1; - } - code = (cp[1] << 8) | cp[0]; - if (code & 0xff80) { - if (u2w_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } - c1 = ul_loaded && (code & 0x80) ? - ul[code & 0x7f] : u2l[code]; - c2 = ul_loaded && (*un & 0x80) ? - ul[*un & 0x7f] : u2l[*un]; - if (c1 != c2) - return -1; - cp += 2; - un++; - } - for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) { - if (--unlen < 0) { - if (!*cp++ && !*cp) - return chksum; - return -1; - } - code = (cp[1] << 8) | cp[0]; - if (code & 0xff80) { - if (u2w_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } - c1 = ul_loaded && (code & 0x80) ? - ul[code & 0x7f] : u2l[code]; - c2 = ul_loaded && (*un & 0x80) ? - ul[*un & 0x7f] : u2l[*un]; - if (c1 != c2) - return -1; - cp += 2; - un++; - } - return chksum; -} - -/* - * Convert Win95 filename to dirbuf. - * Returns the checksum or -1 if impossible - */ -int -win2unixfn(wep, dp, chksum, table_loaded, u2w) - struct winentry *wep; - struct dirent *dp; - int chksum; - int table_loaded; - u_int16_t *u2w; -{ - u_int8_t *cp; - u_int8_t *np, *ep = dp->d_name + WIN_MAXLEN; - u_int16_t code; - int i; - - if ((wep->weCnt&WIN_CNT) > howmany(WIN_MAXLEN, WIN_CHARS) - || !(wep->weCnt&WIN_CNT)) - return -1; - - /* - * First compare checksums - */ - if (wep->weCnt&WIN_LAST) { - chksum = wep->weChksum; - /* - * This works even though d_namlen is one byte! - */ - dp->d_namlen = (wep->weCnt&WIN_CNT) * WIN_CHARS; - } else if (chksum != wep->weChksum) - chksum = -1; - if (chksum == -1) - return -1; - - /* - * Offset of this entry - */ - i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS; - np = (u_int8_t *)dp->d_name + i; - - /* - * Convert the name parts - */ - for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { - code = (cp[1] << 8) | cp[0]; - switch (code) { - case 0: - *np = '\0'; - dp->d_namlen -= sizeof(wep->wePart2)/2 - + sizeof(wep->wePart3)/2 + i + 1; - return chksum; - case '/': - *np = '\0'; - return -1; - default: - if (code & 0xff80) { - if (table_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } - *np++ = code; - break; - } - /* - * The size comparison should result in the compiler - * optimizing the whole if away - */ - if (WIN_MAXLEN % WIN_CHARS < sizeof(wep->wePart1) / 2 - && np > ep) { - np[-1] = 0; - return -1; - } - cp += 2; - } - for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { - code = (cp[1] << 8) | cp[0]; - switch (code) { - case 0: - *np = '\0'; - dp->d_namlen -= sizeof(wep->wePart3)/2 + i + 1; - return chksum; - case '/': - *np = '\0'; - return -1; - default: - if (code & 0xff80) { - if (table_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } - *np++ = code; - break; - } - /* - * The size comparisons should be optimized away - */ - if (WIN_MAXLEN % WIN_CHARS >= sizeof(wep->wePart1) / 2 - && WIN_MAXLEN % WIN_CHARS < (sizeof(wep->wePart1) + sizeof(wep->wePart2)) / 2 - && np > ep) { - np[-1] = 0; - return -1; - } - cp += 2; - } - for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) { - code = (cp[1] << 8) | cp[0]; - switch (code) { - case 0: - *np = '\0'; - dp->d_namlen -= i + 1; - return chksum; - case '/': - *np = '\0'; - return -1; - default: - if (code & 0xff80) { - if (table_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } - *np++ = code; - break; - } - /* - * See above - */ - if (WIN_MAXLEN % WIN_CHARS >= (sizeof(wep->wePart1) + sizeof(wep->wePart2)) / 2 - && np > ep) { - np[-1] = 0; - return -1; - } - cp += 2; - } - return chksum; -} - -/* - * Compute the checksum of a DOS filename for Win95 use - */ -u_int8_t -winChksum(name) - u_int8_t *name; -{ - int i; - u_int8_t s; - - for (s = 0, i = 11; --i >= 0; s += *name++) - s = (s << 7)|(s >> 1); - return s; -} - -/* - * Determine the number of slots necessary for Win95 names - */ -int -winSlotCnt(un, unlen) - const u_char *un; - int unlen; -{ - unlen = winLenFixup(un, unlen); - if (unlen > WIN_MAXLEN) - return 0; - return howmany(unlen, WIN_CHARS); -} - -/* - * Determine the number of bytes neccesary for Win95 names - */ -int -winLenFixup(un, unlen) - const u_char* un; - int unlen; -{ - for (un += unlen; unlen > 0; unlen--) - if (*--un != ' ' && *un != '.') - break; - return unlen; -} diff --git a/sys/msdosfs/msdosfs_denode.c b/sys/msdosfs/msdosfs_denode.c deleted file mode 100644 index dbdf554..0000000 --- a/sys/msdosfs/msdosfs_denode.c +++ /dev/null @@ -1,724 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: msdosfs_denode.c,v 1.28 1998/02/10 14:10:00 mrg Exp $ */ - -/*- - * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. - * Copyright (C) 1994, 1995, 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 - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/mount.h> -#include <sys/malloc.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/vnode.h> -#include <sys/mutex.h> - -#include <vm/vm.h> -#include <vm/vm_extern.h> - -#include <msdosfs/bpb.h> -#include <msdosfs/msdosfsmount.h> -#include <msdosfs/direntry.h> -#include <msdosfs/denode.h> -#include <msdosfs/fat.h> - -static MALLOC_DEFINE(M_MSDOSFSNODE, "MSDOSFS node", "MSDOSFS vnode private part"); - -static struct denode **dehashtbl; -static u_long dehash; /* size of hash table - 1 */ -#define DEHASH(dev, dcl, doff) (dehashtbl[(minor(dev) + (dcl) + (doff) / \ - sizeof(struct direntry)) & dehash]) -static struct mtx dehash_mtx; - -union _qcvt { - quad_t qcvt; - long val[2]; -}; -#define SETHIGH(q, h) { \ - union _qcvt tmp; \ - tmp.qcvt = (q); \ - tmp.val[_QUAD_HIGHWORD] = (h); \ - (q) = tmp.qcvt; \ -} -#define SETLOW(q, l) { \ - union _qcvt tmp; \ - tmp.qcvt = (q); \ - tmp.val[_QUAD_LOWWORD] = (l); \ - (q) = tmp.qcvt; \ -} - -static struct denode * - msdosfs_hashget __P((dev_t dev, u_long dirclust, - u_long diroff)); -static void msdosfs_hashins __P((struct denode *dep)); -static void msdosfs_hashrem __P((struct denode *dep)); - -/*ARGSUSED*/ -int -msdosfs_init(vfsp) - struct vfsconf *vfsp; -{ - dehashtbl = hashinit(desiredvnodes/2, M_MSDOSFSMNT, &dehash); - mtx_init(&dehash_mtx, "msdosfs dehash", MTX_DEF); - return (0); -} - -int -msdosfs_uninit(vfsp) - struct vfsconf *vfsp; -{ - - if (dehashtbl) - free(dehashtbl, M_MSDOSFSMNT); - mtx_destroy(&dehash_mtx); - return (0); -} - -static struct denode * -msdosfs_hashget(dev, dirclust, diroff) - dev_t dev; - u_long dirclust; - u_long diroff; -{ - struct proc *p = curproc; /* XXX */ - struct denode *dep; - struct vnode *vp; - -loop: - mtx_lock(&dehash_mtx); - for (dep = DEHASH(dev, dirclust, diroff); dep; dep = dep->de_next) { - if (dirclust == dep->de_dirclust - && diroff == dep->de_diroffset - && dev == dep->de_dev - && dep->de_refcnt != 0) { - vp = DETOV(dep); - mtx_lock(&vp->v_interlock); - mtx_unlock(&dehash_mtx); - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) - goto loop; - return (dep); - } - } - mtx_unlock(&dehash_mtx); - return (NULL); -} - -static void -msdosfs_hashins(dep) - struct denode *dep; -{ - struct denode **depp, *deq; - - mtx_lock(&dehash_mtx); - depp = &DEHASH(dep->de_dev, dep->de_dirclust, dep->de_diroffset); - deq = *depp; - if (deq) - deq->de_prev = &dep->de_next; - dep->de_next = deq; - dep->de_prev = depp; - *depp = dep; - mtx_unlock(&dehash_mtx); -} - -static void -msdosfs_hashrem(dep) - struct denode *dep; -{ - struct denode *deq; - - mtx_lock(&dehash_mtx); - deq = dep->de_next; - if (deq) - deq->de_prev = dep->de_prev; - *dep->de_prev = deq; -#ifdef DIAGNOSTIC - dep->de_next = NULL; - dep->de_prev = NULL; -#endif - mtx_unlock(&dehash_mtx); -} - -/* - * If deget() succeeds it returns with the gotten denode locked(). - * - * pmp - address of msdosfsmount structure of the filesystem containing - * the denode of interest. The pm_dev field and the address of - * the msdosfsmount structure are used. - * dirclust - which cluster bp contains, if dirclust is 0 (root directory) - * diroffset is relative to the beginning of the root directory, - * otherwise it is cluster relative. - * diroffset - offset past begin of cluster of denode we want - * depp - returns the address of the gotten denode. - */ -int -deget(pmp, dirclust, diroffset, depp) - struct msdosfsmount *pmp; /* so we know the maj/min number */ - u_long dirclust; /* cluster this dir entry came from */ - u_long diroffset; /* index of entry within the cluster */ - struct denode **depp; /* returns the addr of the gotten denode */ -{ - int error; - dev_t dev = pmp->pm_dev; - struct mount *mntp = pmp->pm_mountp; - struct direntry *direntptr; - struct denode *ldep; - struct vnode *nvp; - struct buf *bp; - struct proc *p = curproc; /* XXX */ - struct timeval tv; - -#ifdef MSDOSFS_DEBUG - printf("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n", - pmp, dirclust, diroffset, depp); -#endif - - /* - * On FAT32 filesystems, root is a (more or less) normal - * directory - */ - if (FAT32(pmp) && dirclust == MSDOSFSROOT) - dirclust = pmp->pm_rootdirblk; - - /* - * See if the denode is in the denode cache. Use the location of - * the directory entry to compute the hash value. For subdir use - * address of "." entry. For root dir (if not FAT32) use cluster - * MSDOSFSROOT, offset MSDOSFSROOT_OFS - * - * NOTE: The check for de_refcnt > 0 below insures the denode being - * examined does not represent an unlinked but still open file. - * These files are not to be accessible even when the directory - * entry that represented the file happens to be reused while the - * deleted file is still open. - */ - ldep = msdosfs_hashget(dev, dirclust, diroffset); - if (ldep) { - *depp = ldep; - return (0); - } - - /* - * Do the MALLOC before the getnewvnode since doing so afterward - * might cause a bogus v_data pointer to get dereferenced - * elsewhere if MALLOC should block. - */ - MALLOC(ldep, struct denode *, sizeof(struct denode), M_MSDOSFSNODE, M_WAITOK); - - /* - * Directory entry was not in cache, have to create a vnode and - * copy it from the passed disk buffer. - */ - /* getnewvnode() does a VREF() on the vnode */ - error = getnewvnode(VT_MSDOSFS, mntp, msdosfs_vnodeop_p, &nvp); - if (error) { - *depp = NULL; - FREE(ldep, M_MSDOSFSNODE); - return error; - } - bzero((caddr_t)ldep, sizeof *ldep); - lockinit(&nvp->v_lock, PINOD, "denode", 0, 0); - nvp->v_vnlock = &nvp->v_lock; - nvp->v_data = ldep; - ldep->de_vnode = nvp; - ldep->de_flag = 0; - ldep->de_devvp = 0; - ldep->de_dev = dev; - ldep->de_dirclust = dirclust; - ldep->de_diroffset = diroffset; - fc_purge(ldep, 0); /* init the fat cache for this denode */ - - /* - * Lock the denode so that it can't be accessed until we've read - * it in and have done what we need to it. Do this here instead - * of at the start of msdosfs_hashins() so that reinsert() can - * call msdosfs_hashins() with a locked denode. - */ - if (VOP_LOCK(nvp, LK_EXCLUSIVE, p) != 0) - panic("deget: unexpected lock failure"); - - /* - * Insert the denode into the hash queue. - */ - msdosfs_hashins(ldep); - - ldep->de_pmp = pmp; - ldep->de_refcnt = 1; - /* - * Copy the directory entry into the denode area of the vnode. - */ - if ((dirclust == MSDOSFSROOT - || (FAT32(pmp) && dirclust == pmp->pm_rootdirblk)) - && diroffset == MSDOSFSROOT_OFS) { - /* - * Directory entry for the root directory. There isn't one, - * so we manufacture one. We should probably rummage - * through the root directory and find a label entry (if it - * exists), and then use the time and date from that entry - * as the time and date for the root denode. - */ - nvp->v_flag |= VROOT; /* should be further down XXX */ - - ldep->de_Attributes = ATTR_DIRECTORY; - ldep->de_LowerCase = 0; - if (FAT32(pmp)) - ldep->de_StartCluster = pmp->pm_rootdirblk; - /* de_FileSize will be filled in further down */ - else { - ldep->de_StartCluster = MSDOSFSROOT; - ldep->de_FileSize = pmp->pm_rootdirsize * DEV_BSIZE; - } - /* - * fill in time and date so that dos2unixtime() doesn't - * spit up when called from msdosfs_getattr() with root - * denode - */ - ldep->de_CHun = 0; - ldep->de_CTime = 0x0000; /* 00:00:00 */ - ldep->de_CDate = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT) - | (1 << DD_DAY_SHIFT); - /* Jan 1, 1980 */ - ldep->de_ADate = ldep->de_CDate; - ldep->de_MTime = ldep->de_CTime; - ldep->de_MDate = ldep->de_CDate; - /* leave the other fields as garbage */ - } else { - error = readep(pmp, dirclust, diroffset, &bp, &direntptr); - if (error) { - /* - * The denode does not contain anything useful, so - * it would be wrong to leave it on its hash chain. - * Arrange for vput() to just forget about it. - */ - ldep->de_Name[0] = SLOT_DELETED; - - vput(nvp); - *depp = NULL; - return (error); - } - DE_INTERNALIZE(ldep, direntptr); - brelse(bp); - } - - /* - * Fill in a few fields of the vnode and finish filling in the - * denode. Then return the address of the found denode. - */ - if (ldep->de_Attributes & ATTR_DIRECTORY) { - /* - * Since DOS directory entries that describe directories - * have 0 in the filesize field, we take this opportunity - * to find out the length of the directory and plug it into - * the denode structure. - */ - u_long size; - - nvp->v_type = VDIR; - if (ldep->de_StartCluster != MSDOSFSROOT) { - error = pcbmap(ldep, 0xffff, 0, &size, 0); - if (error == E2BIG) { - ldep->de_FileSize = de_cn2off(pmp, size); - error = 0; - } else - printf("deget(): pcbmap returned %d\n", error); - } - } else - nvp->v_type = VREG; - getmicrouptime(&tv); - SETHIGH(ldep->de_modrev, tv.tv_sec); - SETLOW(ldep->de_modrev, tv.tv_usec * 4294); - ldep->de_devvp = pmp->pm_devvp; - VREF(ldep->de_devvp); - *depp = ldep; - return (0); -} - -int -deupdat(dep, waitfor) - struct denode *dep; - int waitfor; -{ - int error; - struct buf *bp; - struct direntry *dirp; - struct timespec ts; - - if (DETOV(dep)->v_mount->mnt_flag & MNT_RDONLY) - return (0); - getnanotime(&ts); - DETIMES(dep, &ts, &ts, &ts); - if ((dep->de_flag & DE_MODIFIED) == 0) - return (0); - dep->de_flag &= ~DE_MODIFIED; - if (dep->de_Attributes & ATTR_DIRECTORY) - return (0); - if (dep->de_refcnt <= 0) - return (0); - error = readde(dep, &bp, &dirp); - if (error) - return (error); - DE_EXTERNALIZE(dirp, dep); - if (waitfor) - return (bwrite(bp)); - else { - bdwrite(bp); - return (0); - } -} - -/* - * Truncate the file described by dep to the length specified by length. - */ -int -detrunc(dep, length, flags, cred, p) - struct denode *dep; - u_long length; - int flags; - struct ucred *cred; - struct proc *p; -{ - int error; - int allerror; - u_long eofentry; - u_long chaintofree; - daddr_t bn; - int boff; - int isadir = dep->de_Attributes & ATTR_DIRECTORY; - struct buf *bp; - struct msdosfsmount *pmp = dep->de_pmp; - -#ifdef MSDOSFS_DEBUG - printf("detrunc(): file %s, length %lu, flags %x\n", dep->de_Name, length, flags); -#endif - - /* - * Disallow attempts to truncate the root directory since it is of - * fixed size. That's just the way dos filesystems are. We use - * the VROOT bit in the vnode because checking for the directory - * bit and a startcluster of 0 in the denode is not adequate to - * recognize the root directory at this point in a file or - * directory's life. - */ - if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp)) { - printf("detrunc(): can't truncate root directory, clust %ld, offset %ld\n", - dep->de_dirclust, dep->de_diroffset); - return (EINVAL); - } - - - if (dep->de_FileSize < length) { - vnode_pager_setsize(DETOV(dep), length); - return deextend(dep, length, cred); - } - - /* - * If the desired length is 0 then remember the starting cluster of - * the file and set the StartCluster field in the directory entry - * to 0. If the desired length is not zero, then get the number of - * the last cluster in the shortened file. Then get the number of - * the first cluster in the part of the file that is to be freed. - * Then set the next cluster pointer in the last cluster of the - * file to CLUST_EOFE. - */ - if (length == 0) { - chaintofree = dep->de_StartCluster; - dep->de_StartCluster = 0; - eofentry = ~0; - } else { - error = pcbmap(dep, de_clcount(pmp, length) - 1, 0, - &eofentry, 0); - if (error) { -#ifdef MSDOSFS_DEBUG - printf("detrunc(): pcbmap fails %d\n", error); -#endif - return (error); - } - } - - fc_purge(dep, de_clcount(pmp, length)); - - /* - * If the new length is not a multiple of the cluster size then we - * must zero the tail end of the new last cluster in case it - * becomes part of the file again because of a seek. - */ - if ((boff = length & pmp->pm_crbomask) != 0) { - if (isadir) { - bn = cntobn(pmp, eofentry); - error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster, - NOCRED, &bp); - } else { - bn = de_blk(pmp, length); - error = bread(DETOV(dep), bn, pmp->pm_bpcluster, - NOCRED, &bp); - } - if (error) { - brelse(bp); -#ifdef MSDOSFS_DEBUG - printf("detrunc(): bread fails %d\n", error); -#endif - return (error); - } - /* - * is this the right place for it? - */ - bzero(bp->b_data + boff, pmp->pm_bpcluster - boff); - if (flags & IO_SYNC) - bwrite(bp); - else - bdwrite(bp); - } - - /* - * Write out the updated directory entry. Even if the update fails - * we free the trailing clusters. - */ - dep->de_FileSize = length; - if (!isadir) - dep->de_flag |= DE_UPDATE|DE_MODIFIED; - allerror = vtruncbuf(DETOV(dep), cred, p, length, pmp->pm_bpcluster); -#ifdef MSDOSFS_DEBUG - if (allerror) - printf("detrunc(): vtruncbuf error %d\n", allerror); -#endif - error = deupdat(dep, 1); - if (error && (allerror == 0)) - allerror = error; -#ifdef MSDOSFS_DEBUG - printf("detrunc(): allerror %d, eofentry %lu\n", - allerror, eofentry); -#endif - - /* - * If we need to break the cluster chain for the file then do it - * now. - */ - if (eofentry != ~0) { - error = fatentry(FAT_GET_AND_SET, pmp, eofentry, - &chaintofree, CLUST_EOFE); - if (error) { -#ifdef MSDOSFS_DEBUG - printf("detrunc(): fatentry errors %d\n", error); -#endif - return (error); - } - fc_setcache(dep, FC_LASTFC, de_cluster(pmp, length - 1), - eofentry); - } - - /* - * Now free the clusters removed from the file because of the - * truncation. - */ - if (chaintofree != 0 && !MSDOSFSEOF(pmp, chaintofree)) - freeclusterchain(pmp, chaintofree); - - return (allerror); -} - -/* - * Extend the file described by dep to length specified by length. - */ -int -deextend(dep, length, cred) - struct denode *dep; - u_long length; - struct ucred *cred; -{ - struct msdosfsmount *pmp = dep->de_pmp; - u_long count; - int error; - - /* - * The root of a DOS filesystem cannot be extended. - */ - if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp)) - return (EINVAL); - - /* - * Directories cannot be extended. - */ - if (dep->de_Attributes & ATTR_DIRECTORY) - return (EISDIR); - - if (length <= dep->de_FileSize) - panic("deextend: file too large"); - - /* - * Compute the number of clusters to allocate. - */ - count = de_clcount(pmp, length) - de_clcount(pmp, dep->de_FileSize); - if (count > 0) { - if (count > pmp->pm_freeclustercount) - return (ENOSPC); - error = extendfile(dep, count, NULL, NULL, DE_CLEAR); - if (error) { - /* truncate the added clusters away again */ - (void) detrunc(dep, dep->de_FileSize, 0, cred, NULL); - return (error); - } - } - dep->de_FileSize = length; - dep->de_flag |= DE_UPDATE|DE_MODIFIED; - return (deupdat(dep, 1)); -} - -/* - * Move a denode to its correct hash queue after the file it represents has - * been moved to a new directory. - */ -void -reinsert(dep) - struct denode *dep; -{ - /* - * Fix up the denode cache. If the denode is for a directory, - * there is nothing to do since the hash is based on the starting - * cluster of the directory file and that hasn't changed. If for a - * file the hash is based on the location of the directory entry, - * so we must remove it from the cache and re-enter it with the - * hash based on the new location of the directory entry. - */ - if (dep->de_Attributes & ATTR_DIRECTORY) - return; - msdosfs_hashrem(dep); - msdosfs_hashins(dep); -} - -int -msdosfs_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct denode *dep = VTODE(vp); - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_reclaim(): dep %p, file %s, refcnt %ld\n", - dep, dep->de_Name, dep->de_refcnt); -#endif - - if (prtactive && vp->v_usecount != 0) - vprint("msdosfs_reclaim(): pushing active", vp); - /* - * Remove the denode from its hash chain. - */ - msdosfs_hashrem(dep); - /* - * Purge old data structures associated with the denode. - */ - cache_purge(vp); - if (dep->de_devvp) { - vrele(dep->de_devvp); - dep->de_devvp = 0; - } -#if 0 /* XXX */ - dep->de_flag = 0; -#endif - lockdestroy(&vp->v_lock); - FREE(dep, M_MSDOSFSNODE); - vp->v_data = NULL; - - return (0); -} - -int -msdosfs_inactive(ap) - struct vop_inactive_args /* { - struct vnode *a_vp; - struct proc *a_p; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct denode *dep = VTODE(vp); - struct proc *p = ap->a_p; - int error = 0; - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]); -#endif - - if (prtactive && vp->v_usecount != 0) - vprint("msdosfs_inactive(): pushing active", vp); - - /* - * Ignore denodes related to stale file handles. - */ - if (dep->de_Name[0] == SLOT_DELETED) - goto out; - - /* - * If the file has been deleted and it is on a read/write - * filesystem, then truncate the file, and mark the directory slot - * as empty. (This may not be necessary for the dos filesystem.) - */ -#ifdef MSDOSFS_DEBUG - printf("msdosfs_inactive(): dep %p, refcnt %ld, mntflag %x, MNT_RDONLY %x\n", - dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY); -#endif - if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { - error = detrunc(dep, (u_long) 0, 0, NOCRED, p); - dep->de_flag |= DE_UPDATE; - dep->de_Name[0] = SLOT_DELETED; - } - deupdat(dep, 0); - -out: - VOP_UNLOCK(vp, 0, p); - /* - * If we are done with the denode, reclaim it - * so that it can be reused immediately. - */ -#ifdef MSDOSFS_DEBUG - printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", vp->v_usecount, - dep->de_Name[0]); -#endif - if (dep->de_Name[0] == SLOT_DELETED) - vrecycle(vp, NULL, p); - return (error); -} diff --git a/sys/msdosfs/msdosfs_fat.c b/sys/msdosfs/msdosfs_fat.c deleted file mode 100644 index 38abc16..0000000 --- a/sys/msdosfs/msdosfs_fat.c +++ /dev/null @@ -1,1102 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: msdosfs_fat.c,v 1.28 1997/11/17 15:36:49 ws Exp $ */ - -/*- - * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. - * Copyright (C) 1994, 1995, 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 - */ - -/* - * kernel include files. - */ -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/mount.h> /* to define statfs structure */ -#include <sys/vnode.h> /* to define vattr structure */ - -/* - * msdosfs include files. - */ -#include <msdosfs/bpb.h> -#include <msdosfs/msdosfsmount.h> -#include <msdosfs/direntry.h> -#include <msdosfs/denode.h> -#include <msdosfs/fat.h> - -/* - * Fat cache stats. - */ -static int fc_fileextends; /* # of file extends */ -static int fc_lfcempty; /* # of time last file cluster cache entry - * was empty */ -static int fc_bmapcalls; /* # of times pcbmap was called */ - -#define LMMAX 20 -static int fc_lmdistance[LMMAX];/* counters for how far off the last - * cluster mapped entry was. */ -static int fc_largedistance; /* off by more than LMMAX */ - -static int chainalloc __P((struct msdosfsmount *pmp, u_long start, - u_long count, u_long fillwith, - u_long *retcluster, u_long *got)); -static int chainlength __P((struct msdosfsmount *pmp, u_long start, - u_long count)); -static void fatblock __P((struct msdosfsmount *pmp, u_long ofs, - u_long *bnp, u_long *sizep, u_long *bop)); -static int fatchain __P((struct msdosfsmount *pmp, u_long start, - u_long count, u_long fillwith)); -static void fc_lookup __P((struct denode *dep, u_long findcn, - u_long *frcnp, u_long *fsrcnp)); -static void updatefats __P((struct msdosfsmount *pmp, struct buf *bp, - u_long fatbn)); -static __inline void - usemap_alloc __P((struct msdosfsmount *pmp, u_long cn)); -static __inline void - usemap_free __P((struct msdosfsmount *pmp, u_long cn)); - -static void -fatblock(pmp, ofs, bnp, sizep, bop) - struct msdosfsmount *pmp; - u_long ofs; - u_long *bnp; - u_long *sizep; - u_long *bop; -{ - u_long bn, size; - - bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec; - size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn) - * DEV_BSIZE; - bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs; - - if (bnp) - *bnp = bn; - if (sizep) - *sizep = size; - if (bop) - *bop = ofs % pmp->pm_fatblocksize; -} - -/* - * Map the logical cluster number of a file into a physical disk sector - * that is filesystem relative. - * - * dep - address of denode representing the file of interest - * findcn - file relative cluster whose filesystem relative cluster number - * and/or block number are/is to be found - * bnp - address of where to place the file system relative block number. - * If this pointer is null then don't return this quantity. - * cnp - address of where to place the file system relative cluster number. - * If this pointer is null then don't return this quantity. - * - * NOTE: Either bnp or cnp must be non-null. - * This function has one side effect. If the requested file relative cluster - * is beyond the end of file, then the actual number of clusters in the file - * is returned in *cnp. This is useful for determining how long a directory is. - * If cnp is null, nothing is returned. - */ -int -pcbmap(dep, findcn, bnp, cnp, sp) - struct denode *dep; - u_long findcn; /* file relative cluster to get */ - daddr_t *bnp; /* returned filesys relative blk number */ - u_long *cnp; /* returned cluster number */ - int *sp; /* returned block size */ -{ - int error; - u_long i; - u_long cn; - u_long prevcn = 0; /* XXX: prevcn could be used unititialized */ - u_long byteoffset; - u_long bn; - u_long bo; - struct buf *bp = NULL; - u_long bp_bn = -1; - struct msdosfsmount *pmp = dep->de_pmp; - u_long bsize; - - fc_bmapcalls++; - - /* - * If they don't give us someplace to return a value then don't - * bother doing anything. - */ - if (bnp == NULL && cnp == NULL && sp == NULL) - return (0); - - cn = dep->de_StartCluster; - /* - * The "file" that makes up the root directory is contiguous, - * permanently allocated, of fixed size, and is not made up of - * clusters. If the cluster number is beyond the end of the root - * directory, then return the number of clusters in the file. - */ - if (cn == MSDOSFSROOT) { - if (dep->de_Attributes & ATTR_DIRECTORY) { - if (de_cn2off(pmp, findcn) >= dep->de_FileSize) { - if (cnp) - *cnp = de_bn2cn(pmp, pmp->pm_rootdirsize); - return (E2BIG); - } - if (bnp) - *bnp = pmp->pm_rootdirblk + de_cn2bn(pmp, findcn); - if (cnp) - *cnp = MSDOSFSROOT; - if (sp) - *sp = min(pmp->pm_bpcluster, - dep->de_FileSize - de_cn2off(pmp, findcn)); - return (0); - } else { /* just an empty file */ - if (cnp) - *cnp = 0; - return (E2BIG); - } - } - - /* - * All other files do I/O in cluster sized blocks - */ - if (sp) - *sp = pmp->pm_bpcluster; - - /* - * Rummage around in the fat cache, maybe we can avoid tromping - * thru every fat entry for the file. And, keep track of how far - * off the cache was from where we wanted to be. - */ - i = 0; - fc_lookup(dep, findcn, &i, &cn); - if ((bn = findcn - i) >= LMMAX) - fc_largedistance++; - else - fc_lmdistance[bn]++; - - /* - * Handle all other files or directories the normal way. - */ - for (; i < findcn; i++) { - /* - * Stop with all reserved clusters, not just with EOF. - */ - if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD) - goto hiteof; - byteoffset = FATOFS(pmp, cn); - fatblock(pmp, byteoffset, &bn, &bsize, &bo); - if (bn != bp_bn) { - if (bp) - brelse(bp); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - bp_bn = bn; - } - prevcn = cn; - if (FAT32(pmp)) - cn = getulong(&bp->b_data[bo]); - else - cn = getushort(&bp->b_data[bo]); - if (FAT12(pmp) && (prevcn & 1)) - cn >>= 4; - cn &= pmp->pm_fatmask; - - /* - * Force the special cluster numbers - * to be the same for all cluster sizes - * to let the rest of msdosfs handle - * all cases the same. - */ - if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD) - cn |= ~pmp->pm_fatmask; - } - - if (!MSDOSFSEOF(pmp, cn)) { - if (bp) - brelse(bp); - if (bnp) - *bnp = cntobn(pmp, cn); - if (cnp) - *cnp = cn; - fc_setcache(dep, FC_LASTMAP, i, cn); - return (0); - } - -hiteof:; - if (cnp) - *cnp = i; - if (bp) - brelse(bp); - /* update last file cluster entry in the fat cache */ - fc_setcache(dep, FC_LASTFC, i - 1, prevcn); - return (E2BIG); -} - -/* - * Find the closest entry in the fat cache to the cluster we are looking - * for. - */ -static void -fc_lookup(dep, findcn, frcnp, fsrcnp) - struct denode *dep; - u_long findcn; - u_long *frcnp; - u_long *fsrcnp; -{ - int i; - u_long cn; - struct fatcache *closest = 0; - - for (i = 0; i < FC_SIZE; i++) { - cn = dep->de_fc[i].fc_frcn; - if (cn != FCE_EMPTY && cn <= findcn) { - if (closest == 0 || cn > closest->fc_frcn) - closest = &dep->de_fc[i]; - } - } - if (closest) { - *frcnp = closest->fc_frcn; - *fsrcnp = closest->fc_fsrcn; - } -} - -/* - * Purge the fat cache in denode dep of all entries relating to file - * relative cluster frcn and beyond. - */ -void -fc_purge(dep, frcn) - struct denode *dep; - u_int frcn; -{ - int i; - struct fatcache *fcp; - - fcp = dep->de_fc; - for (i = 0; i < FC_SIZE; i++, fcp++) { - if (fcp->fc_frcn >= frcn) - fcp->fc_frcn = FCE_EMPTY; - } -} - -/* - * Update the fat. - * If mirroring the fat, update all copies, with the first copy as last. - * Else update only the current fat (ignoring the others). - * - * pmp - msdosfsmount structure for filesystem to update - * bp - addr of modified fat block - * fatbn - block number relative to begin of filesystem of the modified fat block. - */ -static void -updatefats(pmp, bp, fatbn) - struct msdosfsmount *pmp; - struct buf *bp; - u_long fatbn; -{ - int i; - struct buf *bpn; - -#ifdef MSDOSFS_DEBUG - printf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn); -#endif - - /* - * If we have an FSInfo block, update it. - */ - if (pmp->pm_fsinfo) { - u_long cn = pmp->pm_nxtfree; - - if (pmp->pm_freeclustercount - && (pmp->pm_inusemap[cn / N_INUSEBITS] - & (1 << (cn % N_INUSEBITS)))) { - /* - * The cluster indicated in FSInfo isn't free - * any longer. Got get a new free one. - */ - for (cn = 0; cn < pmp->pm_maxcluster; cn += N_INUSEBITS) - if (pmp->pm_inusemap[cn / N_INUSEBITS] != (u_int)-1) - break; - pmp->pm_nxtfree = cn - + ffs(pmp->pm_inusemap[cn / N_INUSEBITS] - ^ (u_int)-1) - 1; - } - if (bread(pmp->pm_devvp, pmp->pm_fsinfo, fsi_size(pmp), - NOCRED, &bpn) != 0) { - /* - * Ignore the error, but turn off FSInfo update for the future. - */ - pmp->pm_fsinfo = 0; - brelse(bpn); - } else { - struct fsinfo *fp = (struct fsinfo *)bpn->b_data; - - putulong(fp->fsinfree, pmp->pm_freeclustercount); - putulong(fp->fsinxtfree, pmp->pm_nxtfree); - if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) - bwrite(bpn); - else - bdwrite(bpn); - } - } - - if (pmp->pm_flags & MSDOSFS_FATMIRROR) { - /* - * Now copy the block(s) of the modified fat to the other copies of - * the fat and write them out. This is faster than reading in the - * other fats and then writing them back out. This could tie up - * the fat for quite a while. Preventing others from accessing it. - * To prevent us from going after the fat quite so much we use - * delayed writes, unless they specfied "synchronous" when the - * filesystem was mounted. If synch is asked for then use - * bwrite()'s and really slow things down. - */ - for (i = 1; i < pmp->pm_FATs; i++) { - fatbn += pmp->pm_FATsecs; - /* getblk() never fails */ - bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount, 0, 0); - bcopy(bp->b_data, bpn->b_data, bp->b_bcount); - if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) - bwrite(bpn); - else - bdwrite(bpn); - } - } - - /* - * Write out the first (or current) fat last. - */ - if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) - bwrite(bp); - else - bdwrite(bp); - /* - * Maybe update fsinfo sector here? - */ -} - -/* - * Updating entries in 12 bit fats is a pain in the butt. - * - * The following picture shows where nibbles go when moving from a 12 bit - * cluster number into the appropriate bytes in the FAT. - * - * byte m byte m+1 byte m+2 - * +----+----+ +----+----+ +----+----+ - * | 0 1 | | 2 3 | | 4 5 | FAT bytes - * +----+----+ +----+----+ +----+----+ - * - * +----+----+----+ +----+----+----+ - * | 3 0 1 | | 4 5 2 | - * +----+----+----+ +----+----+----+ - * cluster n cluster n+1 - * - * Where n is even. m = n + (n >> 2) - * - */ -static __inline void -usemap_alloc(pmp, cn) - struct msdosfsmount *pmp; - u_long cn; -{ - - pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS); - pmp->pm_freeclustercount--; -} - -static __inline void -usemap_free(pmp, cn) - struct msdosfsmount *pmp; - u_long cn; -{ - - pmp->pm_freeclustercount++; - pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS)); -} - -int -clusterfree(pmp, cluster, oldcnp) - struct msdosfsmount *pmp; - u_long cluster; - u_long *oldcnp; -{ - int error; - u_long oldcn; - - usemap_free(pmp, cluster); - error = fatentry(FAT_GET_AND_SET, pmp, cluster, &oldcn, MSDOSFSFREE); - if (error) { - usemap_alloc(pmp, cluster); - return (error); - } - /* - * If the cluster was successfully marked free, then update - * the count of free clusters, and turn off the "allocated" - * bit in the "in use" cluster bit map. - */ - if (oldcnp) - *oldcnp = oldcn; - return (0); -} - -/* - * Get or Set or 'Get and Set' the cluster'th entry in the fat. - * - * function - whether to get or set a fat entry - * pmp - address of the msdosfsmount structure for the filesystem - * whose fat is to be manipulated. - * cn - which cluster is of interest - * oldcontents - address of a word that is to receive the contents of the - * cluster'th entry if this is a get function - * newcontents - the new value to be written into the cluster'th element of - * the fat if this is a set function. - * - * This function can also be used to free a cluster by setting the fat entry - * for a cluster to 0. - * - * All copies of the fat are updated if this is a set function. NOTE: If - * fatentry() marks a cluster as free it does not update the inusemap in - * the msdosfsmount structure. This is left to the caller. - */ -int -fatentry(function, pmp, cn, oldcontents, newcontents) - int function; - struct msdosfsmount *pmp; - u_long cn; - u_long *oldcontents; - u_long newcontents; -{ - int error; - u_long readcn; - u_long bn, bo, bsize, byteoffset; - struct buf *bp; - -#ifdef MSDOSFS_DEBUG - printf("fatentry(func %d, pmp %p, clust %lu, oldcon %p, newcon %lx)\n", - function, pmp, cn, oldcontents, newcontents); -#endif - -#ifdef DIAGNOSTIC - /* - * Be sure they asked us to do something. - */ - if ((function & (FAT_SET | FAT_GET)) == 0) { - printf("fatentry(): function code doesn't specify get or set\n"); - return (EINVAL); - } - - /* - * If they asked us to return a cluster number but didn't tell us - * where to put it, give them an error. - */ - if ((function & FAT_GET) && oldcontents == NULL) { - printf("fatentry(): get function with no place to put result\n"); - return (EINVAL); - } -#endif - - /* - * Be sure the requested cluster is in the filesystem. - */ - if (cn < CLUST_FIRST || cn > pmp->pm_maxcluster) - return (EINVAL); - - byteoffset = FATOFS(pmp, cn); - fatblock(pmp, byteoffset, &bn, &bsize, &bo); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - - if (function & FAT_GET) { - if (FAT32(pmp)) - readcn = getulong(&bp->b_data[bo]); - else - readcn = getushort(&bp->b_data[bo]); - if (FAT12(pmp) & (cn & 1)) - readcn >>= 4; - readcn &= pmp->pm_fatmask; - /* map reserved fat entries to same values for all fats */ - if ((readcn | ~pmp->pm_fatmask) >= CLUST_RSRVD) - readcn |= ~pmp->pm_fatmask; - *oldcontents = readcn; - } - if (function & FAT_SET) { - switch (pmp->pm_fatmask) { - case FAT12_MASK: - readcn = getushort(&bp->b_data[bo]); - if (cn & 1) { - readcn &= 0x000f; - readcn |= newcontents << 4; - } else { - readcn &= 0xf000; - readcn |= newcontents & 0xfff; - } - putushort(&bp->b_data[bo], readcn); - break; - case FAT16_MASK: - putushort(&bp->b_data[bo], newcontents); - break; - case FAT32_MASK: - /* - * According to spec we have to retain the - * high order bits of the fat entry. - */ - readcn = getulong(&bp->b_data[bo]); - readcn &= ~FAT32_MASK; - readcn |= newcontents & FAT32_MASK; - putulong(&bp->b_data[bo], readcn); - break; - } - updatefats(pmp, bp, bn); - bp = NULL; - pmp->pm_fmod = 1; - } - if (bp) - brelse(bp); - return (0); -} - -/* - * Update a contiguous cluster chain - * - * pmp - mount point - * start - first cluster of chain - * count - number of clusters in chain - * fillwith - what to write into fat entry of last cluster - */ -static int -fatchain(pmp, start, count, fillwith) - struct msdosfsmount *pmp; - u_long start; - u_long count; - u_long fillwith; -{ - int error; - u_long bn, bo, bsize, byteoffset, readcn, newc; - struct buf *bp; - -#ifdef MSDOSFS_DEBUG - printf("fatchain(pmp %p, start %lu, count %lu, fillwith %lx)\n", - pmp, start, count, fillwith); -#endif - /* - * Be sure the clusters are in the filesystem. - */ - if (start < CLUST_FIRST || start + count - 1 > pmp->pm_maxcluster) - return (EINVAL); - - while (count > 0) { - byteoffset = FATOFS(pmp, start); - fatblock(pmp, byteoffset, &bn, &bsize, &bo); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - while (count > 0) { - start++; - newc = --count > 0 ? start : fillwith; - switch (pmp->pm_fatmask) { - case FAT12_MASK: - readcn = getushort(&bp->b_data[bo]); - if (start & 1) { - readcn &= 0xf000; - readcn |= newc & 0xfff; - } else { - readcn &= 0x000f; - readcn |= newc << 4; - } - putushort(&bp->b_data[bo], readcn); - bo++; - if (!(start & 1)) - bo++; - break; - case FAT16_MASK: - putushort(&bp->b_data[bo], newc); - bo += 2; - break; - case FAT32_MASK: - readcn = getulong(&bp->b_data[bo]); - readcn &= ~pmp->pm_fatmask; - readcn |= newc & pmp->pm_fatmask; - putulong(&bp->b_data[bo], readcn); - bo += 4; - break; - } - if (bo >= bsize) - break; - } - updatefats(pmp, bp, bn); - } - pmp->pm_fmod = 1; - return (0); -} - -/* - * Check the length of a free cluster chain starting at start. - * - * pmp - mount point - * start - start of chain - * count - maximum interesting length - */ -static int -chainlength(pmp, start, count) - struct msdosfsmount *pmp; - u_long start; - u_long count; -{ - u_long idx, max_idx; - u_int map; - u_long len; - - max_idx = pmp->pm_maxcluster / N_INUSEBITS; - idx = start / N_INUSEBITS; - start %= N_INUSEBITS; - map = pmp->pm_inusemap[idx]; - map &= ~((1 << start) - 1); - if (map) { - len = ffs(map) - 1 - start; - return (len > count ? count : len); - } - len = N_INUSEBITS - start; - if (len >= count) - return (count); - while (++idx <= max_idx) { - if (len >= count) - break; - map = pmp->pm_inusemap[idx]; - if (map) { - len += ffs(map) - 1; - break; - } - len += N_INUSEBITS; - } - return (len > count ? count : len); -} - -/* - * Allocate contigous free clusters. - * - * pmp - mount point. - * start - start of cluster chain. - * count - number of clusters to allocate. - * fillwith - put this value into the fat entry for the - * last allocated cluster. - * retcluster - put the first allocated cluster's number here. - * got - how many clusters were actually allocated. - */ -static int -chainalloc(pmp, start, count, fillwith, retcluster, got) - struct msdosfsmount *pmp; - u_long start; - u_long count; - u_long fillwith; - u_long *retcluster; - u_long *got; -{ - int error; - u_long cl, n; - - for (cl = start, n = count; n-- > 0;) - usemap_alloc(pmp, cl++); - - error = fatchain(pmp, start, count, fillwith); - if (error != 0) - return (error); -#ifdef MSDOSFS_DEBUG - printf("clusteralloc(): allocated cluster chain at %lu (%lu clusters)\n", - start, count); -#endif - if (retcluster) - *retcluster = start; - if (got) - *got = count; - return (0); -} - -/* - * Allocate contiguous free clusters. - * - * pmp - mount point. - * start - preferred start of cluster chain. - * count - number of clusters requested. - * fillwith - put this value into the fat entry for the - * last allocated cluster. - * retcluster - put the first allocated cluster's number here. - * got - how many clusters were actually allocated. - */ -int -clusteralloc(pmp, start, count, fillwith, retcluster, got) - struct msdosfsmount *pmp; - u_long start; - u_long count; - u_long fillwith; - u_long *retcluster; - u_long *got; -{ - u_long idx; - u_long len, newst, foundl, cn, l; - u_long foundcn = 0; /* XXX: foundcn could be used unititialized */ - u_int map; - -#ifdef MSDOSFS_DEBUG - printf("clusteralloc(): find %lu clusters\n",count); -#endif - if (start) { - if ((len = chainlength(pmp, start, count)) >= count) - return (chainalloc(pmp, start, count, fillwith, retcluster, got)); - } else - len = 0; - - /* - * Start at a (pseudo) random place to maximize cluster runs - * under multiple writers. - */ - newst = random() % (pmp->pm_maxcluster + 1); - foundl = 0; - - for (cn = newst; cn <= pmp->pm_maxcluster;) { - idx = cn / N_INUSEBITS; - map = pmp->pm_inusemap[idx]; - map |= (1 << (cn % N_INUSEBITS)) - 1; - if (map != (u_int)-1) { - cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1; - if ((l = chainlength(pmp, cn, count)) >= count) - return (chainalloc(pmp, cn, count, fillwith, retcluster, got)); - if (l > foundl) { - foundcn = cn; - foundl = l; - } - cn += l + 1; - continue; - } - cn += N_INUSEBITS - cn % N_INUSEBITS; - } - for (cn = 0; cn < newst;) { - idx = cn / N_INUSEBITS; - map = pmp->pm_inusemap[idx]; - map |= (1 << (cn % N_INUSEBITS)) - 1; - if (map != (u_int)-1) { - cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1; - if ((l = chainlength(pmp, cn, count)) >= count) - return (chainalloc(pmp, cn, count, fillwith, retcluster, got)); - if (l > foundl) { - foundcn = cn; - foundl = l; - } - cn += l + 1; - continue; - } - cn += N_INUSEBITS - cn % N_INUSEBITS; - } - - if (!foundl) - return (ENOSPC); - - if (len) - return (chainalloc(pmp, start, len, fillwith, retcluster, got)); - else - return (chainalloc(pmp, foundcn, foundl, fillwith, retcluster, got)); -} - - -/* - * Free a chain of clusters. - * - * pmp - address of the msdosfs mount structure for the filesystem - * containing the cluster chain to be freed. - * startcluster - number of the 1st cluster in the chain of clusters to be - * freed. - */ -int -freeclusterchain(pmp, cluster) - struct msdosfsmount *pmp; - u_long cluster; -{ - int error; - struct buf *bp = NULL; - u_long bn, bo, bsize, byteoffset; - u_long readcn, lbn = -1; - - while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) { - byteoffset = FATOFS(pmp, cluster); - fatblock(pmp, byteoffset, &bn, &bsize, &bo); - if (lbn != bn) { - if (bp) - updatefats(pmp, bp, lbn); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - lbn = bn; - } - usemap_free(pmp, cluster); - switch (pmp->pm_fatmask) { - case FAT12_MASK: - readcn = getushort(&bp->b_data[bo]); - if (cluster & 1) { - cluster = readcn >> 4; - readcn &= 0x000f; - readcn |= MSDOSFSFREE << 4; - } else { - cluster = readcn; - readcn &= 0xf000; - readcn |= MSDOSFSFREE & 0xfff; - } - putushort(&bp->b_data[bo], readcn); - break; - case FAT16_MASK: - cluster = getushort(&bp->b_data[bo]); - putushort(&bp->b_data[bo], MSDOSFSFREE); - break; - case FAT32_MASK: - cluster = getulong(&bp->b_data[bo]); - putulong(&bp->b_data[bo], - (MSDOSFSFREE & FAT32_MASK) | (cluster & ~FAT32_MASK)); - break; - } - cluster &= pmp->pm_fatmask; - if ((cluster | ~pmp->pm_fatmask) >= CLUST_RSRVD) - cluster |= pmp->pm_fatmask; - } - if (bp) - updatefats(pmp, bp, bn); - return (0); -} - -/* - * Read in fat blocks looking for free clusters. For every free cluster - * found turn off its corresponding bit in the pm_inusemap. - */ -int -fillinusemap(pmp) - struct msdosfsmount *pmp; -{ - struct buf *bp = NULL; - u_long cn, readcn; - int error; - u_long bn, bo, bsize, byteoffset; - - /* - * Mark all clusters in use, we mark the free ones in the fat scan - * loop further down. - */ - for (cn = 0; cn < (pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS; cn++) - pmp->pm_inusemap[cn] = (u_int)-1; - - /* - * Figure how many free clusters are in the filesystem by ripping - * through the fat counting the number of entries whose content is - * zero. These represent free clusters. - */ - pmp->pm_freeclustercount = 0; - for (cn = CLUST_FIRST; cn <= pmp->pm_maxcluster; cn++) { - byteoffset = FATOFS(pmp, cn); - bo = byteoffset % pmp->pm_fatblocksize; - if (!bo || !bp) { - /* Read new FAT block */ - if (bp) - brelse(bp); - fatblock(pmp, byteoffset, &bn, &bsize, NULL); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - } - if (FAT32(pmp)) - readcn = getulong(&bp->b_data[bo]); - else - readcn = getushort(&bp->b_data[bo]); - if (FAT12(pmp) && (cn & 1)) - readcn >>= 4; - readcn &= pmp->pm_fatmask; - - if (readcn == 0) - usemap_free(pmp, cn); - } - brelse(bp); - return (0); -} - -/* - * Allocate a new cluster and chain it onto the end of the file. - * - * dep - the file to extend - * count - number of clusters to allocate - * bpp - where to return the address of the buf header for the first new - * file block - * ncp - where to put cluster number of the first newly allocated cluster - * If this pointer is 0, do not return the cluster number. - * flags - see fat.h - * - * NOTE: This function is not responsible for turning on the DE_UPDATE bit of - * the de_flag field of the denode and it does not change the de_FileSize - * field. This is left for the caller to do. - */ -int -extendfile(dep, count, bpp, ncp, flags) - struct denode *dep; - u_long count; - struct buf **bpp; - u_long *ncp; - int flags; -{ - int error; - u_long frcn; - u_long cn, got; - struct msdosfsmount *pmp = dep->de_pmp; - struct buf *bp; - - /* - * Don't try to extend the root directory - */ - if (dep->de_StartCluster == MSDOSFSROOT - && (dep->de_Attributes & ATTR_DIRECTORY)) { - printf("extendfile(): attempt to extend root directory\n"); - return (ENOSPC); - } - - /* - * If the "file's last cluster" cache entry is empty, and the file - * is not empty, then fill the cache entry by calling pcbmap(). - */ - fc_fileextends++; - if (dep->de_fc[FC_LASTFC].fc_frcn == FCE_EMPTY && - dep->de_StartCluster != 0) { - fc_lfcempty++; - error = pcbmap(dep, 0xffff, 0, &cn, 0); - /* we expect it to return E2BIG */ - if (error != E2BIG) - return (error); - } - - while (count > 0) { - /* - * Allocate a new cluster chain and cat onto the end of the - * file. * If the file is empty we make de_StartCluster point - * to the new block. Note that de_StartCluster being 0 is - * sufficient to be sure the file is empty since we exclude - * attempts to extend the root directory above, and the root - * dir is the only file with a startcluster of 0 that has - * blocks allocated (sort of). - */ - if (dep->de_StartCluster == 0) - cn = 0; - else - cn = dep->de_fc[FC_LASTFC].fc_fsrcn + 1; - error = clusteralloc(pmp, cn, count, CLUST_EOFE, &cn, &got); - if (error) - return (error); - - count -= got; - - /* - * Give them the filesystem relative cluster number if they want - * it. - */ - if (ncp) { - *ncp = cn; - ncp = NULL; - } - - if (dep->de_StartCluster == 0) { - dep->de_StartCluster = cn; - frcn = 0; - } else { - error = fatentry(FAT_SET, pmp, - dep->de_fc[FC_LASTFC].fc_fsrcn, - 0, cn); - if (error) { - clusterfree(pmp, cn, NULL); - return (error); - } - frcn = dep->de_fc[FC_LASTFC].fc_frcn + 1; - } - - /* - * Update the "last cluster of the file" entry in the denode's fat - * cache. - */ - fc_setcache(dep, FC_LASTFC, frcn + got - 1, cn + got - 1); - - if (flags & DE_CLEAR) { - while (got-- > 0) { - /* - * Get the buf header for the new block of the file. - */ - if (dep->de_Attributes & ATTR_DIRECTORY) - bp = getblk(pmp->pm_devvp, cntobn(pmp, cn++), - pmp->pm_bpcluster, 0, 0); - else { - bp = getblk(DETOV(dep), de_cn2bn(pmp, frcn++), - pmp->pm_bpcluster, 0, 0); - /* - * Do the bmap now, as in msdosfs_write - */ - if (pcbmap(dep, - de_bn2cn(pmp, bp->b_lblkno), - &bp->b_blkno, 0, 0)) - bp->b_blkno = -1; - if (bp->b_blkno == -1) - panic("extendfile: pcbmap"); - } - clrbuf(bp); - if (bpp) { - *bpp = bp; - bpp = NULL; - } else - bdwrite(bp); - } - } - } - - return (0); -} diff --git a/sys/msdosfs/msdosfs_lookup.c b/sys/msdosfs/msdosfs_lookup.c deleted file mode 100644 index 776559d..0000000 --- a/sys/msdosfs/msdosfs_lookup.c +++ /dev/null @@ -1,1100 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: msdosfs_lookup.c,v 1.37 1997/11/17 15:36:54 ws Exp $ */ - -/*- - * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. - * Copyright (C) 1994, 1995, 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 - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/namei.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/vnode.h> -#include <sys/mount.h> - -#include <msdosfs/bpb.h> -#include <msdosfs/direntry.h> -#include <msdosfs/denode.h> -#include <msdosfs/msdosfsmount.h> -#include <msdosfs/fat.h> - -/* - * When we search a directory the blocks containing directory entries are - * read and examined. The directory entries contain information that would - * normally be in the inode of a unix filesystem. This means that some of - * a directory's contents may also be in memory resident denodes (sort of - * an inode). This can cause problems if we are searching while some other - * process is modifying a directory. To prevent one process from accessing - * incompletely modified directory information we depend upon being the - * sole owner of a directory block. bread/brelse provide this service. - * This being the case, when a process modifies a directory it must first - * acquire the disk block that contains the directory entry to be modified. - * Then update the disk block and the denode, and then write the disk block - * out to disk. This way disk blocks containing directory entries and in - * memory denode's will be in synch. - */ -int -msdosfs_lookup(ap) - struct vop_cachedlookup_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - } */ *ap; -{ - struct vnode *vdp = ap->a_dvp; - struct vnode **vpp = ap->a_vpp; - struct componentname *cnp = ap->a_cnp; - daddr_t bn; - int error; - int lockparent; - int wantparent; - int slotcount; - int slotoffset = 0; - int frcn; - u_long cluster; - int blkoff; - int diroff; - int blsize; - int isadir; /* ~0 if found direntry is a directory */ - u_long scn; /* starting cluster number */ - struct vnode *pdp; - struct denode *dp; - struct denode *tdp; - struct msdosfsmount *pmp; - struct buf *bp = 0; - struct direntry *dep = NULL; - u_char dosfilename[12]; - int flags = cnp->cn_flags; - int nameiop = cnp->cn_nameiop; - struct proc *p = cnp->cn_proc; - int unlen; - - int wincnt = 1; - int chksum = -1; - int olddos = 1; - cnp->cn_flags &= ~PDIRUNLOCK; - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): looking for %s\n", cnp->cn_nameptr); -#endif - dp = VTODE(vdp); - pmp = dp->de_pmp; - *vpp = NULL; - lockparent = flags & LOCKPARENT; - wantparent = flags & (LOCKPARENT | WANTPARENT); -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): vdp %p, dp %p, Attr %02x\n", - vdp, dp, dp->de_Attributes); -#endif - - /* - * If they are going after the . or .. entry in the root directory, - * they won't find it. DOS filesystems don't have them in the root - * directory. So, we fake it. deget() is in on this scam too. - */ - if ((vdp->v_flag & VROOT) && cnp->cn_nameptr[0] == '.' && - (cnp->cn_namelen == 1 || - (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) { - isadir = ATTR_DIRECTORY; - scn = MSDOSFSROOT; -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): looking for . or .. in root directory\n"); -#endif - cluster = MSDOSFSROOT; - blkoff = MSDOSFSROOT_OFS; - goto foundroot; - } - - switch (unix2dosfn((const u_char *)cnp->cn_nameptr, dosfilename, - cnp->cn_namelen, 0, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, pmp->pm_u2d, - pmp->pm_flags & MSDOSFSMNT_ULTABLE, pmp->pm_lu)) { - case 0: - return (EINVAL); - case 1: - break; - case 2: - wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen) + 1; - break; - case 3: - olddos = 0; - wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen) + 1; - break; - } - if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) { - wincnt = 1; - olddos = 1; - } - unlen = winLenFixup(cnp->cn_nameptr, cnp->cn_namelen); - - /* - * Suppress search for slots unless creating - * file and at end of pathname, in which case - * we watch for a place to put the new file in - * case it doesn't already exist. - */ - slotcount = wincnt; - if ((nameiop == CREATE || nameiop == RENAME) && - (flags & ISLASTCN)) - slotcount = 0; - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): dos version of filename %s, length %ld\n", - dosfilename, cnp->cn_namelen); -#endif - /* - * Search the directory pointed at by vdp for the name pointed at - * by cnp->cn_nameptr. - */ - tdp = NULL; - /* - * The outer loop ranges over the clusters that make up the - * directory. Note that the root directory is different from all - * other directories. It has a fixed number of blocks that are not - * part of the pool of allocatable clusters. So, we treat it a - * little differently. The root directory starts at "cluster" 0. - */ - diroff = 0; - for (frcn = 0;; frcn++) { - error = pcbmap(dp, frcn, &bn, &cluster, &blsize); - if (error) { - if (error == E2BIG) - break; - return (error); - } - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - for (blkoff = 0; blkoff < blsize; - blkoff += sizeof(struct direntry), - diroff += sizeof(struct direntry)) { - dep = (struct direntry *)(bp->b_data + blkoff); - /* - * If the slot is empty and we are still looking - * for an empty then remember this one. If the - * slot is not empty then check to see if it - * matches what we are looking for. If the slot - * has never been filled with anything, then the - * remainder of the directory has never been used, - * so there is no point in searching it. - */ - if (dep->deName[0] == SLOT_EMPTY || - dep->deName[0] == SLOT_DELETED) { - /* - * Drop memory of previous long matches - */ - chksum = -1; - - if (slotcount < wincnt) { - slotcount++; - slotoffset = diroff; - } - if (dep->deName[0] == SLOT_EMPTY) { - brelse(bp); - goto notfound; - } - } else { - /* - * If there wasn't enough space for our winentries, - * forget about the empty space - */ - if (slotcount < wincnt) - slotcount = 0; - - /* - * Check for Win95 long filename entry - */ - if (dep->deAttributes == ATTR_WIN95) { - if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) - continue; - - chksum = winChkName((const u_char *)cnp->cn_nameptr, - unlen, - (struct winentry *)dep, - chksum, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, - pmp->pm_u2w, - pmp->pm_flags & MSDOSFSMNT_ULTABLE, - pmp->pm_ul); - continue; - } - - /* - * Ignore volume labels (anywhere, not just - * the root directory). - */ - if (dep->deAttributes & ATTR_VOLUME) { - chksum = -1; - continue; - } - - /* - * Check for a checksum or name match - */ - if (chksum != winChksum(dep->deName) - && (!olddos || bcmp(dosfilename, dep->deName, 11))) { - chksum = -1; - continue; - } -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): match blkoff %d, diroff %d\n", - blkoff, diroff); -#endif - /* - * Remember where this directory - * entry came from for whoever did - * this lookup. - */ - dp->de_fndoffset = diroff; - dp->de_fndcnt = wincnt - 1; - - goto found; - } - } /* for (blkoff = 0; .... */ - /* - * Release the buffer holding the directory cluster just - * searched. - */ - brelse(bp); - } /* for (frcn = 0; ; frcn++) */ - -notfound: - /* - * We hold no disk buffers at this point. - */ - - /* - * Fixup the slot description to point to the place where - * we might put the new DOS direntry (putting the Win95 - * long name entries before that) - */ - if (!slotcount) { - slotcount = 1; - slotoffset = diroff; - } - if (wincnt > slotcount) - slotoffset += sizeof(struct direntry) * (wincnt - slotcount); - - /* - * If we get here we didn't find the entry we were looking for. But - * that's ok if we are creating or renaming and are at the end of - * the pathname and the directory hasn't been removed. - */ -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): op %d, refcnt %ld\n", - nameiop, dp->de_refcnt); - printf(" slotcount %d, slotoffset %d\n", - slotcount, slotoffset); -#endif - if ((nameiop == CREATE || nameiop == RENAME) && - (flags & ISLASTCN) && dp->de_refcnt != 0) { - /* - * Access for write is interpreted as allowing - * creation of files in the directory. - */ - error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_proc); - if (error) - return (error); - /* - * Return an indication of where the new directory - * entry should be put. - */ - dp->de_fndoffset = slotoffset; - dp->de_fndcnt = wincnt - 1; - - /* - * We return with the directory locked, so that - * the parameters we set up above will still be - * valid if we actually decide to do a direnter(). - * We return ni_vp == NULL to indicate that the entry - * does not currently exist; we leave a pointer to - * the (locked) directory inode in ndp->ni_dvp. - * The pathname buffer is saved so that the name - * can be obtained later. - * - * NB - if the directory is unlocked, then this - * information cannot be used. - */ - cnp->cn_flags |= SAVENAME; - if (!lockparent) { - VOP_UNLOCK(vdp, 0, p); - cnp->cn_flags |= PDIRUNLOCK; - } - return (EJUSTRETURN); - } - /* - * Insert name into cache (as non-existent) if appropriate. - */ - if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) - cache_enter(vdp, *vpp, cnp); - return (ENOENT); - -found: - /* - * NOTE: We still have the buffer with matched directory entry at - * this point. - */ - isadir = dep->deAttributes & ATTR_DIRECTORY; - scn = getushort(dep->deStartCluster); - if (FAT32(pmp)) { - scn |= getushort(dep->deHighClust) << 16; - if (scn == pmp->pm_rootdirblk) { - /* - * There should actually be 0 here. - * Just ignore the error. - */ - scn = MSDOSFSROOT; - } - } - - if (isadir) { - cluster = scn; - if (cluster == MSDOSFSROOT) - blkoff = MSDOSFSROOT_OFS; - else - blkoff = 0; - } else if (cluster == MSDOSFSROOT) - blkoff = diroff; - - /* - * Now release buf to allow deget to read the entry again. - * Reserving it here and giving it to deget could result - * in a deadlock. - */ - brelse(bp); - bp = 0; - -foundroot: - /* - * If we entered at foundroot, then we are looking for the . or .. - * entry of the filesystems root directory. isadir and scn were - * setup before jumping here. And, bp is already null. - */ - if (FAT32(pmp) && scn == MSDOSFSROOT) - scn = pmp->pm_rootdirblk; - - /* - * If deleting, and at end of pathname, return - * parameters which can be used to remove file. - * If the wantparent flag isn't set, we return only - * the directory (in ndp->ni_dvp), otherwise we go - * on and lock the inode, being careful with ".". - */ - if (nameiop == DELETE && (flags & ISLASTCN)) { - /* - * Don't allow deleting the root. - */ - if (blkoff == MSDOSFSROOT_OFS) - return EROFS; /* really? XXX */ - - /* - * Write access to directory required to delete files. - */ - error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_proc); - if (error) - return (error); - - /* - * Return pointer to current entry in dp->i_offset. - * Save directory inode pointer in ndp->ni_dvp for dirremove(). - */ - if (dp->de_StartCluster == scn && isadir) { /* "." */ - VREF(vdp); - *vpp = vdp; - return (0); - } - error = deget(pmp, cluster, blkoff, &tdp); - if (error) - return (error); - *vpp = DETOV(tdp); - if (!lockparent) { - VOP_UNLOCK(vdp, 0, p); - cnp->cn_flags |= PDIRUNLOCK; - } - return (0); - } - - /* - * If rewriting (RENAME), return the inode and the - * information required to rewrite the present directory - * Must get inode of directory entry to verify it's a - * regular file, or empty directory. - */ - if (nameiop == RENAME && wantparent && - (flags & ISLASTCN)) { - if (blkoff == MSDOSFSROOT_OFS) - return EROFS; /* really? XXX */ - - error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_proc); - if (error) - return (error); - - /* - * Careful about locking second inode. - * This can only occur if the target is ".". - */ - if (dp->de_StartCluster == scn && isadir) - return (EISDIR); - - if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0) - return (error); - *vpp = DETOV(tdp); - cnp->cn_flags |= SAVENAME; - if (!lockparent) { - VOP_UNLOCK(vdp, 0, p); - cnp->cn_flags |= PDIRUNLOCK; - } - return (0); - } - - /* - * Step through the translation in the name. We do not `vput' the - * directory because we may need it again if a symbolic link - * is relative to the current directory. Instead we save it - * unlocked as "pdp". We must get the target inode before unlocking - * the directory to insure that the inode will not be removed - * before we get it. We prevent deadlock by always fetching - * inodes from the root, moving down the directory tree. Thus - * when following backward pointers ".." we must unlock the - * parent directory before getting the requested directory. - * There is a potential race condition here if both the current - * and parent directories are removed before the VFS_VGET for the - * inode associated with ".." returns. We hope that this occurs - * infrequently since we cannot avoid this race condition without - * implementing a sophisticated deadlock detection algorithm. - * Note also that this simple deadlock detection scheme will not - * work if the file system has any hard links other than ".." - * that point backwards in the directory structure. - */ - pdp = vdp; - if (flags & ISDOTDOT) { - VOP_UNLOCK(pdp, 0, p); - cnp->cn_flags |= PDIRUNLOCK; - error = deget(pmp, cluster, blkoff, &tdp); - if (error) { - vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p); - cnp->cn_flags &= ~PDIRUNLOCK; - return (error); - } - if (lockparent && (flags & ISLASTCN)) { - error = vn_lock(pdp, LK_EXCLUSIVE, p); - if (error) { - vput(DETOV(tdp)); - return (error); - } - cnp->cn_flags &= ~PDIRUNLOCK; - } - *vpp = DETOV(tdp); - } else if (dp->de_StartCluster == scn && isadir) { - VREF(vdp); /* we want ourself, ie "." */ - *vpp = vdp; - } else { - if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0) - return (error); - if (!lockparent || !(flags & ISLASTCN)) { - VOP_UNLOCK(pdp, 0, p); - cnp->cn_flags |= PDIRUNLOCK; - } - *vpp = DETOV(tdp); - } - - /* - * Insert name into cache if appropriate. - */ - if (cnp->cn_flags & MAKEENTRY) - cache_enter(vdp, *vpp, cnp); - return (0); -} - -/* - * dep - directory entry to copy into the directory - * ddep - directory to add to - * depp - return the address of the denode for the created directory entry - * if depp != 0 - * cnp - componentname needed for Win95 long filenames - */ -int -createde(dep, ddep, depp, cnp) - struct denode *dep; - struct denode *ddep; - struct denode **depp; - struct componentname *cnp; -{ - int error; - u_long dirclust, diroffset; - struct direntry *ndep; - struct msdosfsmount *pmp = ddep->de_pmp; - struct buf *bp; - daddr_t bn; - int blsize; - -#ifdef MSDOSFS_DEBUG - printf("createde(dep %p, ddep %p, depp %p, cnp %p)\n", - dep, ddep, depp, cnp); -#endif - - /* - * If no space left in the directory then allocate another cluster - * and chain it onto the end of the file. There is one exception - * to this. That is, if the root directory has no more space it - * can NOT be expanded. extendfile() checks for and fails attempts - * to extend the root directory. We just return an error in that - * case. - */ - if (ddep->de_fndoffset >= ddep->de_FileSize) { - diroffset = ddep->de_fndoffset + sizeof(struct direntry) - - ddep->de_FileSize; - dirclust = de_clcount(pmp, diroffset); - error = extendfile(ddep, dirclust, 0, 0, DE_CLEAR); - if (error) { - (void)detrunc(ddep, ddep->de_FileSize, 0, NOCRED, NULL); - return error; - } - - /* - * Update the size of the directory - */ - ddep->de_FileSize += de_cn2off(pmp, dirclust); - } - - /* - * We just read in the cluster with space. Copy the new directory - * entry in. Then write it to disk. NOTE: DOS directories - * do not get smaller as clusters are emptied. - */ - error = pcbmap(ddep, de_cluster(pmp, ddep->de_fndoffset), - &bn, &dirclust, &blsize); - if (error) - return error; - diroffset = ddep->de_fndoffset; - if (dirclust != MSDOSFSROOT) - diroffset &= pmp->pm_crbomask; - if ((error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp)) != 0) { - brelse(bp); - return error; - } - ndep = bptoep(pmp, bp, ddep->de_fndoffset); - - DE_EXTERNALIZE(ndep, dep); - - /* - * Now write the Win95 long name - */ - if (ddep->de_fndcnt > 0) { - u_int8_t chksum = winChksum(ndep->deName); - const u_char *un = (const u_char *)cnp->cn_nameptr; - int unlen = cnp->cn_namelen; - int cnt = 1; - - while (--ddep->de_fndcnt >= 0) { - if (!(ddep->de_fndoffset & pmp->pm_crbomask)) { - if ((error = bwrite(bp)) != 0) - return error; - - ddep->de_fndoffset -= sizeof(struct direntry); - error = pcbmap(ddep, - de_cluster(pmp, - ddep->de_fndoffset), - &bn, 0, &blsize); - if (error) - return error; - - error = bread(pmp->pm_devvp, bn, blsize, - NOCRED, &bp); - if (error) { - brelse(bp); - return error; - } - ndep = bptoep(pmp, bp, ddep->de_fndoffset); - } else { - ndep--; - ddep->de_fndoffset -= sizeof(struct direntry); - } - if (!unix2winfn(un, unlen, (struct winentry *)ndep, - cnt++, chksum, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, - pmp->pm_u2w)) - break; - } - } - - if ((error = bwrite(bp)) != 0) - return error; - - /* - * If they want us to return with the denode gotten. - */ - if (depp) { - if (dep->de_Attributes & ATTR_DIRECTORY) { - dirclust = dep->de_StartCluster; - if (FAT32(pmp) && dirclust == pmp->pm_rootdirblk) - dirclust = MSDOSFSROOT; - if (dirclust == MSDOSFSROOT) - diroffset = MSDOSFSROOT_OFS; - else - diroffset = 0; - } - return deget(pmp, dirclust, diroffset, depp); - } - - return 0; -} - -/* - * Be sure a directory is empty except for "." and "..". Return 1 if empty, - * return 0 if not empty or error. - */ -int -dosdirempty(dep) - struct denode *dep; -{ - int blsize; - int error; - u_long cn; - daddr_t bn; - struct buf *bp; - struct msdosfsmount *pmp = dep->de_pmp; - struct direntry *dentp; - - /* - * Since the filesize field in directory entries for a directory is - * zero, we just have to feel our way through the directory until - * we hit end of file. - */ - for (cn = 0;; cn++) { - if ((error = pcbmap(dep, cn, &bn, 0, &blsize)) != 0) { - if (error == E2BIG) - return (1); /* it's empty */ - return (0); - } - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (0); - } - for (dentp = (struct direntry *)bp->b_data; - (char *)dentp < bp->b_data + blsize; - dentp++) { - if (dentp->deName[0] != SLOT_DELETED && - (dentp->deAttributes & ATTR_VOLUME) == 0) { - /* - * In dos directories an entry whose name - * starts with SLOT_EMPTY (0) starts the - * beginning of the unused part of the - * directory, so we can just return that it - * is empty. - */ - if (dentp->deName[0] == SLOT_EMPTY) { - brelse(bp); - return (1); - } - /* - * Any names other than "." and ".." in a - * directory mean it is not empty. - */ - if (bcmp(dentp->deName, ". ", 11) && - bcmp(dentp->deName, ".. ", 11)) { - brelse(bp); -#ifdef MSDOSFS_DEBUG - printf("dosdirempty(): entry found %02x, %02x\n", - dentp->deName[0], dentp->deName[1]); -#endif - return (0); /* not empty */ - } - } - } - brelse(bp); - } - /* NOTREACHED */ -} - -/* - * Check to see if the directory described by target is in some - * subdirectory of source. This prevents something like the following from - * succeeding and leaving a bunch or files and directories orphaned. mv - * /a/b/c /a/b/c/d/e/f Where c and f are directories. - * - * source - the inode for /a/b/c - * target - the inode for /a/b/c/d/e/f - * - * Returns 0 if target is NOT a subdirectory of source. - * Otherwise returns a non-zero error number. - * The target inode is always unlocked on return. - */ -int -doscheckpath(source, target) - struct denode *source; - struct denode *target; -{ - daddr_t scn; - struct msdosfsmount *pmp; - struct direntry *ep; - struct denode *dep; - struct buf *bp = NULL; - int error = 0; - - dep = target; - if ((target->de_Attributes & ATTR_DIRECTORY) == 0 || - (source->de_Attributes & ATTR_DIRECTORY) == 0) { - error = ENOTDIR; - goto out; - } - if (dep->de_StartCluster == source->de_StartCluster) { - error = EEXIST; - goto out; - } - if (dep->de_StartCluster == MSDOSFSROOT) - goto out; - pmp = dep->de_pmp; -#ifdef DIAGNOSTIC - if (pmp != source->de_pmp) - panic("doscheckpath: source and target on different filesystems"); -#endif - if (FAT32(pmp) && dep->de_StartCluster == pmp->pm_rootdirblk) - goto out; - - for (;;) { - if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) { - error = ENOTDIR; - break; - } - scn = dep->de_StartCluster; - error = bread(pmp->pm_devvp, cntobn(pmp, scn), - pmp->pm_bpcluster, NOCRED, &bp); - if (error) - break; - - ep = (struct direntry *) bp->b_data + 1; - if ((ep->deAttributes & ATTR_DIRECTORY) == 0 || - bcmp(ep->deName, ".. ", 11) != 0) { - error = ENOTDIR; - break; - } - scn = getushort(ep->deStartCluster); - if (FAT32(pmp)) - scn |= getushort(ep->deHighClust) << 16; - - if (scn == source->de_StartCluster) { - error = EINVAL; - break; - } - if (scn == MSDOSFSROOT) - break; - if (FAT32(pmp) && scn == pmp->pm_rootdirblk) { - /* - * scn should be 0 in this case, - * but we silently ignore the error. - */ - break; - } - - vput(DETOV(dep)); - brelse(bp); - bp = NULL; - /* NOTE: deget() clears dep on error */ - if ((error = deget(pmp, scn, 0, &dep)) != 0) - break; - } -out:; - if (bp) - brelse(bp); - if (error == ENOTDIR) - printf("doscheckpath(): .. not a directory?\n"); - if (dep != NULL) - vput(DETOV(dep)); - return (error); -} - -/* - * Read in the disk block containing the directory entry (dirclu, dirofs) - * and return the address of the buf header, and the address of the - * directory entry within the block. - */ -int -readep(pmp, dirclust, diroffset, bpp, epp) - struct msdosfsmount *pmp; - u_long dirclust, diroffset; - struct buf **bpp; - struct direntry **epp; -{ - int error; - daddr_t bn; - int blsize; - - blsize = pmp->pm_bpcluster; - if (dirclust == MSDOSFSROOT - && de_blk(pmp, diroffset + blsize) > pmp->pm_rootdirsize) - blsize = de_bn2off(pmp, pmp->pm_rootdirsize) & pmp->pm_crbomask; - bn = detobn(pmp, dirclust, diroffset); - if ((error = bread(pmp->pm_devvp, bn, blsize, NOCRED, bpp)) != 0) { - brelse(*bpp); - *bpp = NULL; - return (error); - } - if (epp) - *epp = bptoep(pmp, *bpp, diroffset); - return (0); -} - -/* - * Read in the disk block containing the directory entry dep came from and - * return the address of the buf header, and the address of the directory - * entry within the block. - */ -int -readde(dep, bpp, epp) - struct denode *dep; - struct buf **bpp; - struct direntry **epp; -{ - - return (readep(dep->de_pmp, dep->de_dirclust, dep->de_diroffset, - bpp, epp)); -} - -/* - * Remove a directory entry. At this point the file represented by the - * directory entry to be removed is still full length until noone has it - * open. When the file no longer being used msdosfs_inactive() is called - * and will truncate the file to 0 length. When the vnode containing the - * denode is needed for some other purpose by VFS it will call - * msdosfs_reclaim() which will remove the denode from the denode cache. - */ -int -removede(pdep, dep) - struct denode *pdep; /* directory where the entry is removed */ - struct denode *dep; /* file to be removed */ -{ - int error; - struct direntry *ep; - struct buf *bp; - daddr_t bn; - int blsize; - struct msdosfsmount *pmp = pdep->de_pmp; - u_long offset = pdep->de_fndoffset; - -#ifdef MSDOSFS_DEBUG - printf("removede(): filename %s, dep %p, offset %08lx\n", - dep->de_Name, dep, offset); -#endif - - dep->de_refcnt--; - offset += sizeof(struct direntry); - do { - offset -= sizeof(struct direntry); - error = pcbmap(pdep, de_cluster(pmp, offset), &bn, 0, &blsize); - if (error) - return error; - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); - if (error) { - brelse(bp); - return error; - } - ep = bptoep(pmp, bp, offset); - /* - * Check whether, if we came here the second time, i.e. - * when underflowing into the previous block, the last - * entry in this block is a longfilename entry, too. - */ - if (ep->deAttributes != ATTR_WIN95 - && offset != pdep->de_fndoffset) { - brelse(bp); - break; - } - offset += sizeof(struct direntry); - while (1) { - /* - * We are a bit agressive here in that we delete any Win95 - * entries preceding this entry, not just the ones we "own". - * Since these presumably aren't valid anyway, - * there should be no harm. - */ - offset -= sizeof(struct direntry); - ep--->deName[0] = SLOT_DELETED; - if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) - || !(offset & pmp->pm_crbomask) - || ep->deAttributes != ATTR_WIN95) - break; - } - if ((error = bwrite(bp)) != 0) - return error; - } while (!(pmp->pm_flags & MSDOSFSMNT_NOWIN95) - && !(offset & pmp->pm_crbomask) - && offset); - return 0; -} - -/* - * Create a unique DOS name in dvp - */ -int -uniqdosname(dep, cnp, cp) - struct denode *dep; - struct componentname *cnp; - u_char *cp; -{ - struct msdosfsmount *pmp = dep->de_pmp; - struct direntry *dentp; - int gen; - int blsize; - u_long cn; - daddr_t bn; - struct buf *bp; - int error; - - if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) - return (unix2dosfn((const u_char *)cnp->cn_nameptr, cp, - cnp->cn_namelen, 0, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, pmp->pm_u2d, - pmp->pm_flags & MSDOSFSMNT_ULTABLE, pmp->pm_lu) ? - 0 : EINVAL); - - for (gen = 1;; gen++) { - /* - * Generate DOS name with generation number - */ - if (!unix2dosfn((const u_char *)cnp->cn_nameptr, cp, - cnp->cn_namelen, gen, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, pmp->pm_u2d, - pmp->pm_flags & MSDOSFSMNT_ULTABLE, pmp->pm_lu)) - return gen == 1 ? EINVAL : EEXIST; - - /* - * Now look for a dir entry with this exact name - */ - for (cn = error = 0; !error; cn++) { - if ((error = pcbmap(dep, cn, &bn, 0, &blsize)) != 0) { - if (error == E2BIG) /* EOF reached and not found */ - return 0; - return error; - } - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); - if (error) { - brelse(bp); - return error; - } - for (dentp = (struct direntry *)bp->b_data; - (char *)dentp < bp->b_data + blsize; - dentp++) { - if (dentp->deName[0] == SLOT_EMPTY) { - /* - * Last used entry and not found - */ - brelse(bp); - return 0; - } - /* - * Ignore volume labels and Win95 entries - */ - if (dentp->deAttributes & ATTR_VOLUME) - continue; - if (!bcmp(dentp->deName, cp, 11)) { - error = EEXIST; - break; - } - } - brelse(bp); - } - } -} - -/* - * Find any Win'95 long filename entry in directory dep - */ -int -findwin95(dep) - struct denode *dep; -{ - struct msdosfsmount *pmp = dep->de_pmp; - struct direntry *dentp; - int blsize, win95; - u_long cn; - daddr_t bn; - struct buf *bp; - - win95 = 1; - /* - * Read through the directory looking for Win'95 entries - * Note: Error currently handled just as EOF XXX - */ - for (cn = 0;; cn++) { - if (pcbmap(dep, cn, &bn, 0, &blsize)) - return (win95); - if (bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp)) { - brelse(bp); - return (win95); - } - for (dentp = (struct direntry *)bp->b_data; - (char *)dentp < bp->b_data + blsize; - dentp++) { - if (dentp->deName[0] == SLOT_EMPTY) { - /* - * Last used entry and not found - */ - brelse(bp); - return (win95); - } - if (dentp->deName[0] == SLOT_DELETED) { - /* - * Ignore deleted files - * Note: might be an indication of Win'95 anyway XXX - */ - continue; - } - if (dentp->deAttributes == ATTR_WIN95) { - brelse(bp); - return 1; - } - win95 = 0; - } - brelse(bp); - } -} diff --git a/sys/msdosfs/msdosfs_vfsops.c b/sys/msdosfs/msdosfs_vfsops.c deleted file mode 100644 index abaeb7f..0000000 --- a/sys/msdosfs/msdosfs_vfsops.c +++ /dev/null @@ -1,964 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: msdosfs_vfsops.c,v 1.51 1997/11/17 15:36:58 ws Exp $ */ - -/*- - * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. - * Copyright (C) 1994, 1995, 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 - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/namei.h> -#include <sys/proc.h> -#include <sys/kernel.h> -#include <sys/vnode.h> -#include <sys/mount.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/fcntl.h> -#include <sys/malloc.h> -#include <sys/stat.h> /* defines ALLPERMS */ -#include <sys/mutex.h> - -#include <msdosfs/bpb.h> -#include <msdosfs/bootsect.h> -#include <msdosfs/direntry.h> -#include <msdosfs/denode.h> -#include <msdosfs/msdosfsmount.h> -#include <msdosfs/fat.h> - -#define MSDOSFS_DFLTBSIZE 4096 - -#if 1 /*def PC98*/ -/* - * XXX - The boot signature formatted by NEC PC-98 DOS looks like a - * garbage or a random value :-{ - * If you want to use that broken-signatured media, define the - * following symbol even though PC/AT. - * (ex. mount PC-98 DOS formatted FD on PC/AT) - */ -#define MSDOSFS_NOCHECKSIG -#endif - -MALLOC_DEFINE(M_MSDOSFSMNT, "MSDOSFS mount", "MSDOSFS mount structure"); -static MALLOC_DEFINE(M_MSDOSFSFAT, "MSDOSFS FAT", "MSDOSFS file allocation table"); - -static int update_mp __P((struct mount *mp, struct msdosfs_args *argp)); -static int mountmsdosfs __P((struct vnode *devvp, struct mount *mp, - struct proc *p, struct msdosfs_args *argp)); -static int msdosfs_fhtovp __P((struct mount *, struct fid *, - struct vnode **)); -static int msdosfs_mount __P((struct mount *, char *, caddr_t, - struct nameidata *, struct proc *)); -static int msdosfs_root __P((struct mount *, struct vnode **)); -static int msdosfs_statfs __P((struct mount *, struct statfs *, - struct proc *)); -static int msdosfs_sync __P((struct mount *, int, struct ucred *, - struct proc *)); -static int msdosfs_unmount __P((struct mount *, int, struct proc *)); -static int msdosfs_vptofh __P((struct vnode *, struct fid *)); - -static int -update_mp(mp, argp) - struct mount *mp; - struct msdosfs_args *argp; -{ - struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); - int error; - - pmp->pm_gid = argp->gid; - pmp->pm_uid = argp->uid; - pmp->pm_mask = argp->mask & ALLPERMS; - pmp->pm_flags |= argp->flags & MSDOSFSMNT_MNTOPT; - if (pmp->pm_flags & MSDOSFSMNT_U2WTABLE) { - bcopy(argp->u2w, pmp->pm_u2w, sizeof(pmp->pm_u2w)); - bcopy(argp->d2u, pmp->pm_d2u, sizeof(pmp->pm_d2u)); - bcopy(argp->u2d, pmp->pm_u2d, sizeof(pmp->pm_u2d)); - } - if (pmp->pm_flags & MSDOSFSMNT_ULTABLE) { - bcopy(argp->ul, pmp->pm_ul, sizeof(pmp->pm_ul)); - bcopy(argp->lu, pmp->pm_lu, sizeof(pmp->pm_lu)); - } - -#ifndef __FreeBSD__ - /* - * GEMDOS knows nothing (yet) about win95 - */ - if (pmp->pm_flags & MSDOSFSMNT_GEMDOSFS) - pmp->pm_flags |= MSDOSFSMNT_NOWIN95; -#endif - - if (pmp->pm_flags & MSDOSFSMNT_NOWIN95) - pmp->pm_flags |= MSDOSFSMNT_SHORTNAME; - else if (!(pmp->pm_flags & - (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) { - struct vnode *rootvp; - - /* - * Try to divine whether to support Win'95 long filenames - */ - if (FAT32(pmp)) - pmp->pm_flags |= MSDOSFSMNT_LONGNAME; - else { - if ((error = msdosfs_root(mp, &rootvp)) != 0) - return error; - pmp->pm_flags |= findwin95(VTODE(rootvp)) - ? MSDOSFSMNT_LONGNAME - : MSDOSFSMNT_SHORTNAME; - vput(rootvp); - } - } - return 0; -} - -#ifndef __FreeBSD__ -int -msdosfs_mountroot() -{ - register struct mount *mp; - struct proc *p = curproc; /* XXX */ - size_t size; - int error; - struct msdosfs_args args; - - if (root_device->dv_class != DV_DISK) - return (ENODEV); - - /* - * Get vnodes for swapdev and rootdev. - */ - if (bdevvp(rootdev, &rootvp)) - panic("msdosfs_mountroot: can't setup rootvp"); - - mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK | M_ZERO); - mp->mnt_op = &msdosfs_vfsops; - mp->mnt_flag = 0; - LIST_INIT(&mp->mnt_vnodelist); - - args.flags = 0; - args.uid = 0; - args.gid = 0; - args.mask = 0777; - - if ((error = mountmsdosfs(rootvp, mp, p, &args)) != 0) { - free(mp, M_MOUNT); - return (error); - } - - if ((error = update_mp(mp, &args)) != 0) { - (void)msdosfs_unmount(mp, 0, p); - free(mp, M_MOUNT); - return (error); - } - - if ((error = vfs_lock(mp)) != 0) { - (void)msdosfs_unmount(mp, 0, p); - free(mp, M_MOUNT); - return (error); - } - - TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); - mp->mnt_vnodecovered = NULLVP; - (void) copystr("/", mp->mnt_stat.f_mntonname, MNAMELEN - 1, - &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); - (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, - &size); - bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); - (void)msdosfs_statfs(mp, &mp->mnt_stat, p); - vfs_unlock(mp); - return (0); -} -#endif - -/* - * mp - path - addr in user space of mount point (ie /usr or whatever) - * data - addr in user space of mount params including the name of the block - * special file to treat as a filesystem. - */ -static int -msdosfs_mount(mp, path, data, ndp, p) - struct mount *mp; - char *path; - caddr_t data; - struct nameidata *ndp; - struct proc *p; -{ - struct vnode *devvp; /* vnode for blk device to mount */ - struct msdosfs_args args; /* will hold data from mount request */ - /* msdosfs specific mount control block */ - struct msdosfsmount *pmp = NULL; - size_t size; - int error, flags; - mode_t accessmode; - - error = copyin(data, (caddr_t)&args, sizeof(struct msdosfs_args)); - if (error) - return (error); - if (args.magic != MSDOSFS_ARGSMAGIC) - args.flags = 0; - /* - * If updating, check whether changing from read-only to - * read/write; if there is no device name, that's all we do. - */ - if (mp->mnt_flag & MNT_UPDATE) { - pmp = VFSTOMSDOSFS(mp); - error = 0; - if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_RDONLY)) { - flags = WRITECLOSE; - if (mp->mnt_flag & MNT_FORCE) - flags |= FORCECLOSE; - error = vflush(mp, 0, flags); - } - if (!error && (mp->mnt_flag & MNT_RELOAD)) - /* not yet implemented */ - error = EOPNOTSUPP; - if (error) - return (error); - if ((pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_kern_flag & MNTK_WANTRDWR)) { - /* - * If upgrade to read-write by non-root, then verify - * that user has necessary permissions on the device. - */ - if (p->p_ucred->cr_uid != 0) { - devvp = pmp->pm_devvp; - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); - error = VOP_ACCESS(devvp, VREAD | VWRITE, - p->p_ucred, p); - if (error) { - VOP_UNLOCK(devvp, 0, p); - return (error); - } - VOP_UNLOCK(devvp, 0, p); - } - pmp->pm_flags &= ~MSDOSFSMNT_RONLY; - } - if (args.fspec == 0) { -#ifdef __notyet__ /* doesn't work correctly with current mountd XXX */ - if (args.flags & MSDOSFSMNT_MNTOPT) { - pmp->pm_flags &= ~MSDOSFSMNT_MNTOPT; - pmp->pm_flags |= args.flags & MSDOSFSMNT_MNTOPT; - if (pmp->pm_flags & MSDOSFSMNT_NOWIN95) - pmp->pm_flags |= MSDOSFSMNT_SHORTNAME; - } -#endif - /* - * Process export requests. - */ - return (vfs_export(mp, &args.export)); - } - } - /* - * Not an update, or updating the name: look up the name - * and verify that it refers to a sensible block device. - */ - NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); - error = namei(ndp); - if (error) - return (error); - devvp = ndp->ni_vp; - NDFREE(ndp, NDF_ONLY_PNBUF); - - if (!vn_isdisk(devvp, &error)) { - vrele(devvp); - return (error); - } - /* - * If mount by non-root, then verify that user has necessary - * permissions on the device. - */ - if (p->p_ucred->cr_uid != 0) { - accessmode = VREAD; - if ((mp->mnt_flag & MNT_RDONLY) == 0) - accessmode |= VWRITE; - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); - error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p); - if (error) { - vput(devvp); - return (error); - } - VOP_UNLOCK(devvp, 0, p); - } - if ((mp->mnt_flag & MNT_UPDATE) == 0) { - error = mountmsdosfs(devvp, mp, p, &args); -#ifdef MSDOSFS_DEBUG /* only needed for the printf below */ - pmp = VFSTOMSDOSFS(mp); -#endif - } else { - if (devvp != pmp->pm_devvp) - error = EINVAL; /* XXX needs translation */ - else - vrele(devvp); - } - if (error) { - vrele(devvp); - return (error); - } - - error = update_mp(mp, &args); - if (error) { - msdosfs_unmount(mp, MNT_FORCE, p); - return error; - } - (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, - &size); - bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); - (void) msdosfs_statfs(mp, &mp->mnt_stat, p); -#ifdef MSDOSFS_DEBUG - printf("msdosfs_mount(): mp %p, pmp %p, inusemap %p\n", mp, pmp, pmp->pm_inusemap); -#endif - return (0); -} - -static int -mountmsdosfs(devvp, mp, p, argp) - struct vnode *devvp; - struct mount *mp; - struct proc *p; - struct msdosfs_args *argp; -{ - struct msdosfsmount *pmp; - struct buf *bp; - dev_t dev = devvp->v_rdev; -#ifndef __FreeBSD__ - struct partinfo dpart; - int bsize = 0, dtype = 0, tmp; -#endif - union bootsector *bsp; - struct byte_bpb33 *b33; - struct byte_bpb50 *b50; - struct byte_bpb710 *b710; - u_int8_t SecPerClust; - u_long clusters; - int ronly, error; - - /* - * Disallow multiple mounts of the same device. - * Disallow mounting of a device that is currently in use - * (except for root, which might share swap device for miniroot). - * Flush out any old buffers remaining from a previous use. - */ - error = vfs_mountedon(devvp); - if (error) - return (error); - if (vcount(devvp) > 1 && devvp != rootvp) - return (EBUSY); - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); - error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0); - VOP_UNLOCK(devvp, 0, p); - if (error) - return (error); - - ronly = (mp->mnt_flag & MNT_RDONLY) != 0; - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); - error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); - VOP_UNLOCK(devvp, 0, p); - if (error) - return (error); - - bp = NULL; /* both used in error_exit */ - pmp = NULL; - -#ifndef __FreeBSD__ - if (argp->flags & MSDOSFSMNT_GEMDOSFS) { - /* - * We need the disklabel to calculate the size of a FAT entry - * later on. Also make sure the partition contains a filesystem - * of type FS_MSDOS. This doesn't work for floppies, so we have - * to check for them too. - * - * At least some parts of the msdos fs driver seem to assume - * that the size of a disk block will always be 512 bytes. - * Let's check it... - */ - error = VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, - FREAD, NOCRED, p); - if (error) - goto error_exit; - tmp = dpart.part->p_fstype; - dtype = dpart.disklab->d_type; - bsize = dpart.disklab->d_secsize; - if (bsize != 512 || (dtype!=DTYPE_FLOPPY && tmp!=FS_MSDOS)) { - error = EINVAL; - goto error_exit; - } - } -#endif - - /* - * Read the boot sector of the filesystem, and then check the - * boot signature. If not a dos boot sector then error out. - * - * NOTE: 2048 is a maximum sector size in current... - */ - error = bread(devvp, 0, 2048, NOCRED, &bp); - if (error) - goto error_exit; - bp->b_flags |= B_AGE; - bsp = (union bootsector *)bp->b_data; - b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB; - b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB; - b710 = (struct byte_bpb710 *)bsp->bs710.bsPBP; - -#ifndef __FreeBSD__ - if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) { -#endif -#ifndef MSDOSFS_NOCHECKSIG - if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 - || bsp->bs50.bsBootSectSig1 != BOOTSIG1) { - error = EINVAL; - goto error_exit; - } -#endif -#ifndef __FreeBSD__ - } -#endif - - pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK | M_ZERO); - pmp->pm_mountp = mp; - - /* - * Compute several useful quantities from the bpb in the - * bootsector. Copy in the dos 5 variant of the bpb then fix up - * the fields that are different between dos 5 and dos 3.3. - */ - SecPerClust = b50->bpbSecPerClust; - pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec); - pmp->pm_ResSectors = getushort(b50->bpbResSectors); - pmp->pm_FATs = b50->bpbFATs; - pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts); - pmp->pm_Sectors = getushort(b50->bpbSectors); - pmp->pm_FATsecs = getushort(b50->bpbFATsecs); - pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack); - pmp->pm_Heads = getushort(b50->bpbHeads); - pmp->pm_Media = b50->bpbMedia; - - /* calculate the ratio of sector size to DEV_BSIZE */ - pmp->pm_BlkPerSec = pmp->pm_BytesPerSec / DEV_BSIZE; - -#ifndef __FreeBSD__ - if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) { -#endif - /* XXX - We should probably check more values here */ - if (!pmp->pm_BytesPerSec || !SecPerClust - || !pmp->pm_Heads || pmp->pm_Heads > 255 -#ifdef PC98 - || !pmp->pm_SecPerTrack || pmp->pm_SecPerTrack > 255) { -#else - || !pmp->pm_SecPerTrack || pmp->pm_SecPerTrack > 63) { -#endif - error = EINVAL; - goto error_exit; - } -#ifndef __FreeBSD__ - } -#endif - - if (pmp->pm_Sectors == 0) { - pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); - pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); - } else { - pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs); - pmp->pm_HugeSectors = pmp->pm_Sectors; - } - if (pmp->pm_HugeSectors > 0xffffffff / - (pmp->pm_BytesPerSec / sizeof(struct direntry)) + 1) { - /* - * We cannot deal currently with this size of disk - * due to fileid limitations (see msdosfs_getattr and - * msdosfs_readdir) - */ - error = EINVAL; - printf("mountmsdosfs(): disk too big, sorry\n"); - goto error_exit; - } - - if (pmp->pm_RootDirEnts == 0) { - if (bsp->bs710.bsBootSectSig2 != BOOTSIG2 - || bsp->bs710.bsBootSectSig3 != BOOTSIG3 - || pmp->pm_Sectors - || pmp->pm_FATsecs - || getushort(b710->bpbFSVers)) { - error = EINVAL; - printf("mountmsdosfs(): bad FAT32 filesystem\n"); - goto error_exit; - } - pmp->pm_fatmask = FAT32_MASK; - pmp->pm_fatmult = 4; - pmp->pm_fatdiv = 1; - pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs); - if (getushort(b710->bpbExtFlags) & FATMIRROR) - pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM; - else - pmp->pm_flags |= MSDOSFS_FATMIRROR; - } else - pmp->pm_flags |= MSDOSFS_FATMIRROR; - - /* - * Check a few values (could do some more): - * - logical sector size: power of 2, >= block size - * - sectors per cluster: power of 2, >= 1 - * - number of sectors: >= 1, <= size of partition - */ - if ( (SecPerClust == 0) - || (SecPerClust & (SecPerClust - 1)) - || (pmp->pm_BytesPerSec < DEV_BSIZE) - || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) - || (pmp->pm_HugeSectors == 0) - ) { - error = EINVAL; - goto error_exit; - } - - pmp->pm_HugeSectors *= pmp->pm_BlkPerSec; - pmp->pm_HiddenSects *= pmp->pm_BlkPerSec; /* XXX not used? */ - pmp->pm_FATsecs *= pmp->pm_BlkPerSec; - SecPerClust *= pmp->pm_BlkPerSec; - - pmp->pm_fatblk = pmp->pm_ResSectors * pmp->pm_BlkPerSec; - - if (FAT32(pmp)) { - pmp->pm_rootdirblk = getulong(b710->bpbRootClust); - pmp->pm_firstcluster = pmp->pm_fatblk - + (pmp->pm_FATs * pmp->pm_FATsecs); - pmp->pm_fsinfo = getushort(b710->bpbFSInfo) * pmp->pm_BlkPerSec; - } else { - pmp->pm_rootdirblk = pmp->pm_fatblk + - (pmp->pm_FATs * pmp->pm_FATsecs); - pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry) - + DEV_BSIZE - 1) - / DEV_BSIZE; /* in blocks */ - pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; - } - - pmp->pm_maxcluster = (pmp->pm_HugeSectors - pmp->pm_firstcluster) / - SecPerClust + 1; - pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE; /* XXX not used? */ - -#ifndef __FreeBSD__ - if (argp->flags & MSDOSFSMNT_GEMDOSFS) { - if ((pmp->pm_maxcluster <= (0xff0 - 2)) - && ((dtype == DTYPE_FLOPPY) || ((dtype == DTYPE_VNODE) - && ((pmp->pm_Heads == 1) || (pmp->pm_Heads == 2)))) - ) { - pmp->pm_fatmask = FAT12_MASK; - pmp->pm_fatmult = 3; - pmp->pm_fatdiv = 2; - } else { - pmp->pm_fatmask = FAT16_MASK; - pmp->pm_fatmult = 2; - pmp->pm_fatdiv = 1; - } - } else -#endif - if (pmp->pm_fatmask == 0) { - if (pmp->pm_maxcluster - <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) { - /* - * This will usually be a floppy disk. This size makes - * sure that one fat entry will not be split across - * multiple blocks. - */ - pmp->pm_fatmask = FAT12_MASK; - pmp->pm_fatmult = 3; - pmp->pm_fatdiv = 2; - } else { - pmp->pm_fatmask = FAT16_MASK; - pmp->pm_fatmult = 2; - pmp->pm_fatdiv = 1; - } - } - - clusters = (pmp->pm_fatsize / pmp->pm_fatmult) * pmp->pm_fatdiv; - if (pmp->pm_maxcluster >= clusters) { - printf("Warning: number of clusters (%ld) exceeds FAT " - "capacity (%ld)\n", pmp->pm_maxcluster + 1, clusters); - pmp->pm_maxcluster = clusters - 1; - } - - - if (FAT12(pmp)) - pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec; - else - pmp->pm_fatblocksize = MSDOSFS_DFLTBSIZE; - - pmp->pm_fatblocksec = pmp->pm_fatblocksize / DEV_BSIZE; - pmp->pm_bnshift = ffs(DEV_BSIZE) - 1; - - /* - * Compute mask and shift value for isolating cluster relative byte - * offsets and cluster numbers from a file offset. - */ - pmp->pm_bpcluster = SecPerClust * DEV_BSIZE; - pmp->pm_crbomask = pmp->pm_bpcluster - 1; - pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1; - - /* - * Check for valid cluster size - * must be a power of 2 - */ - if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) { - error = EINVAL; - goto error_exit; - } - - /* - * Release the bootsector buffer. - */ - brelse(bp); - bp = NULL; - - /* - * Check FSInfo. - */ - if (pmp->pm_fsinfo) { - struct fsinfo *fp; - - if ((error = bread(devvp, pmp->pm_fsinfo, fsi_size(pmp), - NOCRED, &bp)) != 0) - goto error_exit; - fp = (struct fsinfo *)bp->b_data; - if (!bcmp(fp->fsisig1, "RRaA", 4) - && !bcmp(fp->fsisig2, "rrAa", 4) - && !bcmp(fp->fsisig3, "\0\0\125\252", 4) - && !bcmp(fp->fsisig4, "\0\0\125\252", 4)) - pmp->pm_nxtfree = getulong(fp->fsinxtfree); - else - pmp->pm_fsinfo = 0; - brelse(bp); - bp = NULL; - } - - /* - * Check and validate (or perhaps invalidate?) the fsinfo structure? XXX - */ - - /* - * Allocate memory for the bitmap of allocated clusters, and then - * fill it in. - */ - pmp->pm_inusemap = malloc(((pmp->pm_maxcluster + N_INUSEBITS - 1) - / N_INUSEBITS) - * sizeof(*pmp->pm_inusemap), - M_MSDOSFSFAT, M_WAITOK); - - /* - * fillinusemap() needs pm_devvp. - */ - pmp->pm_dev = dev; - pmp->pm_devvp = devvp; - - /* - * Have the inuse map filled in. - */ - if ((error = fillinusemap(pmp)) != 0) - goto error_exit; - - /* - * If they want fat updates to be synchronous then let them suffer - * the performance degradation in exchange for the on disk copy of - * the fat being correct just about all the time. I suppose this - * would be a good thing to turn on if the kernel is still flakey. - */ - if (mp->mnt_flag & MNT_SYNCHRONOUS) - pmp->pm_flags |= MSDOSFSMNT_WAITONFAT; - - /* - * Finish up. - */ - if (ronly) - pmp->pm_flags |= MSDOSFSMNT_RONLY; - else - pmp->pm_fmod = 1; - mp->mnt_data = (qaddr_t) pmp; - mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); - mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; - mp->mnt_flag |= MNT_LOCAL; - devvp->v_rdev->si_mountpoint = mp; - - return 0; - -error_exit: - if (bp) - brelse(bp); - (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD | FWRITE, NOCRED, p); - if (pmp) { - if (pmp->pm_inusemap) - free(pmp->pm_inusemap, M_MSDOSFSFAT); - free(pmp, M_MSDOSFSMNT); - mp->mnt_data = (qaddr_t)0; - } - return (error); -} - -/* - * Unmount the filesystem described by mp. - */ -static int -msdosfs_unmount(mp, mntflags, p) - struct mount *mp; - int mntflags; - struct proc *p; -{ - struct msdosfsmount *pmp; - int error, flags; - - flags = 0; - if (mntflags & MNT_FORCE) - flags |= FORCECLOSE; - error = vflush(mp, 0, flags); - if (error) - return error; - pmp = VFSTOMSDOSFS(mp); - pmp->pm_devvp->v_rdev->si_mountpoint = NULL; -#ifdef MSDOSFS_DEBUG - { - struct vnode *vp = pmp->pm_devvp; - - printf("msdosfs_umount(): just before calling VOP_CLOSE()\n"); - printf("flag %08lx, usecount %d, writecount %d, holdcnt %ld\n", - vp->v_flag, vp->v_usecount, vp->v_writecount, vp->v_holdcnt); - printf("id %lu, mount %p, op %p\n", - vp->v_id, vp->v_mount, vp->v_op); - printf("freef %p, freeb %p, mount %p\n", - TAILQ_NEXT(vp, v_freelist), vp->v_freelist.tqe_prev, - vp->v_mount); - printf("cleanblkhd %p, dirtyblkhd %p, numoutput %ld, type %d\n", - TAILQ_FIRST(&vp->v_cleanblkhd), - TAILQ_FIRST(&vp->v_dirtyblkhd), - vp->v_numoutput, vp->v_type); - printf("union %p, tag %d, data[0] %08x, data[1] %08x\n", - vp->v_socket, vp->v_tag, - ((u_int *)vp->v_data)[0], - ((u_int *)vp->v_data)[1]); - } -#endif - error = VOP_CLOSE(pmp->pm_devvp, - (pmp->pm_flags&MSDOSFSMNT_RONLY) ? FREAD : FREAD | FWRITE, - NOCRED, p); - vrele(pmp->pm_devvp); - free(pmp->pm_inusemap, M_MSDOSFSFAT); - free(pmp, M_MSDOSFSMNT); - mp->mnt_data = (qaddr_t)0; - mp->mnt_flag &= ~MNT_LOCAL; - return (error); -} - -static int -msdosfs_root(mp, vpp) - struct mount *mp; - struct vnode **vpp; -{ - struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); - struct denode *ndep; - int error; - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_root(); mp %p, pmp %p\n", mp, pmp); -#endif - error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, &ndep); - if (error) - return (error); - *vpp = DETOV(ndep); - return (0); -} - -static int -msdosfs_statfs(mp, sbp, p) - struct mount *mp; - struct statfs *sbp; - struct proc *p; -{ - struct msdosfsmount *pmp; - - pmp = VFSTOMSDOSFS(mp); - sbp->f_bsize = pmp->pm_bpcluster; - sbp->f_iosize = pmp->pm_bpcluster; - sbp->f_blocks = pmp->pm_maxcluster + 1; - sbp->f_bfree = pmp->pm_freeclustercount; - sbp->f_bavail = pmp->pm_freeclustercount; - sbp->f_files = pmp->pm_RootDirEnts; /* XXX */ - sbp->f_ffree = 0; /* what to put in here? */ - if (sbp != &mp->mnt_stat) { - sbp->f_type = mp->mnt_vfc->vfc_typenum; - bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); - bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); - } - strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN); - return (0); -} - -static int -msdosfs_sync(mp, waitfor, cred, p) - struct mount *mp; - int waitfor; - struct ucred *cred; - struct proc *p; -{ - struct vnode *vp, *nvp; - struct denode *dep; - struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); - int error, allerror = 0; - - /* - * If we ever switch to not updating all of the fats all the time, - * this would be the place to update them from the first one. - */ - if (pmp->pm_fmod != 0) { - if (pmp->pm_flags & MSDOSFSMNT_RONLY) - panic("msdosfs_sync: rofs mod"); - else { - /* update fats here */ - } - } - /* - * Write back each (modified) denode. - */ - mtx_lock(&mntvnode_mtx); -loop: - for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nvp) { - /* - * If the vnode that we are about to sync is no longer - * associated with this mount point, start over. - */ - if (vp->v_mount != mp) - goto loop; - - mtx_lock(&vp->v_interlock); - nvp = LIST_NEXT(vp, v_mntvnodes); - dep = VTODE(vp); - if (vp->v_type == VNON || - ((dep->de_flag & - (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0 && - (TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY))) { - mtx_unlock(&vp->v_interlock); - continue; - } - mtx_unlock(&mntvnode_mtx); - error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p); - if (error) { - mtx_lock(&mntvnode_mtx); - if (error == ENOENT) - goto loop; - continue; - } - error = VOP_FSYNC(vp, cred, waitfor, p); - if (error) - allerror = error; - VOP_UNLOCK(vp, 0, p); - vrele(vp); - mtx_lock(&mntvnode_mtx); - } - mtx_unlock(&mntvnode_mtx); - - /* - * Flush filesystem control info. - */ - if (waitfor != MNT_LAZY) { - vn_lock(pmp->pm_devvp, LK_EXCLUSIVE | LK_RETRY, p); - error = VOP_FSYNC(pmp->pm_devvp, cred, waitfor, p); - if (error) - allerror = error; - VOP_UNLOCK(pmp->pm_devvp, 0, p); - } - return (allerror); -} - -static int -msdosfs_fhtovp(mp, fhp, vpp) - struct mount *mp; - struct fid *fhp; - struct vnode **vpp; -{ - struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); - struct defid *defhp = (struct defid *) fhp; - struct denode *dep; - int error; - - error = deget(pmp, defhp->defid_dirclust, defhp->defid_dirofs, &dep); - if (error) { - *vpp = NULLVP; - return (error); - } - *vpp = DETOV(dep); - return (0); -} - -static int -msdosfs_vptofh(vp, fhp) - struct vnode *vp; - struct fid *fhp; -{ - struct denode *dep; - struct defid *defhp; - - dep = VTODE(vp); - defhp = (struct defid *)fhp; - defhp->defid_len = sizeof(struct defid); - defhp->defid_dirclust = dep->de_dirclust; - defhp->defid_dirofs = dep->de_diroffset; - /* defhp->defid_gen = dep->de_gen; */ - return (0); -} - -static struct vfsops msdosfs_vfsops = { - msdosfs_mount, - vfs_stdstart, - msdosfs_unmount, - msdosfs_root, - vfs_stdquotactl, - msdosfs_statfs, - msdosfs_sync, - vfs_stdvget, - msdosfs_fhtovp, - vfs_stdcheckexp, - msdosfs_vptofh, - msdosfs_init, - msdosfs_uninit, - vfs_stdextattrctl, -}; - -VFS_SET(msdosfs_vfsops, msdos, 0); diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c deleted file mode 100644 index b942d30..0000000 --- a/sys/msdosfs/msdosfs_vnops.c +++ /dev/null @@ -1,1905 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: msdosfs_vnops.c,v 1.68 1998/02/10 14:10:04 mrg Exp $ */ - -/*- - * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. - * Copyright (C) 1994, 1995, 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 - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/namei.h> -#include <sys/resourcevar.h> /* defines plimit structure in proc struct */ -#include <sys/kernel.h> -#include <sys/stat.h> -#include <sys/bio.h> -#include <sys/buf.h> -#include <sys/proc.h> -#include <sys/mount.h> -#include <sys/unistd.h> -#include <sys/vnode.h> -#include <sys/malloc.h> -#include <sys/dirent.h> -#include <sys/signalvar.h> - -#include <vm/vm.h> -#include <vm/vm_extern.h> -#include <vm/vnode_pager.h> - -#include <machine/mutex.h> - -#include <msdosfs/bpb.h> -#include <msdosfs/direntry.h> -#include <msdosfs/denode.h> -#include <msdosfs/msdosfsmount.h> -#include <msdosfs/fat.h> - -#define DOS_FILESIZE_MAX 0xffffffff - -/* - * Prototypes for MSDOSFS vnode operations - */ -static int msdosfs_create __P((struct vop_create_args *)); -static int msdosfs_mknod __P((struct vop_mknod_args *)); -static int msdosfs_close __P((struct vop_close_args *)); -static int msdosfs_access __P((struct vop_access_args *)); -static int msdosfs_getattr __P((struct vop_getattr_args *)); -static int msdosfs_setattr __P((struct vop_setattr_args *)); -static int msdosfs_read __P((struct vop_read_args *)); -static int msdosfs_write __P((struct vop_write_args *)); -static int msdosfs_fsync __P((struct vop_fsync_args *)); -static int msdosfs_remove __P((struct vop_remove_args *)); -static int msdosfs_link __P((struct vop_link_args *)); -static int msdosfs_rename __P((struct vop_rename_args *)); -static int msdosfs_mkdir __P((struct vop_mkdir_args *)); -static int msdosfs_rmdir __P((struct vop_rmdir_args *)); -static int msdosfs_symlink __P((struct vop_symlink_args *)); -static int msdosfs_readdir __P((struct vop_readdir_args *)); -static int msdosfs_bmap __P((struct vop_bmap_args *)); -static int msdosfs_strategy __P((struct vop_strategy_args *)); -static int msdosfs_print __P((struct vop_print_args *)); -static int msdosfs_pathconf __P((struct vop_pathconf_args *ap)); - -/* - * Some general notes: - * - * In the ufs filesystem the inodes, superblocks, and indirect blocks are - * read/written using the vnode for the filesystem. Blocks that represent - * the contents of a file are read/written using the vnode for the file - * (including directories when they are read/written as files). This - * presents problems for the dos filesystem because data that should be in - * an inode (if dos had them) resides in the directory itself. Since we - * must update directory entries without the benefit of having the vnode - * for the directory we must use the vnode for the filesystem. This means - * that when a directory is actually read/written (via read, write, or - * readdir, or seek) we must use the vnode for the filesystem instead of - * the vnode for the directory as would happen in ufs. This is to insure we - * retreive the correct block from the buffer cache since the hash value is - * based upon the vnode address and the desired block number. - */ - -/* - * Create a regular file. On entry the directory to contain the file being - * created is locked. We must release before we return. We must also free - * the pathname buffer pointed at by cnp->cn_pnbuf, always on error, or - * only if the SAVESTART bit in cn_flags is clear on success. - */ -static int -msdosfs_create(ap) - struct vop_create_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - } */ *ap; -{ - struct componentname *cnp = ap->a_cnp; - struct denode ndirent; - struct denode *dep; - struct denode *pdep = VTODE(ap->a_dvp); - struct timespec ts; - int error; - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_create(cnp %p, vap %p\n", cnp, ap->a_vap); -#endif - - /* - * If this is the root directory and there is no space left we - * can't do anything. This is because the root directory can not - * change size. - */ - if (pdep->de_StartCluster == MSDOSFSROOT - && pdep->de_fndoffset >= pdep->de_FileSize) { - error = ENOSPC; - goto bad; - } - - /* - * Create a directory entry for the file, then call createde() to - * have it installed. NOTE: DOS files are always executable. We - * use the absence of the owner write bit to make the file - * readonly. - */ -#ifdef DIAGNOSTIC - if ((cnp->cn_flags & HASBUF) == 0) - panic("msdosfs_create: no name"); -#endif - bzero(&ndirent, sizeof(ndirent)); - error = uniqdosname(pdep, cnp, ndirent.de_Name); - if (error) - goto bad; - - ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE) ? - ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY; - ndirent.de_LowerCase = 0; - ndirent.de_StartCluster = 0; - ndirent.de_FileSize = 0; - ndirent.de_dev = pdep->de_dev; - ndirent.de_devvp = pdep->de_devvp; - ndirent.de_pmp = pdep->de_pmp; - ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE; - getnanotime(&ts); - DETIMES(&ndirent, &ts, &ts, &ts); - error = createde(&ndirent, pdep, &dep, cnp); - if (error) - goto bad; - *ap->a_vpp = DETOV(dep); - return (0); - -bad: - return (error); -} - -static int -msdosfs_mknod(ap) - struct vop_mknod_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - } */ *ap; -{ - - switch (ap->a_vap->va_type) { - case VDIR: - return (msdosfs_mkdir((struct vop_mkdir_args *)ap)); - break; - - case VREG: - return (msdosfs_create((struct vop_create_args *)ap)); - break; - - default: - return (EINVAL); - } - /* NOTREACHED */ -} - -static int -msdosfs_close(ap) - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct denode *dep = VTODE(vp); - struct timespec ts; - - mtx_lock(&vp->v_interlock); - if (vp->v_usecount > 1) { - getnanotime(&ts); - DETIMES(dep, &ts, &ts, &ts); - } - mtx_unlock(&vp->v_interlock); - return 0; -} - -static int -msdosfs_access(ap) - struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct denode *dep = VTODE(ap->a_vp); - struct msdosfsmount *pmp = dep->de_pmp; - mode_t file_mode, mode = ap->a_mode; - - file_mode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) | - ((dep->de_Attributes & ATTR_READONLY) ? 0 : (S_IWUSR|S_IWGRP|S_IWOTH)); - file_mode &= pmp->pm_mask; - - /* - * Disallow write attempts on read-only file systems; - * unless the file is a socket, fifo, or a block or - * character device resident on the file system. - */ - if (mode & VWRITE) { - switch (vp->v_type) { - case VDIR: - case VLNK: - case VREG: - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - break; - default: - break; - } - } - - return (vaccess(vp->v_type, file_mode, pmp->pm_uid, pmp->pm_gid, - ap->a_mode, ap->a_cred, NULL)); -} - -static int -msdosfs_getattr(ap) - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct denode *dep = VTODE(ap->a_vp); - struct msdosfsmount *pmp = dep->de_pmp; - struct vattr *vap = ap->a_vap; - mode_t mode; - struct timespec ts; - u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); - u_long fileid; - - getnanotime(&ts); - DETIMES(dep, &ts, &ts, &ts); - vap->va_fsid = dev2udev(dep->de_dev); - /* - * The following computation of the fileid must be the same as that - * used in msdosfs_readdir() to compute d_fileno. If not, pwd - * doesn't work. - */ - if (dep->de_Attributes & ATTR_DIRECTORY) { - fileid = cntobn(pmp, dep->de_StartCluster) * dirsperblk; - if (dep->de_StartCluster == MSDOSFSROOT) - fileid = 1; - } else { - fileid = cntobn(pmp, dep->de_dirclust) * dirsperblk; - if (dep->de_dirclust == MSDOSFSROOT) - fileid = roottobn(pmp, 0) * dirsperblk; - fileid += dep->de_diroffset / sizeof(struct direntry); - } - vap->va_fileid = fileid; - if ((dep->de_Attributes & ATTR_READONLY) == 0) - mode = S_IRWXU|S_IRWXG|S_IRWXO; - else - mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; - vap->va_mode = mode & pmp->pm_mask; - vap->va_uid = pmp->pm_uid; - vap->va_gid = pmp->pm_gid; - vap->va_nlink = 1; - vap->va_rdev = 0; - vap->va_size = dep->de_FileSize; - dos2unixtime(dep->de_MDate, dep->de_MTime, 0, &vap->va_mtime); - if (pmp->pm_flags & MSDOSFSMNT_LONGNAME) { - dos2unixtime(dep->de_ADate, 0, 0, &vap->va_atime); - dos2unixtime(dep->de_CDate, dep->de_CTime, dep->de_CHun, &vap->va_ctime); - } else { - vap->va_atime = vap->va_mtime; - vap->va_ctime = vap->va_mtime; - } - vap->va_flags = 0; - if ((dep->de_Attributes & ATTR_ARCHIVE) == 0) - vap->va_flags |= SF_ARCHIVED; - vap->va_gen = 0; - vap->va_blocksize = pmp->pm_bpcluster; - vap->va_bytes = - (dep->de_FileSize + pmp->pm_crbomask) & ~pmp->pm_crbomask; - vap->va_type = ap->a_vp->v_type; - vap->va_filerev = dep->de_modrev; - return (0); -} - -static int -msdosfs_setattr(ap) - struct vop_setattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct denode *dep = VTODE(ap->a_vp); - struct msdosfsmount *pmp = dep->de_pmp; - struct vattr *vap = ap->a_vap; - struct ucred *cred = ap->a_cred; - int error = 0; - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_setattr(): vp %p, vap %p, cred %p, p %p\n", - ap->a_vp, vap, cred, ap->a_p); -#endif - - /* - * Check for unsettable attributes. - */ - if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || - (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || - (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || - (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { -#ifdef MSDOSFS_DEBUG - printf("msdosfs_setattr(): returning EINVAL\n"); - printf(" va_type %d, va_nlink %x, va_fsid %lx, va_fileid %lx\n", - vap->va_type, vap->va_nlink, vap->va_fsid, vap->va_fileid); - printf(" va_blocksize %lx, va_rdev %x, va_bytes %qx, va_gen %lx\n", - vap->va_blocksize, vap->va_rdev, vap->va_bytes, vap->va_gen); - printf(" va_uid %x, va_gid %x\n", - vap->va_uid, vap->va_gid); -#endif - return (EINVAL); - } - if (vap->va_flags != VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - if (cred->cr_uid != pmp->pm_uid && - (error = suser_xxx(cred, ap->a_p, PRISON_ROOT))) - return (error); - /* - * We are very inconsistent about handling unsupported - * attributes. We ignored the access time and the - * read and execute bits. We were strict for the other - * attributes. - * - * Here we are strict, stricter than ufs in not allowing - * users to attempt to set SF_SETTABLE bits or anyone to - * set unsupported bits. However, we ignore attempts to - * set ATTR_ARCHIVE for directories `cp -pr' from a more - * sensible file system attempts it a lot. - */ - if (cred->cr_uid != 0) { - if (vap->va_flags & SF_SETTABLE) - return EPERM; - } - if (vap->va_flags & ~SF_ARCHIVED) - return EOPNOTSUPP; - if (vap->va_flags & SF_ARCHIVED) - dep->de_Attributes &= ~ATTR_ARCHIVE; - else if (!(dep->de_Attributes & ATTR_DIRECTORY)) - dep->de_Attributes |= ATTR_ARCHIVE; - dep->de_flag |= DE_MODIFIED; - } - - if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { - uid_t uid; - gid_t gid; - - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - uid = vap->va_uid; - if (uid == (uid_t)VNOVAL) - uid = pmp->pm_uid; - gid = vap->va_gid; - if (gid == (gid_t)VNOVAL) - gid = pmp->pm_gid; - if ((cred->cr_uid != pmp->pm_uid || uid != pmp->pm_uid || - (gid != pmp->pm_gid && !groupmember(gid, cred))) && - (error = suser_xxx(cred, ap->a_p, PRISON_ROOT))) - return error; - if (uid != pmp->pm_uid || gid != pmp->pm_gid) - return EINVAL; - } - - if (vap->va_size != VNOVAL) { - /* - * Disallow write attempts on read-only file systems; - * unless the file is a socket, fifo, or a block or - * character device resident on the file system. - */ - switch (vp->v_type) { - case VDIR: - return (EISDIR); - /* NOT REACHED */ - case VLNK: - case VREG: - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - break; - default: - break; - } - error = detrunc(dep, vap->va_size, 0, cred, ap->a_p); - if (error) - return error; - } - if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - if (cred->cr_uid != pmp->pm_uid && - (error = suser_xxx(cred, ap->a_p, PRISON_ROOT)) && - ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(ap->a_vp, VWRITE, cred, ap->a_p)))) - return (error); - if (vp->v_type != VDIR) { - if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && - vap->va_atime.tv_sec != VNOVAL) - unix2dostime(&vap->va_atime, &dep->de_ADate, NULL, NULL); - if (vap->va_mtime.tv_sec != VNOVAL) - unix2dostime(&vap->va_mtime, &dep->de_MDate, &dep->de_MTime, NULL); - dep->de_Attributes |= ATTR_ARCHIVE; - dep->de_flag |= DE_MODIFIED; - } - } - /* - * DOS files only have the ability to have their writability - * attribute set, so we use the owner write bit to set the readonly - * attribute. - */ - if (vap->va_mode != (mode_t)VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - if (cred->cr_uid != pmp->pm_uid && - (error = suser_xxx(cred, ap->a_p, PRISON_ROOT))) - return (error); - if (vp->v_type != VDIR) { - /* We ignore the read and execute bits. */ - if (vap->va_mode & VWRITE) - dep->de_Attributes &= ~ATTR_READONLY; - else - dep->de_Attributes |= ATTR_READONLY; - dep->de_flag |= DE_MODIFIED; - } - } - return (deupdat(dep, 1)); -} - -static int -msdosfs_read(ap) - struct vop_read_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap; -{ - int error = 0; - int blsize; - int isadir; - int orig_resid; - u_int n; - u_long diff; - u_long on; - daddr_t lbn; - daddr_t rablock; - int rasize; - int seqcount; - struct buf *bp; - struct vnode *vp = ap->a_vp; - struct denode *dep = VTODE(vp); - struct msdosfsmount *pmp = dep->de_pmp; - struct uio *uio = ap->a_uio; - - if (uio->uio_offset < 0) - return (EINVAL); - - if ((uoff_t)uio->uio_offset > DOS_FILESIZE_MAX) - return (0); - /* - * If they didn't ask for any data, then we are done. - */ - orig_resid = uio->uio_resid; - if (orig_resid <= 0) - return (0); - - seqcount = ap->a_ioflag >> 16; - - isadir = dep->de_Attributes & ATTR_DIRECTORY; - do { - if (uio->uio_offset >= dep->de_FileSize) - break; - lbn = de_cluster(pmp, uio->uio_offset); - /* - * If we are operating on a directory file then be sure to - * do i/o with the vnode for the filesystem instead of the - * vnode for the directory. - */ - if (isadir) { - /* convert cluster # to block # */ - error = pcbmap(dep, lbn, &lbn, 0, &blsize); - if (error == E2BIG) { - error = EINVAL; - break; - } else if (error) - break; - error = bread(pmp->pm_devvp, lbn, blsize, NOCRED, &bp); - } else { - blsize = pmp->pm_bpcluster; - rablock = lbn + 1; - if (seqcount > 1 && - de_cn2off(pmp, rablock) < dep->de_FileSize) { - rasize = pmp->pm_bpcluster; - error = breadn(vp, lbn, blsize, - &rablock, &rasize, 1, NOCRED, &bp); - } else { - error = bread(vp, lbn, blsize, NOCRED, &bp); - } - } - if (error) { - brelse(bp); - break; - } - on = uio->uio_offset & pmp->pm_crbomask; - diff = pmp->pm_bpcluster - on; - n = diff > uio->uio_resid ? uio->uio_resid : diff; - diff = dep->de_FileSize - uio->uio_offset; - if (diff < n) - n = diff; - diff = blsize - bp->b_resid; - if (diff < n) - n = diff; - error = uiomove(bp->b_data + on, (int) n, uio); - brelse(bp); - } while (error == 0 && uio->uio_resid > 0 && n != 0); - if (!isadir && (error == 0 || uio->uio_resid != orig_resid) && - (vp->v_mount->mnt_flag & MNT_NOATIME) == 0) - dep->de_flag |= DE_ACCESS; - return (error); -} - -/* - * Write data to a file or directory. - */ -static int -msdosfs_write(ap) - struct vop_write_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap; -{ - int n; - int croffset; - int resid; - u_long osize; - int error = 0; - u_long count; - daddr_t bn, lastcn; - struct buf *bp; - int ioflag = ap->a_ioflag; - struct uio *uio = ap->a_uio; - struct proc *p = uio->uio_procp; - struct vnode *vp = ap->a_vp; - struct vnode *thisvp; - struct denode *dep = VTODE(vp); - struct msdosfsmount *pmp = dep->de_pmp; - struct ucred *cred = ap->a_cred; - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_write(vp %p, uio %p, ioflag %x, cred %p\n", - vp, uio, ioflag, cred); - printf("msdosfs_write(): diroff %lu, dirclust %lu, startcluster %lu\n", - dep->de_diroffset, dep->de_dirclust, dep->de_StartCluster); -#endif - - switch (vp->v_type) { - case VREG: - if (ioflag & IO_APPEND) - uio->uio_offset = dep->de_FileSize; - thisvp = vp; - break; - case VDIR: - return EISDIR; - default: - panic("msdosfs_write(): bad file type"); - } - - if (uio->uio_offset < 0) - return (EFBIG); - - if (uio->uio_resid == 0) - return (0); - - /* - * If they've exceeded their filesize limit, tell them about it. - */ - if (p && - ((uoff_t)uio->uio_offset + uio->uio_resid > - p->p_rlimit[RLIMIT_FSIZE].rlim_cur)) { - PROC_LOCK(p); - psignal(p, SIGXFSZ); - PROC_UNLOCK(p); - return (EFBIG); - } - - if ((uoff_t)uio->uio_offset + uio->uio_resid > DOS_FILESIZE_MAX) - return (EFBIG); - - /* - * If the offset we are starting the write at is beyond the end of - * the file, then they've done a seek. Unix filesystems allow - * files with holes in them, DOS doesn't so we must fill the hole - * with zeroed blocks. - */ - if (uio->uio_offset > dep->de_FileSize) { - error = deextend(dep, uio->uio_offset, cred); - if (error) - return (error); - } - - /* - * Remember some values in case the write fails. - */ - resid = uio->uio_resid; - osize = dep->de_FileSize; - - /* - * If we write beyond the end of the file, extend it to its ultimate - * size ahead of the time to hopefully get a contiguous area. - */ - if (uio->uio_offset + resid > osize) { - count = de_clcount(pmp, uio->uio_offset + resid) - - de_clcount(pmp, osize); - error = extendfile(dep, count, NULL, NULL, 0); - if (error && (error != ENOSPC || (ioflag & IO_UNIT))) - goto errexit; - lastcn = dep->de_fc[FC_LASTFC].fc_frcn; - } else - lastcn = de_clcount(pmp, osize) - 1; - - do { - if (de_cluster(pmp, uio->uio_offset) > lastcn) { - error = ENOSPC; - break; - } - - croffset = uio->uio_offset & pmp->pm_crbomask; - n = min(uio->uio_resid, pmp->pm_bpcluster - croffset); - if (uio->uio_offset + n > dep->de_FileSize) { - dep->de_FileSize = uio->uio_offset + n; - /* The object size needs to be set before buffer is allocated */ - vnode_pager_setsize(vp, dep->de_FileSize); - } - - bn = de_cluster(pmp, uio->uio_offset); - if ((uio->uio_offset & pmp->pm_crbomask) == 0 - && (de_cluster(pmp, uio->uio_offset + uio->uio_resid) - > de_cluster(pmp, uio->uio_offset) - || uio->uio_offset + uio->uio_resid >= dep->de_FileSize)) { - /* - * If either the whole cluster gets written, - * or we write the cluster from its start beyond EOF, - * then no need to read data from disk. - */ - bp = getblk(thisvp, bn, pmp->pm_bpcluster, 0, 0); - clrbuf(bp); - /* - * Do the bmap now, since pcbmap needs buffers - * for the fat table. (see msdosfs_strategy) - */ - if (bp->b_blkno == bp->b_lblkno) { - error = pcbmap(dep, bp->b_lblkno, &bp->b_blkno, - 0, 0); - if (error) - bp->b_blkno = -1; - } - if (bp->b_blkno == -1) { - brelse(bp); - if (!error) - error = EIO; /* XXX */ - break; - } - } else { - /* - * The block we need to write into exists, so read it in. - */ - error = bread(thisvp, bn, pmp->pm_bpcluster, cred, &bp); - if (error) { - brelse(bp); - break; - } - } - - /* - * Should these vnode_pager_* functions be done on dir - * files? - */ - - /* - * Copy the data from user space into the buf header. - */ - error = uiomove(bp->b_data + croffset, n, uio); - if (error) { - brelse(bp); - break; - } - - /* - * If they want this synchronous then write it and wait for - * it. Otherwise, if on a cluster boundary write it - * asynchronously so we can move on to the next block - * without delay. Otherwise do a delayed write because we - * may want to write somemore into the block later. - */ - if (ioflag & IO_SYNC) - (void) bwrite(bp); - else if (n + croffset == pmp->pm_bpcluster) - bawrite(bp); - else - bdwrite(bp); - dep->de_flag |= DE_UPDATE; - } while (error == 0 && uio->uio_resid > 0); - - /* - * If the write failed and they want us to, truncate the file back - * to the size it was before the write was attempted. - */ -errexit: - if (error) { - if (ioflag & IO_UNIT) { - detrunc(dep, osize, ioflag & IO_SYNC, NOCRED, NULL); - uio->uio_offset -= resid - uio->uio_resid; - uio->uio_resid = resid; - } else { - detrunc(dep, dep->de_FileSize, ioflag & IO_SYNC, NOCRED, NULL); - if (uio->uio_resid != resid) - error = 0; - } - } else if (ioflag & IO_SYNC) - error = deupdat(dep, 1); - return (error); -} - -/* - * Flush the blocks of a file to disk. - * - * This function is worthless for vnodes that represent directories. Maybe we - * could just do a sync if they try an fsync on a directory file. - */ -static int -msdosfs_fsync(ap) - struct vop_fsync_args /* { - struct vnode *a_vp; - struct ucred *a_cred; - int a_waitfor; - struct proc *a_p; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - int s; - struct buf *bp, *nbp; - - /* - * Flush all dirty buffers associated with a vnode. - */ -loop: - s = splbio(); - for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); - if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) - continue; - if ((bp->b_flags & B_DELWRI) == 0) - panic("msdosfs_fsync: not dirty"); - bremfree(bp); - splx(s); - (void) bwrite(bp); - goto loop; - } - while (vp->v_numoutput) { - vp->v_flag |= VBWAIT; - (void) tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "msdosfsn", 0); - } -#ifdef DIAGNOSTIC - if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) { - vprint("msdosfs_fsync: dirty", vp); - goto loop; - } -#endif - splx(s); - return (deupdat(VTODE(vp), ap->a_waitfor == MNT_WAIT)); -} - -static int -msdosfs_remove(ap) - struct vop_remove_args /* { - struct vnode *a_dvp; - struct vnode *a_vp; - struct componentname *a_cnp; - } */ *ap; -{ - struct denode *dep = VTODE(ap->a_vp); - struct denode *ddep = VTODE(ap->a_dvp); - int error; - - if (ap->a_vp->v_type == VDIR) - error = EPERM; - else - error = removede(ddep, dep); -#ifdef MSDOSFS_DEBUG - printf("msdosfs_remove(), dep %p, v_usecount %d\n", dep, ap->a_vp->v_usecount); -#endif - return (error); -} - -/* - * DOS filesystems don't know what links are. - */ -static int -msdosfs_link(ap) - struct vop_link_args /* { - struct vnode *a_tdvp; - struct vnode *a_vp; - struct componentname *a_cnp; - } */ *ap; -{ - return (EOPNOTSUPP); -} - -/* - * Renames on files require moving the denode to a new hash queue since the - * denode's location is used to compute which hash queue to put the file - * in. Unless it is a rename in place. For example "mv a b". - * - * What follows is the basic algorithm: - * - * if (file move) { - * if (dest file exists) { - * remove dest file - * } - * if (dest and src in same directory) { - * rewrite name in existing directory slot - * } else { - * write new entry in dest directory - * update offset and dirclust in denode - * move denode to new hash chain - * clear old directory entry - * } - * } else { - * directory move - * if (dest directory exists) { - * if (dest is not empty) { - * return ENOTEMPTY - * } - * remove dest directory - * } - * if (dest and src in same directory) { - * rewrite name in existing entry - * } else { - * be sure dest is not a child of src directory - * write entry in dest directory - * update "." and ".." in moved directory - * clear old directory entry for moved directory - * } - * } - * - * On entry: - * source's parent directory is unlocked - * source file or directory is unlocked - * destination's parent directory is locked - * destination file or directory is locked if it exists - * - * On exit: - * all denodes should be released - */ -static int -msdosfs_rename(ap) - struct vop_rename_args /* { - struct vnode *a_fdvp; - struct vnode *a_fvp; - struct componentname *a_fcnp; - struct vnode *a_tdvp; - struct vnode *a_tvp; - struct componentname *a_tcnp; - } */ *ap; -{ - struct vnode *tdvp = ap->a_tdvp; - struct vnode *fvp = ap->a_fvp; - struct vnode *fdvp = ap->a_fdvp; - struct vnode *tvp = ap->a_tvp; - struct componentname *tcnp = ap->a_tcnp; - struct componentname *fcnp = ap->a_fcnp; - struct proc *p = fcnp->cn_proc; - struct denode *ip, *xp, *dp, *zp; - u_char toname[11], oldname[11]; - u_long from_diroffset, to_diroffset; - u_char to_count; - int doingdirectory = 0, newparent = 0; - int error; - u_long cn; - daddr_t bn; - struct denode *fddep; /* from file's parent directory */ - struct denode *fdep; /* from file or directory */ - struct denode *tddep; /* to file's parent directory */ - struct denode *tdep; /* to file or directory */ - struct msdosfsmount *pmp; - struct direntry *dotdotp; - struct buf *bp; - - fddep = VTODE(ap->a_fdvp); - fdep = VTODE(ap->a_fvp); - tddep = VTODE(ap->a_tdvp); - tdep = tvp ? VTODE(tvp) : NULL; - pmp = fddep->de_pmp; - - pmp = VFSTOMSDOSFS(fdvp->v_mount); - -#ifdef DIAGNOSTIC - if ((tcnp->cn_flags & HASBUF) == 0 || - (fcnp->cn_flags & HASBUF) == 0) - panic("msdosfs_rename: no name"); -#endif - /* - * Check for cross-device rename. - */ - if ((fvp->v_mount != tdvp->v_mount) || - (tvp && (fvp->v_mount != tvp->v_mount))) { - error = EXDEV; -abortit: - if (tdvp == tvp) - vrele(tdvp); - else - vput(tdvp); - if (tvp) - vput(tvp); - vrele(fdvp); - vrele(fvp); - return (error); - } - - /* - * If source and dest are the same, do nothing. - */ - if (tvp == fvp) { - error = 0; - goto abortit; - } - - error = vn_lock(fvp, LK_EXCLUSIVE, p); - if (error) - goto abortit; - dp = VTODE(fdvp); - ip = VTODE(fvp); - - /* - * Be sure we are not renaming ".", "..", or an alias of ".". This - * leads to a crippled directory tree. It's pretty tough to do a - * "ls" or "pwd" with the "." directory entry missing, and "cd .." - * doesn't work if the ".." entry is missing. - */ - if (ip->de_Attributes & ATTR_DIRECTORY) { - /* - * Avoid ".", "..", and aliases of "." for obvious reasons. - */ - if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || - dp == ip || - (fcnp->cn_flags & ISDOTDOT) || - (tcnp->cn_flags & ISDOTDOT) || - (ip->de_flag & DE_RENAME)) { - VOP_UNLOCK(fvp, 0, p); - error = EINVAL; - goto abortit; - } - ip->de_flag |= DE_RENAME; - doingdirectory++; - } - - /* - * When the target exists, both the directory - * and target vnodes are returned locked. - */ - dp = VTODE(tdvp); - xp = tvp ? VTODE(tvp) : NULL; - /* - * Remember direntry place to use for destination - */ - to_diroffset = dp->de_fndoffset; - to_count = dp->de_fndcnt; - - /* - * If ".." must be changed (ie the directory gets a new - * parent) then the source directory must not be in the - * directory heirarchy above the target, as this would - * orphan everything below the source directory. Also - * the user must have write permission in the source so - * as to be able to change "..". We must repeat the call - * to namei, as the parent directory is unlocked by the - * call to doscheckpath(). - */ - error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc); - VOP_UNLOCK(fvp, 0, p); - if (VTODE(fdvp)->de_StartCluster != VTODE(tdvp)->de_StartCluster) - newparent = 1; - if (doingdirectory && newparent) { - if (error) /* write access check above */ - goto bad; - if (xp != NULL) - vput(tvp); - /* - * doscheckpath() vput()'s dp, - * so we have to do a relookup afterwards - */ - error = doscheckpath(ip, dp); - if (error) - goto out; - if ((tcnp->cn_flags & SAVESTART) == 0) - panic("msdosfs_rename: lost to startdir"); - error = relookup(tdvp, &tvp, tcnp); - if (error) - goto out; - dp = VTODE(tdvp); - xp = tvp ? VTODE(tvp) : NULL; - } - - if (xp != NULL) { - /* - * Target must be empty if a directory and have no links - * to it. Also, ensure source and target are compatible - * (both directories, or both not directories). - */ - if (xp->de_Attributes & ATTR_DIRECTORY) { - if (!dosdirempty(xp)) { - error = ENOTEMPTY; - goto bad; - } - if (!doingdirectory) { - error = ENOTDIR; - goto bad; - } - cache_purge(tdvp); - } else if (doingdirectory) { - error = EISDIR; - goto bad; - } - error = removede(dp, xp); - if (error) - goto bad; - vput(tvp); - xp = NULL; - } - - /* - * Convert the filename in tcnp into a dos filename. We copy this - * into the denode and directory entry for the destination - * file/directory. - */ - error = uniqdosname(VTODE(tdvp), tcnp, toname); - if (error) - goto abortit; - - /* - * Since from wasn't locked at various places above, - * have to do a relookup here. - */ - fcnp->cn_flags &= ~MODMASK; - fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; - if ((fcnp->cn_flags & SAVESTART) == 0) - panic("msdosfs_rename: lost from startdir"); - if (!newparent) - VOP_UNLOCK(tdvp, 0, p); - if (relookup(fdvp, &fvp, fcnp) == 0) - vrele(fdvp); - if (fvp == NULL) { - /* - * From name has disappeared. - */ - if (doingdirectory) - panic("rename: lost dir entry"); - vrele(ap->a_fvp); - if (newparent) - VOP_UNLOCK(tdvp, 0, p); - vrele(tdvp); - return 0; - } - xp = VTODE(fvp); - zp = VTODE(fdvp); - from_diroffset = zp->de_fndoffset; - - /* - * Ensure that the directory entry still exists and has not - * changed till now. If the source is a file the entry may - * have been unlinked or renamed. In either case there is - * no further work to be done. If the source is a directory - * then it cannot have been rmdir'ed or renamed; this is - * prohibited by the DE_RENAME flag. - */ - if (xp != ip) { - if (doingdirectory) - panic("rename: lost dir entry"); - vrele(ap->a_fvp); - VOP_UNLOCK(fvp, 0, p); - if (newparent) - VOP_UNLOCK(fdvp, 0, p); - xp = NULL; - } else { - vrele(fvp); - xp = NULL; - - /* - * First write a new entry in the destination - * directory and mark the entry in the source directory - * as deleted. Then move the denode to the correct hash - * chain for its new location in the filesystem. And, if - * we moved a directory, then update its .. entry to point - * to the new parent directory. - */ - bcopy(ip->de_Name, oldname, 11); - bcopy(toname, ip->de_Name, 11); /* update denode */ - dp->de_fndoffset = to_diroffset; - dp->de_fndcnt = to_count; - error = createde(ip, dp, (struct denode **)0, tcnp); - if (error) { - bcopy(oldname, ip->de_Name, 11); - if (newparent) - VOP_UNLOCK(fdvp, 0, p); - VOP_UNLOCK(fvp, 0, p); - goto bad; - } - ip->de_refcnt++; - zp->de_fndoffset = from_diroffset; - error = removede(zp, ip); - if (error) { - /* XXX should really panic here, fs is corrupt */ - if (newparent) - VOP_UNLOCK(fdvp, 0, p); - VOP_UNLOCK(fvp, 0, p); - goto bad; - } - if (!doingdirectory) { - error = pcbmap(dp, de_cluster(pmp, to_diroffset), 0, - &ip->de_dirclust, 0); - if (error) { - /* XXX should really panic here, fs is corrupt */ - if (newparent) - VOP_UNLOCK(fdvp, 0, p); - VOP_UNLOCK(fvp, 0, p); - goto bad; - } - if (ip->de_dirclust == MSDOSFSROOT) - ip->de_diroffset = to_diroffset; - else - ip->de_diroffset = to_diroffset & pmp->pm_crbomask; - } - reinsert(ip); - if (newparent) - VOP_UNLOCK(fdvp, 0, p); - } - - /* - * If we moved a directory to a new parent directory, then we must - * fixup the ".." entry in the moved directory. - */ - if (doingdirectory && newparent) { - cn = ip->de_StartCluster; - if (cn == MSDOSFSROOT) { - /* this should never happen */ - panic("msdosfs_rename(): updating .. in root directory?"); - } else - bn = cntobn(pmp, cn); - error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster, - NOCRED, &bp); - if (error) { - /* XXX should really panic here, fs is corrupt */ - brelse(bp); - VOP_UNLOCK(fvp, 0, p); - goto bad; - } - dotdotp = (struct direntry *)bp->b_data + 1; - putushort(dotdotp->deStartCluster, dp->de_StartCluster); - if (FAT32(pmp)) - putushort(dotdotp->deHighClust, dp->de_StartCluster >> 16); - error = bwrite(bp); - if (error) { - /* XXX should really panic here, fs is corrupt */ - VOP_UNLOCK(fvp, 0, p); - goto bad; - } - } - - VOP_UNLOCK(fvp, 0, p); -bad: - if (xp) - vput(tvp); - vput(tdvp); -out: - ip->de_flag &= ~DE_RENAME; - vrele(fdvp); - vrele(fvp); - return (error); - -} - -static struct { - struct direntry dot; - struct direntry dotdot; -} dosdirtemplate = { - { ". ", " ", /* the . entry */ - ATTR_DIRECTORY, /* file attribute */ - 0, /* reserved */ - 0, { 0, 0 }, { 0, 0 }, /* create time & date */ - { 0, 0 }, /* access date */ - { 0, 0 }, /* high bits of start cluster */ - { 210, 4 }, { 210, 4 }, /* modify time & date */ - { 0, 0 }, /* startcluster */ - { 0, 0, 0, 0 } /* filesize */ - }, - { ".. ", " ", /* the .. entry */ - ATTR_DIRECTORY, /* file attribute */ - 0, /* reserved */ - 0, { 0, 0 }, { 0, 0 }, /* create time & date */ - { 0, 0 }, /* access date */ - { 0, 0 }, /* high bits of start cluster */ - { 210, 4 }, { 210, 4 }, /* modify time & date */ - { 0, 0 }, /* startcluster */ - { 0, 0, 0, 0 } /* filesize */ - } -}; - -static int -msdosfs_mkdir(ap) - struct vop_mkdir_args /* { - struct vnode *a_dvp; - struvt vnode **a_vpp; - struvt componentname *a_cnp; - struct vattr *a_vap; - } */ *ap; -{ - struct componentname *cnp = ap->a_cnp; - struct denode *dep; - struct denode *pdep = VTODE(ap->a_dvp); - struct direntry *denp; - struct msdosfsmount *pmp = pdep->de_pmp; - struct buf *bp; - u_long newcluster, pcl; - int bn; - int error; - struct denode ndirent; - struct timespec ts; - - /* - * If this is the root directory and there is no space left we - * can't do anything. This is because the root directory can not - * change size. - */ - if (pdep->de_StartCluster == MSDOSFSROOT - && pdep->de_fndoffset >= pdep->de_FileSize) { - error = ENOSPC; - goto bad2; - } - - /* - * Allocate a cluster to hold the about to be created directory. - */ - error = clusteralloc(pmp, 0, 1, CLUST_EOFE, &newcluster, NULL); - if (error) - goto bad2; - - bzero(&ndirent, sizeof(ndirent)); - ndirent.de_pmp = pmp; - ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE; - getnanotime(&ts); - DETIMES(&ndirent, &ts, &ts, &ts); - - /* - * Now fill the cluster with the "." and ".." entries. And write - * the cluster to disk. This way it is there for the parent - * directory to be pointing at if there were a crash. - */ - bn = cntobn(pmp, newcluster); - /* always succeeds */ - bp = getblk(pmp->pm_devvp, bn, pmp->pm_bpcluster, 0, 0); - bzero(bp->b_data, pmp->pm_bpcluster); - bcopy(&dosdirtemplate, bp->b_data, sizeof dosdirtemplate); - denp = (struct direntry *)bp->b_data; - putushort(denp[0].deStartCluster, newcluster); - putushort(denp[0].deCDate, ndirent.de_CDate); - putushort(denp[0].deCTime, ndirent.de_CTime); - denp[0].deCHundredth = ndirent.de_CHun; - putushort(denp[0].deADate, ndirent.de_ADate); - putushort(denp[0].deMDate, ndirent.de_MDate); - putushort(denp[0].deMTime, ndirent.de_MTime); - pcl = pdep->de_StartCluster; - if (FAT32(pmp) && pcl == pmp->pm_rootdirblk) - pcl = 0; - putushort(denp[1].deStartCluster, pcl); - putushort(denp[1].deCDate, ndirent.de_CDate); - putushort(denp[1].deCTime, ndirent.de_CTime); - denp[1].deCHundredth = ndirent.de_CHun; - putushort(denp[1].deADate, ndirent.de_ADate); - putushort(denp[1].deMDate, ndirent.de_MDate); - putushort(denp[1].deMTime, ndirent.de_MTime); - if (FAT32(pmp)) { - putushort(denp[0].deHighClust, newcluster >> 16); - putushort(denp[1].deHighClust, pdep->de_StartCluster >> 16); - } - - error = bwrite(bp); - if (error) - goto bad; - - /* - * Now build up a directory entry pointing to the newly allocated - * cluster. This will be written to an empty slot in the parent - * directory. - */ -#ifdef DIAGNOSTIC - if ((cnp->cn_flags & HASBUF) == 0) - panic("msdosfs_mkdir: no name"); -#endif - error = uniqdosname(pdep, cnp, ndirent.de_Name); - if (error) - goto bad; - - ndirent.de_Attributes = ATTR_DIRECTORY; - ndirent.de_LowerCase = 0; - ndirent.de_StartCluster = newcluster; - ndirent.de_FileSize = 0; - ndirent.de_dev = pdep->de_dev; - ndirent.de_devvp = pdep->de_devvp; - error = createde(&ndirent, pdep, &dep, cnp); - if (error) - goto bad; - *ap->a_vpp = DETOV(dep); - return (0); - -bad: - clusterfree(pmp, newcluster, NULL); -bad2: - return (error); -} - -static int -msdosfs_rmdir(ap) - struct vop_rmdir_args /* { - struct vnode *a_dvp; - struct vnode *a_vp; - struct componentname *a_cnp; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct vnode *dvp = ap->a_dvp; - register struct componentname *cnp = ap->a_cnp; - register struct denode *ip, *dp; - struct proc *p = cnp->cn_proc; - int error; - - ip = VTODE(vp); - dp = VTODE(dvp); - - /* - * Verify the directory is empty (and valid). - * (Rmdir ".." won't be valid since - * ".." will contain a reference to - * the current directory and thus be - * non-empty.) - */ - error = 0; - if (!dosdirempty(ip) || ip->de_flag & DE_RENAME) { - error = ENOTEMPTY; - goto out; - } - /* - * Delete the entry from the directory. For dos filesystems this - * gets rid of the directory entry on disk, the in memory copy - * still exists but the de_refcnt is <= 0. This prevents it from - * being found by deget(). When the vput() on dep is done we give - * up access and eventually msdosfs_reclaim() will be called which - * will remove it from the denode cache. - */ - error = removede(dp, ip); - if (error) - goto out; - /* - * This is where we decrement the link count in the parent - * directory. Since dos filesystems don't do this we just purge - * the name cache. - */ - cache_purge(dvp); - VOP_UNLOCK(dvp, 0, p); - /* - * Truncate the directory that is being deleted. - */ - error = detrunc(ip, (u_long)0, IO_SYNC, cnp->cn_cred, p); - cache_purge(vp); - - vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); -out: - return (error); -} - -/* - * DOS filesystems don't know what symlinks are. - */ -static int -msdosfs_symlink(ap) - struct vop_symlink_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - char *a_target; - } */ *ap; -{ - return (EOPNOTSUPP); -} - -static int -msdosfs_readdir(ap) - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_eofflag; - int *a_ncookies; - u_long **a_cookies; - } */ *ap; -{ - int error = 0; - int diff; - long n; - int blsize; - long on; - u_long cn; - u_long fileno; - u_long dirsperblk; - long bias = 0; - daddr_t bn, lbn; - struct buf *bp; - struct denode *dep = VTODE(ap->a_vp); - struct msdosfsmount *pmp = dep->de_pmp; - struct direntry *dentp; - struct dirent dirbuf; - struct uio *uio = ap->a_uio; - u_long *cookies = NULL; - int ncookies = 0; - off_t offset, off; - int chksum = -1; - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_readdir(): vp %p, uio %p, cred %p, eofflagp %p\n", - ap->a_vp, uio, ap->a_cred, ap->a_eofflag); -#endif - - /* - * msdosfs_readdir() won't operate properly on regular files since - * it does i/o only with the the filesystem vnode, and hence can - * retrieve the wrong block from the buffer cache for a plain file. - * So, fail attempts to readdir() on a plain file. - */ - if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) - return (ENOTDIR); - - /* - * To be safe, initialize dirbuf - */ - bzero(dirbuf.d_name, sizeof(dirbuf.d_name)); - - /* - * If the user buffer is smaller than the size of one dos directory - * entry or the file offset is not a multiple of the size of a - * directory entry, then we fail the read. - */ - off = offset = uio->uio_offset; - if (uio->uio_resid < sizeof(struct direntry) || - (offset & (sizeof(struct direntry) - 1))) - return (EINVAL); - - if (ap->a_ncookies) { - ncookies = uio->uio_resid / 16; - MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, - M_WAITOK); - *ap->a_cookies = cookies; - *ap->a_ncookies = ncookies; - } - - dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); - - /* - * If they are reading from the root directory then, we simulate - * the . and .. entries since these don't exist in the root - * directory. We also set the offset bias to make up for having to - * simulate these entries. By this I mean that at file offset 64 we - * read the first entry in the root directory that lives on disk. - */ - if (dep->de_StartCluster == MSDOSFSROOT - || (FAT32(pmp) && dep->de_StartCluster == pmp->pm_rootdirblk)) { -#if 0 - printf("msdosfs_readdir(): going after . or .. in root dir, offset %d\n", - offset); -#endif - bias = 2 * sizeof(struct direntry); - if (offset < bias) { - for (n = (int)offset / sizeof(struct direntry); - n < 2; n++) { - if (FAT32(pmp)) - dirbuf.d_fileno = cntobn(pmp, - pmp->pm_rootdirblk) - * dirsperblk; - else - dirbuf.d_fileno = 1; - dirbuf.d_type = DT_DIR; - switch (n) { - case 0: - dirbuf.d_namlen = 1; - strcpy(dirbuf.d_name, "."); - break; - case 1: - dirbuf.d_namlen = 2; - strcpy(dirbuf.d_name, ".."); - break; - } - dirbuf.d_reclen = GENERIC_DIRSIZ(&dirbuf); - if (uio->uio_resid < dirbuf.d_reclen) - goto out; - error = uiomove((caddr_t) &dirbuf, - dirbuf.d_reclen, uio); - if (error) - goto out; - offset += sizeof(struct direntry); - off = offset; - if (cookies) { - *cookies++ = offset; - if (--ncookies <= 0) - goto out; - } - } - } - } - - off = offset; - while (uio->uio_resid > 0) { - lbn = de_cluster(pmp, offset - bias); - on = (offset - bias) & pmp->pm_crbomask; - n = min(pmp->pm_bpcluster - on, uio->uio_resid); - diff = dep->de_FileSize - (offset - bias); - if (diff <= 0) - break; - n = min(n, diff); - error = pcbmap(dep, lbn, &bn, &cn, &blsize); - if (error) - break; - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - n = min(n, blsize - bp->b_resid); - - /* - * Convert from dos directory entries to fs-independent - * directory entries. - */ - for (dentp = (struct direntry *)(bp->b_data + on); - (char *)dentp < bp->b_data + on + n; - dentp++, offset += sizeof(struct direntry)) { -#if 0 - printf("rd: dentp %08x prev %08x crnt %08x deName %02x attr %02x\n", - dentp, prev, crnt, dentp->deName[0], dentp->deAttributes); -#endif - /* - * If this is an unused entry, we can stop. - */ - if (dentp->deName[0] == SLOT_EMPTY) { - brelse(bp); - goto out; - } - /* - * Skip deleted entries. - */ - if (dentp->deName[0] == SLOT_DELETED) { - chksum = -1; - continue; - } - - /* - * Handle Win95 long directory entries - */ - if (dentp->deAttributes == ATTR_WIN95) { - if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) - continue; - chksum = win2unixfn((struct winentry *)dentp, - &dirbuf, chksum, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, - pmp->pm_u2w); - continue; - } - - /* - * Skip volume labels - */ - if (dentp->deAttributes & ATTR_VOLUME) { - chksum = -1; - continue; - } - /* - * This computation of d_fileno must match - * the computation of va_fileid in - * msdosfs_getattr. - */ - if (dentp->deAttributes & ATTR_DIRECTORY) { - fileno = getushort(dentp->deStartCluster); - if (FAT32(pmp)) - fileno |= getushort(dentp->deHighClust) << 16; - /* if this is the root directory */ - if (fileno == MSDOSFSROOT) - if (FAT32(pmp)) - fileno = cntobn(pmp, - pmp->pm_rootdirblk) - * dirsperblk; - else - fileno = 1; - else - fileno = cntobn(pmp, fileno) * dirsperblk; - dirbuf.d_fileno = fileno; - dirbuf.d_type = DT_DIR; - } else { - dirbuf.d_fileno = offset / sizeof(struct direntry); - dirbuf.d_type = DT_REG; - } - if (chksum != winChksum(dentp->deName)) - dirbuf.d_namlen = dos2unixfn(dentp->deName, - (u_char *)dirbuf.d_name, - dentp->deLowerCase | - ((pmp->pm_flags & MSDOSFSMNT_SHORTNAME) ? - (LCASE_BASE | LCASE_EXT) : 0), - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, - pmp->pm_d2u, - pmp->pm_flags & MSDOSFSMNT_ULTABLE, - pmp->pm_ul); - else - dirbuf.d_name[dirbuf.d_namlen] = 0; - chksum = -1; - dirbuf.d_reclen = GENERIC_DIRSIZ(&dirbuf); - if (uio->uio_resid < dirbuf.d_reclen) { - brelse(bp); - goto out; - } - error = uiomove((caddr_t) &dirbuf, - dirbuf.d_reclen, uio); - if (error) { - brelse(bp); - goto out; - } - if (cookies) { - *cookies++ = offset + sizeof(struct direntry); - if (--ncookies <= 0) { - brelse(bp); - goto out; - } - } - off = offset + sizeof(struct direntry); - } - brelse(bp); - } -out: - /* Subtract unused cookies */ - if (ap->a_ncookies) - *ap->a_ncookies -= ncookies; - - uio->uio_offset = off; - - /* - * Set the eofflag (NFS uses it) - */ - if (ap->a_eofflag) { - if (dep->de_FileSize - (offset - bias) <= 0) - *ap->a_eofflag = 1; - else - *ap->a_eofflag = 0; - } - return (error); -} - -/* - * vp - address of vnode file the file - * bn - which cluster we are interested in mapping to a filesystem block number. - * vpp - returns the vnode for the block special file holding the filesystem - * containing the file of interest - * bnp - address of where to return the filesystem relative block number - */ -static int -msdosfs_bmap(ap) - struct vop_bmap_args /* { - struct vnode *a_vp; - daddr_t a_bn; - struct vnode **a_vpp; - daddr_t *a_bnp; - int *a_runp; - int *a_runb; - } */ *ap; -{ - struct denode *dep = VTODE(ap->a_vp); - - if (ap->a_vpp != NULL) - *ap->a_vpp = dep->de_devvp; - if (ap->a_bnp == NULL) - return (0); - if (ap->a_runp) { - /* - * Sequential clusters should be counted here. - */ - *ap->a_runp = 0; - } - if (ap->a_runb) { - *ap->a_runb = 0; - } - return (pcbmap(dep, ap->a_bn, ap->a_bnp, 0, 0)); -} - -static int -msdosfs_strategy(ap) - struct vop_strategy_args /* { - struct vnode *a_vp; - struct buf *a_bp; - } */ *ap; -{ - struct buf *bp = ap->a_bp; - struct denode *dep = VTODE(bp->b_vp); - struct vnode *vp; - int error = 0; - - if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR) - panic("msdosfs_strategy: spec"); - /* - * If we don't already know the filesystem relative block number - * then get it using pcbmap(). If pcbmap() returns the block - * number as -1 then we've got a hole in the file. DOS filesystems - * don't allow files with holes, so we shouldn't ever see this. - */ - if (bp->b_blkno == bp->b_lblkno) { - error = pcbmap(dep, bp->b_lblkno, &bp->b_blkno, 0, 0); - if (error) { - bp->b_error = error; - bp->b_ioflags |= BIO_ERROR; - bufdone(bp); - return (error); - } - if ((long)bp->b_blkno == -1) - vfs_bio_clrbuf(bp); - } - if (bp->b_blkno == -1) { - bufdone(bp); - return (0); - } - /* - * Read/write the block from/to the disk that contains the desired - * file block. - */ - vp = dep->de_devvp; - bp->b_dev = vp->v_rdev; - VOP_STRATEGY(vp, bp); - return (0); -} - -static int -msdosfs_print(ap) - struct vop_print_args /* { - struct vnode *vp; - } */ *ap; -{ - struct denode *dep = VTODE(ap->a_vp); - - printf( - "tag VT_MSDOSFS, startcluster %lu, dircluster %lu, diroffset %lu ", - dep->de_StartCluster, dep->de_dirclust, dep->de_diroffset); - printf(" dev %d, %d", major(dep->de_dev), minor(dep->de_dev)); - lockmgr_printinfo(&ap->a_vp->v_lock); - printf("\n"); - return (0); -} - -static int -msdosfs_pathconf(ap) - struct vop_pathconf_args /* { - struct vnode *a_vp; - int a_name; - int *a_retval; - } */ *ap; -{ - struct msdosfsmount *pmp = VTODE(ap->a_vp)->de_pmp; - - switch (ap->a_name) { - case _PC_LINK_MAX: - *ap->a_retval = 1; - return (0); - case _PC_NAME_MAX: - *ap->a_retval = pmp->pm_flags & MSDOSFSMNT_LONGNAME ? WIN_MAXLEN : 12; - return (0); - case _PC_PATH_MAX: - *ap->a_retval = PATH_MAX; - return (0); - case _PC_CHOWN_RESTRICTED: - *ap->a_retval = 1; - return (0); - case _PC_NO_TRUNC: - *ap->a_retval = 0; - return (0); - default: - return (EINVAL); - } - /* NOTREACHED */ -} - - -/* Global vfs data structures for msdosfs */ -vop_t **msdosfs_vnodeop_p; -static struct vnodeopv_entry_desc msdosfs_vnodeop_entries[] = { - { &vop_default_desc, (vop_t *) vop_defaultop }, - { &vop_access_desc, (vop_t *) msdosfs_access }, - { &vop_bmap_desc, (vop_t *) msdosfs_bmap }, - { &vop_cachedlookup_desc, (vop_t *) msdosfs_lookup }, - { &vop_close_desc, (vop_t *) msdosfs_close }, - { &vop_create_desc, (vop_t *) msdosfs_create }, - { &vop_fsync_desc, (vop_t *) msdosfs_fsync }, - { &vop_getattr_desc, (vop_t *) msdosfs_getattr }, - { &vop_inactive_desc, (vop_t *) msdosfs_inactive }, - { &vop_islocked_desc, (vop_t *) vop_stdislocked }, - { &vop_link_desc, (vop_t *) msdosfs_link }, - { &vop_lock_desc, (vop_t *) vop_stdlock }, - { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, - { &vop_mkdir_desc, (vop_t *) msdosfs_mkdir }, - { &vop_mknod_desc, (vop_t *) msdosfs_mknod }, - { &vop_pathconf_desc, (vop_t *) msdosfs_pathconf }, - { &vop_print_desc, (vop_t *) msdosfs_print }, - { &vop_read_desc, (vop_t *) msdosfs_read }, - { &vop_readdir_desc, (vop_t *) msdosfs_readdir }, - { &vop_reclaim_desc, (vop_t *) msdosfs_reclaim }, - { &vop_remove_desc, (vop_t *) msdosfs_remove }, - { &vop_rename_desc, (vop_t *) msdosfs_rename }, - { &vop_rmdir_desc, (vop_t *) msdosfs_rmdir }, - { &vop_setattr_desc, (vop_t *) msdosfs_setattr }, - { &vop_strategy_desc, (vop_t *) msdosfs_strategy }, - { &vop_symlink_desc, (vop_t *) msdosfs_symlink }, - { &vop_unlock_desc, (vop_t *) vop_stdunlock }, - { &vop_write_desc, (vop_t *) msdosfs_write }, - { NULL, NULL } -}; -static struct vnodeopv_desc msdosfs_vnodeop_opv_desc = - { &msdosfs_vnodeop_p, msdosfs_vnodeop_entries }; - -VNODEOP_SET(msdosfs_vnodeop_opv_desc); diff --git a/sys/msdosfs/msdosfsmount.h b/sys/msdosfs/msdosfsmount.h deleted file mode 100644 index 1c9a890..0000000 --- a/sys/msdosfs/msdosfsmount.h +++ /dev/null @@ -1,245 +0,0 @@ -/* $FreeBSD$ */ -/* $NetBSD: msdosfsmount.h,v 1.17 1997/11/17 15:37:07 ws Exp $ */ - -/*- - * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. - * Copyright (C) 1994, 1995, 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 - */ - -#ifndef _MSDOSFS_MSDOSFSMOUNT_H_ -#define _MSDOSFS_MSDOSFSMOUNT_H_ - -#ifdef _KERNEL - -#ifdef MALLOC_DECLARE -MALLOC_DECLARE(M_MSDOSFSMNT); -#endif - -/* - * Layout of the mount control block for a msdos file system. - */ -struct msdosfsmount { - struct mount *pm_mountp;/* vfs mount struct for this fs */ - dev_t pm_dev; /* block special device mounted */ - uid_t pm_uid; /* uid to set as owner of the files */ - gid_t pm_gid; /* gid to set as owner of the files */ - mode_t pm_mask; /* mask to and with file protection bits */ - struct vnode *pm_devvp; /* vnode for block device mntd */ - struct bpb50 pm_bpb; /* BIOS parameter blk for this fs */ - u_long pm_BlkPerSec; /* How many DEV_BSIZE blocks fit inside a physical sector */ - u_long pm_FATsecs; /* actual number of fat sectors */ - u_long pm_fatblk; /* block # of first FAT */ - u_long pm_rootdirblk; /* block # (cluster # for FAT32) of root directory number */ - u_long pm_rootdirsize; /* size in blocks (not clusters) */ - u_long pm_firstcluster; /* block number of first cluster */ - u_long pm_maxcluster; /* maximum cluster number */ - u_long pm_freeclustercount; /* number of free clusters */ - u_long pm_cnshift; /* shift file offset right this amount to get a cluster number */ - u_long pm_crbomask; /* and a file offset with this mask to get cluster rel offset */ - u_long pm_bnshift; /* shift file offset right this amount to get a block number */ - u_long pm_bpcluster; /* bytes per cluster */ - u_long pm_fmod; /* ~0 if fs is modified, this can rollover to 0 */ - u_long pm_fatblocksize; /* size of fat blocks in bytes */ - u_long pm_fatblocksec; /* size of fat blocks in sectors */ - u_long pm_fatsize; /* size of fat in bytes */ - u_int32_t pm_fatmask; /* mask to use for fat numbers */ - u_long pm_fsinfo; /* fsinfo block number */ - u_long pm_nxtfree; /* next free cluster in fsinfo block */ - u_int pm_fatmult; /* these 2 values are used in fat */ - u_int pm_fatdiv; /* offset computation */ - u_int pm_curfat; /* current fat for FAT32 (0 otherwise) */ - u_int *pm_inusemap; /* ptr to bitmap of in-use clusters */ - u_int pm_flags; /* see below */ - u_int16_t pm_u2w[128]; /* Local->Unicode table */ - u_int8_t pm_ul[128]; /* Local upper->lower table */ - u_int8_t pm_lu[128]; /* Local lower->upper table */ - u_int8_t pm_d2u[128]; /* DOS->local table */ - u_int8_t pm_u2d[128]; /* Local->DOS table */ -}; -/* Byte offset in FAT on filesystem pmp, cluster cn */ -#define FATOFS(pmp, cn) ((cn) * (pmp)->pm_fatmult / (pmp)->pm_fatdiv) - - -#define VFSTOMSDOSFS(mp) ((struct msdosfsmount *)mp->mnt_data) - -/* Number of bits in one pm_inusemap item: */ -#define N_INUSEBITS (8 * sizeof(u_int)) - -/* - * Shorthand for fields in the bpb contained in the msdosfsmount structure. - */ -#define pm_BytesPerSec pm_bpb.bpbBytesPerSec -#define pm_ResSectors pm_bpb.bpbResSectors -#define pm_FATs pm_bpb.bpbFATs -#define pm_RootDirEnts pm_bpb.bpbRootDirEnts -#define pm_Sectors pm_bpb.bpbSectors -#define pm_Media pm_bpb.bpbMedia -#define pm_SecPerTrack pm_bpb.bpbSecPerTrack -#define pm_Heads pm_bpb.bpbHeads -#define pm_HiddenSects pm_bpb.bpbHiddenSecs -#define pm_HugeSectors pm_bpb.bpbHugeSectors - -/* - * Convert pointer to buffer -> pointer to direntry - */ -#define bptoep(pmp, bp, dirofs) \ - ((struct direntry *)(((bp)->b_data) \ - + ((dirofs) & (pmp)->pm_crbomask))) - -/* - * Convert block number to cluster number - */ -#define de_bn2cn(pmp, bn) \ - ((bn) >> ((pmp)->pm_cnshift - (pmp)->pm_bnshift)) - -/* - * Convert cluster number to block number - */ -#define de_cn2bn(pmp, cn) \ - ((cn) << ((pmp)->pm_cnshift - (pmp)->pm_bnshift)) - -/* - * Convert file offset to cluster number - */ -#define de_cluster(pmp, off) \ - ((off) >> (pmp)->pm_cnshift) - -/* - * Clusters required to hold size bytes - */ -#define de_clcount(pmp, size) \ - (((size) + (pmp)->pm_bpcluster - 1) >> (pmp)->pm_cnshift) - -/* - * Convert file offset to block number - */ -#define de_blk(pmp, off) \ - (de_cn2bn(pmp, de_cluster((pmp), (off)))) - -/* - * Convert cluster number to file offset - */ -#define de_cn2off(pmp, cn) \ - ((cn) << (pmp)->pm_cnshift) - -/* - * Convert block number to file offset - */ -#define de_bn2off(pmp, bn) \ - ((bn) << (pmp)->pm_bnshift) -/* - * Map a cluster number into a filesystem relative block number. - */ -#define cntobn(pmp, cn) \ - (de_cn2bn((pmp), (cn)-CLUST_FIRST) + (pmp)->pm_firstcluster) - -/* - * Calculate block number for directory entry in root dir, offset dirofs - */ -#define roottobn(pmp, dirofs) \ - (de_blk((pmp), (dirofs)) + (pmp)->pm_rootdirblk) - -/* - * Calculate block number for directory entry at cluster dirclu, offset - * dirofs - */ -#define detobn(pmp, dirclu, dirofs) \ - ((dirclu) == MSDOSFSROOT \ - ? roottobn((pmp), (dirofs)) \ - : cntobn((pmp), (dirclu))) - -/* - * Calculate fsinfo block size - */ -#define fsi_size(pmp) \ - (1024 << ((pmp)->pm_BlkPerSec >> 2)) - -int msdosfs_init __P((struct vfsconf *vfsp)); -int msdosfs_uninit __P((struct vfsconf *vfsp)); -int msdosfs_mountroot __P((void)); - -#endif /* _KERNEL */ - -/* - * Arguments to mount MSDOS filesystems. - */ -struct msdosfs_args { - char *fspec; /* blocks special holding the fs to mount */ - struct export_args export; /* network export information */ - uid_t uid; /* uid that owns msdosfs files */ - gid_t gid; /* gid that owns msdosfs files */ - mode_t mask; /* mask to be applied for msdosfs perms */ - int flags; /* see below */ - int magic; /* version number */ - u_int16_t u2w[128]; /* Local->Unicode table */ - u_int8_t ul[128]; /* Local upper->lower table */ - u_int8_t lu[128]; /* Local lower->upper table */ - u_int8_t d2u[128]; /* DOS->local table */ - u_int8_t u2d[128]; /* Local->DOS table */ -}; - -/* - * Msdosfs mount options: - */ -#define MSDOSFSMNT_SHORTNAME 1 /* Force old DOS short names only */ -#define MSDOSFSMNT_LONGNAME 2 /* Force Win'95 long names */ -#define MSDOSFSMNT_NOWIN95 4 /* Completely ignore Win95 entries */ -#ifndef __FreeBSD__ -#define MSDOSFSMNT_GEMDOSFS 8 /* This is a gemdos-flavour */ -#endif -#define MSDOSFSMNT_U2WTABLE 0x10 /* Local->Unicode and local<->DOS */ - /* tables loaded */ -#define MSDOSFSMNT_ULTABLE 0x20 /* Local upper<->lower table loaded */ -/* All flags above: */ -#define MSDOSFSMNT_MNTOPT \ - (MSDOSFSMNT_SHORTNAME|MSDOSFSMNT_LONGNAME|MSDOSFSMNT_NOWIN95 \ - /*|MSDOSFSMNT_GEMDOSFS*/|MSDOSFSMNT_U2WTABLE|MSDOSFSMNT_ULTABLE) -#define MSDOSFSMNT_RONLY 0x80000000 /* mounted read-only */ -#define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */ -#define MSDOSFS_FATMIRROR 0x20000000 /* FAT is mirrored */ - -#define MSDOSFS_ARGSMAGIC 0xe4eff300 - -#endif /* !_MSDOSFS_MSDOSFSMOUNT_H_ */ diff --git a/usr.bin/fstat/msdosfs.c b/usr.bin/fstat/msdosfs.c index 809477d..0c9c161 100644 --- a/usr.bin/fstat/msdosfs.c +++ b/usr.bin/fstat/msdosfs.c @@ -43,13 +43,13 @@ #define _KERNEL #include <sys/mount.h> -#include <msdosfs/bpb.h> -#include <msdosfs/msdosfsmount.h> +#include <fs/msdosfs/bpb.h> +#include <fs/msdosfs/msdosfsmount.h> #undef _KERNEL -#include <msdosfs/denode.h> -#include <msdosfs/direntry.h> -#include <msdosfs/fat.h> +#include <fs/msdosfs/denode.h> +#include <fs/msdosfs/direntry.h> +#include <fs/msdosfs/fat.h> #include <err.h> #include <kvm.h> diff --git a/usr.sbin/amd/include/config.h b/usr.sbin/amd/include/config.h index 2456edd..8766a5c 100644 --- a/usr.sbin/amd/include/config.h +++ b/usr.sbin/amd/include/config.h @@ -1572,7 +1572,10 @@ /* #undef HAVE_MOUNT_H */ /* Define if you have the <msdosfs/msdosfsmount.h> header file. */ -#define HAVE_MSDOSFS_MSDOSFSMOUNT_H 1 +/* #undef HAVE_MSDOSFS_MSDOSFSMOUNT_H */ + +/* Define if you have the <fs/msdosfs/msdosfsmount.h> header file. */ +#define HAVE_FS_MSDOSFS_MSDOSFSMOUNT_H 1 /* Define if you have the <ndbm.h> header file. */ #define HAVE_NDBM_H 1 diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c index cab8bc0..2d198e6 100644 --- a/usr.sbin/mountd/mountd.c +++ b/usr.sbin/mountd/mountd.c @@ -63,7 +63,7 @@ static const char rcsid[] = #include <nfs/nfsproto.h> #include <nfs/nfs.h> #include <ufs/ufs/ufsmount.h> -#include <msdosfs/msdosfsmount.h> +#include <fs/msdosfs/msdosfsmount.h> #include <ntfs/ntfsmount.h> #include <isofs/cd9660/cd9660_mount.h> /* XXX need isofs in include */ diff --git a/usr.sbin/sade/install.c b/usr.sbin/sade/install.c index 9b4b088..a30634e 100644 --- a/usr.sbin/sade/install.c +++ b/usr.sbin/sade/install.c @@ -45,7 +45,7 @@ #define MSDOSFS #include <sys/mount.h> #include <ufs/ufs/ufsmount.h> -#include <msdosfs/msdosfsmount.h> +#include <fs/msdosfs/msdosfsmount.h> #undef MSDOSFS #include <sys/stat.h> #include <sys/sysctl.h> diff --git a/usr.sbin/sysinstall/dos.c b/usr.sbin/sysinstall/dos.c index ae6eb1e..bada228 100644 --- a/usr.sbin/sysinstall/dos.c +++ b/usr.sbin/sysinstall/dos.c @@ -46,7 +46,7 @@ #include <grp.h> #define MSDOSFS #include <sys/mount.h> -#include <msdosfs/msdosfsmount.h> +#include <fs/msdosfs/msdosfsmount.h> #undef MSDOSFS static Boolean DOSMounted; diff --git a/usr.sbin/sysinstall/floppy.c b/usr.sbin/sysinstall/floppy.c index b37f513..4a42c61 100644 --- a/usr.sbin/sysinstall/floppy.c +++ b/usr.sbin/sysinstall/floppy.c @@ -49,7 +49,7 @@ #define MSDOSFS #include <sys/mount.h> -#include <msdosfs/msdosfsmount.h> +#include <fs/msdosfs/msdosfsmount.h> #undef MSDOSFS #include <ufs/ufs/ufsmount.h> diff --git a/usr.sbin/sysinstall/install.c b/usr.sbin/sysinstall/install.c index 9b4b088..a30634e 100644 --- a/usr.sbin/sysinstall/install.c +++ b/usr.sbin/sysinstall/install.c @@ -45,7 +45,7 @@ #define MSDOSFS #include <sys/mount.h> #include <ufs/ufs/ufsmount.h> -#include <msdosfs/msdosfsmount.h> +#include <fs/msdosfs/msdosfsmount.h> #undef MSDOSFS #include <sys/stat.h> #include <sys/sysctl.h> |