home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.unix.bsd:9003 alt.sources:2539
- Path: sparky!uunet!charon.amdahl.com!amdahl!paulp
- From: paulp@uts.amdahl.com (Paul Popelka)
- Newsgroups: comp.unix.bsd,alt.sources
- Subject: [386bsd] mountable DOS filesystem code, Part 1/5
- Message-ID: <ba3w03h7bbR300@amdahl.uts.amdahl.com>
- Date: 17 Nov 92 17:25:12 GMT
- Followup-To: comp.unix.bsd
- Organization: Amdahl Corporation, Sunnyvale CA
- Lines: 1069
-
-
- # This is a shell archive. Save it in a file, remove anything before
- # this line, and then unpack it by entering "sh file". Note, it may
- # create directories; files and directories will be owned by you and
- # have default permissions.
- #
- # This archive contains:
- #
- # /sys/pcfs
- # /sys/pcfs/INSTALL
- # /sys/pcfs/README
- # /sys/pcfs/pcfs.8
- # /sys/pcfs/pcfs.cdiff
- # /sys/pcfs/fat.h
- # /sys/pcfs/direntry.h
- # /sys/pcfs/denode.h
- # /sys/pcfs/bpb.h
- # /sys/pcfs/bootsect.h
- # /sys/pcfs/pcfsmount.h
- # /usr/src/sbin/mount_pcfs
- # /usr/src/sbin/mount_pcfs/mount_pcfs.c
- # /usr/src/sbin/mount_pcfs/Makefile
- #
- echo c - /sys/pcfs
- mkdir /sys/pcfs > /dev/null 2>&1
- echo x - /sys/pcfs/INSTALL
- sed 's/^X//' >/sys/pcfs/INSTALL << 'END-of-/sys/pcfs/INSTALL'
- XThis note describes the installation of the pcfs filesystem into
- Xa 386bsd 0.1 system.
- X
- XFirst unshar the shar files. They are made with absolute pathnames.
- XThey do not overwrite anything that is part of a standard system.
- XThey deposit files into the /usr/src/sbin/mount_pcfs and /sys/pcfs
- Xdirectories.
- X
- XIn the /sys/pcfs directory is a context diff file pcfs.cdiff. It
- Xcontains context diffs to the following files:
- X /sys/sys/vnode.h
- X /sys/sys/mount.h
- X /sys/sys/malloc.h
- X /sys/conf/files
- X /sys/kern/vfs_conf.c
- X
- XApply them with the following command:
- X patch -p <pcfs.cdiff
- X
- XNext go to the /usr/src/sbin/mount_pcfs directory and build and install
- Xthe mount_pcfs command:
- X cd /usr/src/sbin/mount_pcfs
- X make install
- X
- XTo configure pcfs into your kernel goto to your configuration file
- Xin the /sys/i386/conf directory and add the following statement:
- X options PCFS
- X
- XThen run the config command.
- X config WHATEVER_YOU_CALL_IT
- X
- XThen goto the your kernel build directory in /sys/compile/WHATEVER_YOU_CALL_IT
- Xand do a "make depend" and then do a make.
- X make depend
- X make
- X
- XThen copy the kernel into the root directory and reboot your system.
- X cp 386bsd /
- X
- XTo mount a pcfs filesystem:
- X mount -t pcfs /dev/fd0a /mnt
- X
- XTo unmount a pcfs filesystem:
- X umount /mnt
- END-of-/sys/pcfs/INSTALL
- echo x - /sys/pcfs/README
- sed 's/^X//' >/sys/pcfs/README << 'END-of-/sys/pcfs/README'
- XThis is version 0.0 of the code to allow mountable DOS filesystems
- Xunder 386bsd 0.1. It is refered as pcfs from now on. No, this is
- Xnot related to sun's pcfs, although they essentially do the same
- Xthing.
- X
- XThis package has been installed on a 386bsd 0.1 system that has NOT
- Xhad the patchkit installed.
- X
- XUnshar each of the following 4 shar files. They create files in
- X/sys/pcfs and /usr/src/sbin/mount_pcfs. They do not overwrite any
- Xexisting files. Once you have them unshared read the /sys/pcfs/INSTALL
- Xfile to find out how to install it and mount pc filesystems. Then look
- Xat the /sys/pcfs/pcfs.8 file for a list of the filesystem's quirks.
- X
- XIf you have problems send me some email and I'll see what I can do.
- XIf you add things please send me the mods and I will try to incorporate
- Xthem for the next release.
- X
- XHave fun,
- XPaul
- Xpaulp@sde.uts.amdahl.com
- END-of-/sys/pcfs/README
- echo x - /sys/pcfs/pcfs.8
- sed 's/^X//' >/sys/pcfs/pcfs.8 << 'END-of-/sys/pcfs/pcfs.8'
- XPCFS quirks file
- X
- XPCFS filesystems on floppy disks only are supported in this release.
- XAnd, only high density floppy disks are supported. This is because
- Xthe floppy disk driver only supports high density disks. PCFS
- Xfilesystems on hard disks are not supported yet. This is because
- Xadditions to the disk drivers to make them better utilize dos
- Xpartition information are required.
- X
- XCreated files use only the user permissions bits. And of these
- Xonly the write bit is meaningful. DOS files always have the
- Xexecute and read bits on.
- X
- XPCFS does not turn on or off the DOS archive attribute bit.
- X
- XThe timestamp on dos files is updated when ever the file is modified.
- XThere is no inode time or create time stamp.
- X
- XThe timestamp placed on a dos file does not have corrections for
- Xdaylight savings time included. It does have the correction for
- Xtimezone though.
- X
- XUnix times before 1980 will have their year set to 1980 in dos file
- Xtimestamps. This is because dos's idea of time starts in 1980.
- X
- XPCFS filesystems do not support sparse files. Any attempt to seek
- Xpast the end of a file results in the blocks being allocated and
- Xcleared.
- X
- XWhen read() is used to examine pcfs directories you will get dos
- Xdirectory contents. Note that the root directory does not contain
- Xa "." or ".." entry. Only the readdir() system call simulates these
- Xentries in the root directory of a dos filesystem. readdir() returns
- Xdirectory entries as described in getdirentries(2).
- X
- XUsing read() and write() to manipulate the contents of dos directories
- Xis unwise on an active dos filesystem since a more up to date copy of
- Xtheir contents may reside in data structures in the kernel. It is
- Xprobably safe to examine the filename field of dos directory entries.
- XThe filesystem code keeps this up to date at all times.
- X
- XThe cluster allocation algorithm is very simplistic. It starts at
- Xcluster 2 and searchs until the last cluster of the filesystem and
- Xtakes the first available cluster.
- X
- XThe fsync() system call does not work on file descriptors open on
- Xdirectories. This isn't a terrible thing since very few programs
- Xopen directories for writing.
- X
- XThe pcfs filesystem truncates filenames quietly. If a filename has
- Xmore than 8 characters before the 1st period only the 1st eigth are
- Xused. It only uses the 1st three characters after the period if
- Xthey exist. The filenames "abc" and "abc." are the same to pcfs.
- XFilenames that begin with a "." are considered to be dos filenames
- Xwith an extension only and so are limited to 3 characters after the
- Xleading ".". For example ".imlost" would be seen as ".iml" by pcfs.
- XPCFS folds filenames to upper case before writing them to disk or
- Xlooking up filenames, and folds them to lower case when reading them
- Xfrom disk for presentation to the user (for example by readdir()).
- X
- XDirectory entries for the DOS filesystem label are quietly ignored.
- X
- XThis is probably going to be a problem. This implementation expects
- Xthe length of the root directory to be a multiple of the size of
- Xa cluster. If this is not true a warning message is printed when
- Xthe filesystem is mounted.
- X
- XPCFS supports DOS filesystems with 12 bit or 16 bit FATs. It supports
- Xboth regular and huge filesystems ( > 32 megabytes). It supports
- Xboth version 3.3 and 5.0 BPB's. Don't know about version 4.x and
- Xless than 3.3. It has not been tested with 16 bit fats or huge
- Xfilesystems. This is because the hard disk drivers need to support
- Xdos partitions to do these things.
- X
- XPCFS does not support symbolic links or hard links. It does not
- Xsupport quotas. How could it, pcfs files have no owners. PCFS
- Xfiles have a simulated owner and group of 0. PCFS does not support
- Xfile locking. Though it may in the future. PCFS filesystems are
- Xnot remote mountable, but they will be in the future.
- X
- XThis is the first release and as such has performance problems.
- XReading large files is very slow because the read ahead code in pcfs_read()
- Xdoesn't read far enough ahead for filesystems with small blocksizes.
- XPerformance and dos hard disk paritions are the next areas to be
- Xworked on. Unless someone else does it.
- X
- X
- XOperational Details
- X-------------------
- X
- XTo mount a pcfs filesystem:
- X mount -t pcfs /dev/fd0a /mnt
- X
- XTo unmount a pcfs filesystem:
- X umount /mnt
- X
- XIf you want to be sure the fat is ALWAYS up to date, mount the
- Xfilesystem with the synchronous option:
- X mount -t pcfs -o synchronous /dev/fd0a /mnt
- XThis reasults in very slow file write performance because it turns
- Xoff write behind of fst disk blocks.
- X
- X
- XConfiguring PCFS into your kernel
- X---------------------------------
- X
- XAdd the following statements to your configuration file in /sys/i386/conf/BLOT.
- XOr whatever you call your config file.
- X
- X options PCFS
- X
- XThen do a "config BLOT" in /sys/i386/conf.
- X
- XThen do a "make depend" in /sys/compile/BLOT.
- X
- XAnd then do a "make" in /sys/compile/BLOT.
- X
- XCopy the kernel to / and boot your system.
- X
- XPCFS consumes approximately 24000 bytes of kernel code space and
- Xapproximately 4000 bytes of bss.
- X
- XPCFS has some debug printf's that can be turned on by defining PCFSDEBUG.
- XIt produces lots of output. If you use it be sure to kill syslogd before
- Xusing a PCFS filesystem with debug.
- END-of-/sys/pcfs/pcfs.8
- echo x - /sys/pcfs/pcfs.cdiff
- sed 's/^X//' >/sys/pcfs/pcfs.cdiff << 'END-of-/sys/pcfs/pcfs.cdiff'
- X*** /sys/sys/vnode.h Tue Dec 24 14:24:19 1991
- X--- /sys/sys/NEWvnode.h Thu Oct 22 21:44:42 1992
- X***************
- X*** 53,59 ****
- X * These are for the benefit of external programs only (e.g., pstat)
- X * and should NEVER be inspected inside the kernel.
- X */
- X! enum vtagtype { VT_NON, VT_UFS, VT_NFS, VT_MFS };
- X
- X /*
- X * This defines the maximum size of the private data area
- X--- 53,59 ----
- X * These are for the benefit of external programs only (e.g., pstat)
- X * and should NEVER be inspected inside the kernel.
- X */
- X! enum vtagtype { VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_PCFS };
- X
- X /*
- X * This defines the maximum size of the private data area
- X*** /sys/sys/mount.h Sun May 24 18:36:01 1992
- X--- /sys/sys/NEWmount.h Thu Oct 22 21:45:47 1992
- X***************
- X*** 76,82 ****
- X #define MOUNT_UFS 1 /* UNIX "Fast" Filesystem */
- X #define MOUNT_NFS 2 /* Network Filesystem */
- X #define MOUNT_MFS 3 /* Memory Filesystem */
- X! #define MOUNT_MSDOS 4 /* MSDOS Filesystem */
- X #define MOUNT_ISOFS 5 /* iso9660 cdrom */
- X #define MOUNT_MAXTYPE 5
- X
- X--- 76,82 ----
- X #define MOUNT_UFS 1 /* UNIX "Fast" Filesystem */
- X #define MOUNT_NFS 2 /* Network Filesystem */
- X #define MOUNT_MFS 3 /* Memory Filesystem */
- X! #define MOUNT_PCFS 4 /* MSDOS Filesystem */
- X #define MOUNT_ISOFS 5 /* iso9660 cdrom */
- X #define MOUNT_MAXTYPE 5
- X
- X***************
- X*** 260,265 ****
- X--- 260,276 ----
- X #define NFSMNT_COMPRESS 0x0800 /* Compress nfs rpc xdr */
- X #define NFSMNT_LOCKBITS (NFSMNT_SCKLOCK | NFSMNT_WANTSCK)
- X #endif NFS
- X+
- X+ #ifdef PCFS
- X+ /*
- X+ * Arguments to mount MSDOS filesystems.
- X+ */
- X+ struct pcfs_args {
- X+ char *fspec; /* blocks special holding the fs to mount */
- X+ int exflags; /* mount flags */
- X+ uid_t exroot; /* mapping for root uid */
- X+ };
- X+ #endif /* PCFS */
- X
- X #ifdef KERNEL
- X /*
- X*** /sys/sys/malloc.h Tue Dec 24 14:24:17 1991
- X--- /sys/sys/NEWmalloc.h Thu Oct 22 21:46:27 1992
- X***************
- X*** 91,97 ****
- X #define M_PROC 41 /* Proc structures */
- X #define M_SUBPROC 42 /* Proc sub-structures */
- X #define M_TEMP 49 /* misc temporary data buffers */
- X! #define M_LAST 50
- X
- X #define INITKMEMNAMES { \
- X "free", /* 0 M_FREE */ \
- X--- 91,99 ----
- X #define M_PROC 41 /* Proc structures */
- X #define M_SUBPROC 42 /* Proc sub-structures */
- X #define M_TEMP 49 /* misc temporary data buffers */
- X! #define M_PCFSMNT 50 /* PCFS mount structure */
- X! #define M_PCFSFAT 51 /* PCFS fat table */
- X! #define M_LAST 52
- X
- X #define INITKMEMNAMES { \
- X "free", /* 0 M_FREE */ \
- X***************
- X*** 139,144 ****
- X--- 141,148 ----
- X "subproc", /* 42 M_PROC */ \
- X 0, 0, 0, 0, 0, 0, \
- X "temp", /* 49 M_TEMP */ \
- X+ "PCFS mount", /* 50 M_PCFSMNT */ \
- X+ "PCFS fat", /* 51 M_PCFSFAT */ \
- X }
- X
- X struct kmemstats {
- X*** /sys/conf/files Mon May 25 12:26:27 1992
- X--- /sys/conf/NEWfiles Thu Oct 22 21:48:05 1992
- X***************
- X*** 214,216 ****
- X--- 214,222 ----
- X ddb/db_variables.c optional ddb
- X ddb/db_watch.c optional ddb
- X ddb/db_write_cmd.c optional ddb
- X+ pcfs/pcfs_fat.c optional pcfs
- X+ pcfs/pcfs_conv.c optional pcfs
- X+ pcfs/pcfs_denode.c optional pcfs
- X+ pcfs/pcfs_lookup.c optional pcfs
- X+ pcfs/pcfs_vfsops.c optional pcfs
- X+ pcfs/pcfs_vnops.c optional pcfs
- X*** /sys/kern/vfs_conf.c Mon May 25 02:43:56 1992
- X--- /sys/kern/NEWvfs_conf.c Thu Oct 22 21:48:58 1992
- X***************
- X*** 63,68 ****
- X--- 63,72 ----
- X extern struct vfsops mfs_vfsops;
- X #endif
- X
- X+ #ifdef PCFS
- X+ extern struct vfsops pcfs_vfsops;
- X+ #endif
- X+
- X #ifdef ISOFS
- X extern struct vfsops isofs_vfsops;
- X #endif
- X***************
- X*** 80,86 ****
- X #else
- X (struct vfsops *)0,
- X #endif
- X! (struct vfsops *)0, /* 4 = MOUNT_MSDOS */
- X #ifdef ISOFS
- X &isofs_vfsops, /* 5 = MOUNT_ISOFS */
- X #else
- X--- 84,94 ----
- X #else
- X (struct vfsops *)0,
- X #endif
- X! #ifdef PCFS
- X! &pcfs_vfsops, /* 4 = MOUNT_PCFS */
- X! #else
- X! (struct vfsops *)0,
- X! #endif
- X #ifdef ISOFS
- X &isofs_vfsops, /* 5 = MOUNT_ISOFS */
- X #else
- END-of-/sys/pcfs/pcfs.cdiff
- echo x - /sys/pcfs/fat.h
- sed 's/^X//' >/sys/pcfs/fat.h << 'END-of-/sys/pcfs/fat.h'
- X/*
- X * Some useful cluster numbers.
- X */
- X#define PCFSROOT 0 /* cluster 0 means the root dir */
- X#define CLUST_FREE 0 /* cluster 0 also means a free cluster */
- X#define PCFSFREE CLUST_FREE
- X#define CLUST_FIRST 2 /* first legal cluster number */
- X#define CLUST_RSRVS 0xfff0 /* start of reserved cluster range */
- X#define CLUST_RSRVE 0xfff6 /* end of reserved cluster range */
- X#define CLUST_BAD 0xfff7 /* a cluster with a defect */
- X#define CLUST_EOFS 0xfff8 /* start of eof cluster range */
- X#define CLUST_EOFE 0xffff /* end of eof cluster range */
- X
- X#define FAT12_MASK 0x0fff /* mask for 12 bit cluster numbers */
- X#define FAT16_MASK 0xffff /* mask for 16 bit cluster numbers */
- X
- X/*
- X * Return true if filesystem uses 12 bit fats.
- X * Microsoft Programmer's Reference says if the
- X * maximum cluster number in a filesystem is greater
- X * than 4086 then we've got a 16 bit fat filesystem.
- X */
- X#define FAT12(pmp) (pmp->pm_maxcluster <= 4086)
- X#define FAT16(pmp) (pmp->pm_maxcluster > 4086)
- X
- X#define PCFSEOF(cn) (((cn) & 0xfff8) == 0xfff8)
- X
- X/*
- X * These are the values for the function argument to
- X * the function fatentry().
- X */
- X#define FAT_GET 0x0001 /* get a fat entry */
- X#define FAT_SET 0x0002 /* set a fat entry */
- X#define FAT_GET_AND_SET (FAT_GET | FAT_SET)
- X
- X/*
- X * This union is useful for manipulating entries
- X * in 12 bit fats.
- X */
- Xunion fattwiddle {
- X unsigned short word;
- X unsigned char byte[2];
- X};
- X
- X#if defined(KERNEL)
- Xint pcbmap __P((struct denode *dep,
- X unsigned long findcn,
- X daddr_t *bnp,
- X unsigned long *cnp));
- Xint clusterfree __P((struct pcfsmount *pmp, unsigned long cn));
- Xint clusteralloc __P((struct pcfsmount *pmp, unsigned long *retcluster,
- X unsigned long fillwith));
- Xint fatentry __P((int function, struct pcfsmount *pmp,
- X unsigned long cluster,
- X unsigned long *oldcontents,
- X unsigned long newcontents));
- Xint freeclusterchain __P((struct pcfsmount *pmp, unsigned long startchain));
- X#endif /* defined(KERNEL) */
- END-of-/sys/pcfs/fat.h
- echo x - /sys/pcfs/direntry.h
- sed 's/^X//' >/sys/pcfs/direntry.h << 'END-of-/sys/pcfs/direntry.h'
- X/*
- X * Structure of a dos directory entry.
- X */
- Xstruct direntry {
- X unsigned char deName[8]; /* filename, blank filled */
- X#define SLOT_EMPTY 0x00 /* slot has never been used */
- X#define SLOT_E5 0x05 /* the real value is 0xe5 */
- X#define SLOT_DELETED 0xe5 /* file in this slot deleted */
- X unsigned char deExtension[3]; /* extension, blank filled */
- X unsigned char deAttributes; /* file attributes */
- X#define ATTR_NORMAL 0x00 /* normal file */
- X#define ATTR_READONLY 0x01 /* file is readonly */
- X#define ATTR_HIDDEN 0x02 /* file is hidden */
- X#define ATTR_SYSTEM 0x04 /* file is a system file */
- X#define ATTR_VOLUME 0x08 /* entry is a volume label */
- X#define ATTR_DIRECTORY 0x10 /* entry is a directory name */
- X#define ATTR_ARCHIVE 0x20 /* file is new or modified */
- X char deReserved[10]; /* reserved */
- X unsigned short deTime; /* create/last update time */
- X unsigned short deDate; /* create/last update date */
- X unsigned short deStartCluster; /* starting cluster of file */
- X unsigned long deFileSize; /* size of file in bytes */
- X};
- X
- X/*
- X * This is the format of the contents of the deTime
- X * field in the direntry structure.
- X */
- Xstruct DOStime {
- X unsigned short
- X dt_2seconds:5, /* seconds divided by 2 */
- X dt_minutes:6, /* minutes */
- X dt_hours:5; /* hours */
- X};
- X
- X/*
- X * This is the format of the contents of the deDate
- X * field in the direntry structure.
- X */
- Xstruct DOSdate {
- X unsigned short
- X dd_day:5, /* day of month */
- X dd_month:4, /* month */
- X dd_year:7; /* years since 1980 */
- X};
- X
- Xunion dostime {
- X struct DOStime dts;
- X unsigned short dti;
- X};
- X
- Xunion dosdate {
- X struct DOSdate dds;
- X unsigned short ddi;
- X};
- X
- X/*
- X * The following defines are used to rename fields in
- X * the ufs_specific structure in the nameidata structure
- X * in namei.h
- X */
- X#define ni_pcfs ni_ufs
- X#define pcfs_count ufs_count
- X#define pcfs_offset ufs_offset
- X#define pcfs_cluster ufs_ino
- X
- X#if defined(KERNEL)
- Xvoid unix2dostime __P((struct timeval *tvp,
- X union dosdate *ddp,
- X union dostime *dtp));
- Xvoid dos2unixtime __P((union dosdate *ddp,
- X union dostime *dtp,
- X struct timeval *tvp));
- Xint dos2unixfn __P((unsigned char dn[11], unsigned char *un));
- Xvoid unix2dosfn __P((unsigned char *un, unsigned char dn[11], int unlen));
- X#endif /* defined(KERNEL) */
- END-of-/sys/pcfs/direntry.h
- echo x - /sys/pcfs/denode.h
- sed 's/^X//' >/sys/pcfs/denode.h << 'END-of-/sys/pcfs/denode.h'
- X/*
- X * Written by Paul Popelka (paulp@uts.amdahl.com)
- X *
- X * You can do anything you want with this software,
- X * just don't say you wrote it,
- X * and don't remove this notice.
- X *
- X * This software is provided "as is".
- X *
- X * The author supplies this software to be publicly
- X * redistributed on the understanding that the author
- X * is not responsible for the correct functioning of
- X * this software in any circumstances and is not liable
- X * for any damages caused by this software.
- X *
- X * October 1992
- X */
- X/*
- X * This is the pc filesystem specific portion of the
- X * vnode structure.
- X * To describe a file uniquely the de_dirclust, de_diroffset,
- X * and de_de.deStartCluster fields are used. de_dirclust
- X * contains the cluster number of the directory cluster containing
- X * the entry for a file or directory. de_diroffset is the
- X * index into the cluster for the entry describing a file
- X * or directory. de_de.deStartCluster is the number of the
- X * first cluster of the file or directory. Now to describe the
- X * quirks of the pc filesystem.
- X * - Clusters 0 and 1 are reserved.
- X * - The first allocatable cluster is 2.
- X * - The root directory is of fixed size and all blocks that
- X * make it up are contiguous.
- X * - Cluster 0 refers to the root directory when it is found
- X * in the startcluster field of a directory entry that points
- X * to another directory.
- X * - Cluster 0 implies a 0 length file when found in the start
- X * cluster field of a directory entry that points to a file.
- X * - You can't use the cluster number 0 to derive
- X * the address of the root directory.
- X * - Multiple directory entries can point to a directory.
- X * The entry in the parent directory points to a child
- X * directory. Any directories in the child directory contain
- X * a ".." entry that points back to the child. The child
- X * directory itself contains a "." entry that points to
- X * itself.
- X * - The root directory does not contain a "." or ".." entry.
- X * - Directory entries for directories are never changed once
- X * they are created (except when removed). The size stays
- X * 0, and the last modification time is never changed. This
- X * is because so many directory entries can point to the physical
- X * clusters that make up a directory. It would lead to an update
- X * nightmare.
- X * - The length field in a directory entry pointing to a directory
- X * contains 0 (always). The only way to find the end of a directory
- X * is to follow the cluster chain until the "last cluster"
- X * marker is found.
- X * My extensions to make this house of cards work. These apply
- X * only to the in memory copy of the directory entry.
- X * - A reference count for each denode will be kept since dos doesn't
- X * keep such things.
- X */
- X
- X/*
- X * The fat cache structure.
- X * fc_fsrcn is the filesystem relative cluster number
- X * that corresponds to the file relative cluster number
- X * in this structure (fc_frcn).
- X */
- Xstruct fatcache {
- X unsigned short fc_frcn; /* file relative cluster number */
- X unsigned short fc_fsrcn; /* filesystem relative cluster number */
- X};
- X
- X/*
- X * The fat entry cache as it stands helps make extending
- X * files a "quick" operation by avoiding having to scan
- X * the fat to discover the last cluster of the file.
- X * The cache also helps sequential reads by remembering
- X * the last cluster read from the file. This also prevents
- X * us from having to rescan the fat to find the next cluster
- X * to read. This cache is probably pretty worthless if a
- X * file is opened by multiple processes.
- X */
- X#define FC_SIZE 2 /* number of entries in the cache */
- X#define FC_LASTMAP 0 /* entry the last call to pcbmap() resolved to */
- X#define FC_LASTFC 1 /* entry for the last cluster in the file */
- X
- X#define FCE_EMPTY 0xffff /* doesn't represent an actual cluster # */
- X
- X/*
- X * Set a slot in the fat cache.
- X */
- X#define fc_setcache(dep, slot, frcn, fsrcn) \
- X (dep)->de_fc[slot].fc_frcn = frcn; \
- X (dep)->de_fc[slot].fc_fsrcn = fsrcn;
- X
- X/*
- X * This is the in memory variant of a dos directory
- X * entry. It is usually contained within a vnode.
- X */
- Xstruct denode {
- X struct denode *de_chain[2]; /* hash chain ptrs */
- X struct vnode *de_vnode; /* addr of vnode we are part of */
- X struct vnode *de_devvp; /* vnode of blk dev we live on */
- X u_long de_flag; /* flag bits */
- X dev_t de_dev; /* device where direntry lives */
- X u_long de_dirclust; /* cluster of the directory file
- X * containing this entry */
- X u_long de_diroffset; /* ordinal of this entry in the
- X * directory */
- X long de_refcnt; /* reference count */
- X struct pcfsmount *de_pmp; /* addr of our mount struct */
- X struct lockf *de_lockf; /* byte level lock list */
- X long de_spare0; /* current lock holder */
- X long de_spare1; /* lock wanter */
- X struct direntry de_de; /* the actual directory entry */
- X struct fatcache de_fc[FC_SIZE]; /* fat cache */
- X};
- X
- X/*
- X * Values for the de_flag field of the denode.
- X */
- X#define DELOCKED 0x0001 /* directory entry is locked */
- X#define DEWANT 0x0002 /* someone wants this de */
- X#define DERENAME 0x0004 /* de is being renamed */
- X#define DEUPD 0x0008 /* file has been modified */
- X#define DESHLOCK 0x0010 /* file has shared lock */
- X#define DEEXLOCK 0x0020 /* file has exclusive lock */
- X#define DELWAIT 0x0040 /* someone waiting on file lock */
- X#define DEMOD 0x0080 /* denode wants to be written back
- X * to disk */
- X
- X/*
- X * Shorthand macros used to reference fields in the direntry
- X * contained in the denode structure.
- X */
- X#define de_Name de_de.deName
- X#define de_Extension de_de.deExtension
- X#define de_Attributes de_de.deAttributes
- X#define de_Reserved de_de.deReserved
- X#define de_Time de_de.deTime
- X#define de_Date de_de.deDate
- X#define de_StartCluster de_de.deStartCluster
- X#define de_FileSize de_de.deFileSize
- X#define de_forw de_chain[0]
- X#define de_back de_chain[1]
- X
- X#if defined(KERNEL)
- X
- X#define VTODE(vp) ((struct denode *)(vp)->v_data)
- X#define DETOV(de) ((de)->de_vnode)
- X
- X#define DELOCK(de) delock(de)
- X#define DEUNLOCK(de) deunlock(de)
- X
- X#define DEUPDAT(dep, t, waitfor) \
- X if (dep->de_flag & DEUPD) \
- X (void) deupdat(dep, t, waitfor);
- X
- X#define DETIMES(dep, t) \
- X if (dep->de_flag & DEUPD) { \
- X (dep)->de_flag |= DEMOD; \
- X unix2dostime(t, (union dosdate *)&dep->de_Date, \
- X (union dostime *)&dep->de_Time); \
- X (dep)->de_flag &= ~DEUPD; \
- X }
- X
- X/*
- X * Prototypes for PCFS vnode operations
- X */
- Xint pcfs_lookup __P((struct vnode *vp, struct nameidata *ndp, struct proc *p));
- Xint pcfs_create __P((struct nameidata *ndp, struct vattr *vap, struct proc *p));
- Xint pcfs_mknod __P((struct nameidata *ndp, struct vattr *vap, struct ucred *cred,
- X struct proc *p));
- Xint pcfs_open __P((struct vnode *vp, int mode, struct ucred *cred,
- X struct proc *p));
- Xint pcfs_close __P((struct vnode *vp, int fflag, struct ucred *cred,
- X struct proc *p));
- Xint pcfs_access __P((struct vnode *vp, int mode, struct ucred *cred,
- X struct proc *p));
- Xint pcfs_getattr __P((struct vnode *vp, struct vattr *vap, struct ucred *cred,
- X struct proc *p));
- Xint pcfs_setattr __P((struct vnode *vp, struct vattr *vap, struct ucred *cred,
- X struct proc *p));
- Xint pcfs_read __P((struct vnode *vp, struct uio *uio, int ioflag,
- X struct ucred *cred));
- Xint pcfs_write __P((struct vnode *vp, struct uio *uio, int ioflag,
- X struct ucred *cred));
- Xint pcfs_ioctl __P((struct vnode *vp, int command, caddr_t data, int fflag,
- X struct ucred *cred, struct proc *p));
- Xint pcfs_select __P((struct vnode *vp, int which, int fflags, struct ucred *cred,
- X struct proc *p));
- Xint pcfs_mmap __P((struct vnode *vp, int fflags, struct ucred *cred,
- X struct proc *p));
- Xint pcfs_fsync __P((struct vnode *vp, int fflags, struct ucred *cred,
- X int waitfor, struct proc *p));
- Xint pcfs_seek __P((struct vnode *vp, off_t oldoff, off_t newoff,
- X struct ucred *cred));
- Xint pcfs_remove __P((struct nameidata *ndp, struct proc *p));
- Xint pcfs_link __P((struct vnode *vp, struct nameidata *ndp, struct proc *p));
- Xint pcfs_rename __P((struct nameidata *fndp, struct nameidata *tdnp,
- X struct proc *p));
- Xint pcfs_mkdir __P((struct nameidata *ndp, struct vattr *vap, struct proc *p));
- Xint pcfs_rmdir __P((struct nameidata *ndp, struct proc *p));
- Xint pcfs_symlink __P((struct nameidata *ndp, struct vattr *vap, char *target,
- X struct proc *p));
- Xint pcfs_readdir __P((struct vnode *vp, struct uio *uio, struct ucred *cred,
- X int *eofflagp));
- Xint pcfs_readlink __P((struct vnode *vp, struct uio *uio, struct ucred *cred));
- Xint pcfs_abortop __P((struct nameidata *ndp));
- Xint pcfs_inactive __P((struct vnode *vp, struct proc *p));
- Xint pcfs_reclaim __P((struct vnode *vp));
- Xint pcfs_lock __P((struct vnode *vp));
- Xint pcfs_unlock __P((struct vnode *vp));
- Xint pcfs_bmap __P((struct vnode *vp, daddr_t bn, struct vnode **vpp,
- X daddr_t *bnp));
- Xint pcfs_strategy __P((struct buf *bp));
- Xint pcfs_print __P((struct vnode *vp));
- Xint pcfs_islocked __P((struct vnode *vp));
- Xint pcfs_advlock __P((struct vnode *vp, caddr_t id, int op, struct flock *fl,
- X int flags));
- X
- X/*
- X * Internal service routine prototypes.
- X */
- Xint deget __P((struct pcfsmount *pmp, int isadir, unsigned long dirclust,
- X unsigned long diroffset, unsigned long startclust,
- X struct buf *bp, struct denode **depp));
- X#endif /* defined(KERNEL) */
- END-of-/sys/pcfs/denode.h
- echo x - /sys/pcfs/bpb.h
- sed 's/^X//' >/sys/pcfs/bpb.h << 'END-of-/sys/pcfs/bpb.h'
- X/*
- X * BIOS Parameter Block (BPB) for DOS 3.3
- X */
- Xstruct bpb33 {
- X u_short bpbBytesPerSec; /* bytes per sector */
- X u_char bpbSecPerClust; /* sectors per cluster */
- X u_short bpbResSectors; /* number of reserved sectors */
- X u_char bpbFATs; /* number of FATs */
- X u_short bpbRootDirEnts; /* number of root directory entries */
- X u_short bpbSectors; /* total number of sectors */
- X u_char bpbMedia; /* media descriptor */
- X u_short bpbFATsecs; /* number of sectors per FAT */
- X u_short bpbSecPerTrack; /* sectors per track */
- X u_short bpbHeads; /* number of heads */
- X u_short bpbHiddenSecs; /* number of hidden sectors */
- X};
- X
- X/*
- X * BPB for DOS 5.0
- X * The difference is bpbHiddenSecs is a short for DOS 3.3,
- X * and bpbHugeSectors is not in the 3.3 bpb.
- X */
- Xstruct bpb50 {
- X u_short bpbBytesPerSec; /* bytes per sector */
- X u_char bpbSecPerClust; /* sectors per cluster */
- X u_short bpbResSectors; /* number of reserved sectors */
- X u_char bpbFATs; /* number of FATs */
- X u_short bpbRootDirEnts; /* number of root directory entries */
- X u_short bpbSectors; /* total number of sectors */
- X u_char bpbMedia; /* media descriptor */
- X u_short bpbFATsecs; /* number of sectors per FAT */
- X u_short bpbSecPerTrack; /* sectors per track */
- X u_short bpbHeads; /* number of heads */
- X u_long bpbHiddenSecs; /* number of hidden sectors */
- X u_long bpbHugeSectors; /* number of sectrs if bpbSectors == 0 */
- X};
- X
- X/*
- X * The following structures represent how the bpb's look
- X * on disk. shorts and longs are just character arrays
- X * of the appropriate length. This is because the compiler
- X * forces shorts and longs to align on word or halfword
- X * boundaries.
- X */
- X#define getushort(x) *((unsigned short *)(x))
- X#define getulong(x) *((unsigned long *)(x))
- X
- X/*
- X * BIOS Parameter Block (BPB) for DOS 3.3
- X */
- Xstruct byte_bpb33 {
- X char bpbBytesPerSec[2]; /* bytes per sector */
- X char bpbSecPerClust; /* sectors per cluster */
- X char bpbResSectors[2]; /* number of reserved sectors */
- X char bpbFATs; /* number of FATs */
- X char bpbRootDirEnts[2]; /* number of root directory entries */
- X char bpbSectors[2]; /* total number of sectors */
- X char bpbMedia; /* media descriptor */
- X char bpbFATsecs[2]; /* number of sectors per FAT */
- X char bpbSecPerTrack[2]; /* sectors per track */
- X char bpbHeads[2]; /* number of heads */
- X char bpbHiddenSecs[2]; /* number of hidden sectors */
- X};
- X
- X/*
- X * BPB for DOS 5.0
- X * The difference is bpbHiddenSecs is a short for DOS 3.3,
- X * and bpbHugeSectors is not in the 3.3 bpb.
- X */
- Xstruct byte_bpb50 {
- X char bpbBytesPerSec[2]; /* bytes per sector */
- X char bpbSecPerClust; /* sectors per cluster */
- X char bpbResSectors[2]; /* number of reserved sectors */
- X char bpbFATs; /* number of FATs */
- X char bpbRootDirEnts[2]; /* number of root directory entries */
- X char bpbSectors[2]; /* total number of sectors */
- X char bpbMedia; /* media descriptor */
- X char bpbFATsecs[2]; /* number of sectors per FAT */
- X char bpbSecPerTrack[2]; /* sectors per track */
- X char bpbHeads[2]; /* number of heads */
- X char bpbHiddenSecs[4]; /* number of hidden sectors */
- X char bpbHugeSectors[4]; /* number of sectrs if bpbSectors == 0 */
- X};
- END-of-/sys/pcfs/bpb.h
- echo x - /sys/pcfs/bootsect.h
- sed 's/^X//' >/sys/pcfs/bootsect.h << 'END-of-/sys/pcfs/bootsect.h'
- X/*
- X * Format of a boot sector. This is the first sector
- X * on a DOS floppy disk or the fist sector of a partition
- X * on a hard disk. But, it is not the first sector of
- X * a partitioned hard disk.
- X */
- Xstruct bootsector33 {
- X char bsJump[3]; /* jump instruction E9xxxx or EBxx90 */
- X char bsOemName[8]; /* OEM name and version */
- X char bsBPB[19]; /* BIOS parameter block */
- X char bsDriveNumber; /* drive number (0x80) */
- X char bsBootCode[474]; /* pad so structure is 512 bytes long */
- X unsigned short bsBootSectSig;
- X#define BOOTSIG 0xaa55
- X};
- X
- Xstruct bootsector50 {
- X char bsJump[3]; /* jump instruction E9xxxx or EBxx90 */
- X char bsOemName[8]; /* OEM name and version */
- X char bsBPB[25]; /* BIOS parameter block */
- X char bsDriveNumber; /* drive number (0x80) */
- X char bsReserved1; /* reserved */
- X char bsBootSignature; /* extended boot signature (0x29) */
- X#define EXBOOTSIG 0x29
- X char bsVolumeID[4]; /* volume ID number */
- X char bsVolumeLabel[11]; /* volume label */
- X char bsFileSysType[8]; /* file system type (FAT12 or FAT16) */
- X char bsBootCode[448]; /* pad so structure is 512 bytes long */
- X unsigned short bsBootSectSig;
- X#define BOOTSIG 0xaa55
- X};
- X
- Xunion bootsector {
- X struct bootsector33 bs33;
- X struct bootsector50 bs50;
- X};
- X
- X/*
- X * Shorthand for fields in the bpb.
- X */
- X#define bsBytesPerSec bsBPB.bpbBytesPerSec
- X#define bsSectPerClust bsBPB.bpbSectPerClust
- X#define bsResSectors bsBPB.bpbResSectors
- X#define bsFATS bsBPB.bpbFATS
- X#define bsRootDirEnts bsBPB.bpbRootDirEnts
- X#define bsSectors bsBPB.bpbSectors
- X#define bsMedia bsBPB.bpbMedia
- X#define bsFATsecs bsBPB.bpbFATsecs
- X#define bsSectPerTrack bsBPB.bpbSectPerTrack
- X#define bsHeads bsBPB.bpbHeads
- X#define bsHiddenSecs bsBPB.bpbHiddenSecs
- X#define bsHugeSectors bsBPB.bpbHugeSectors
- END-of-/sys/pcfs/bootsect.h
- echo x - /sys/pcfs/pcfsmount.h
- sed 's/^X//' >/sys/pcfs/pcfsmount.h << 'END-of-/sys/pcfs/pcfsmount.h'
- X/*
- X * Written by Paul Popelka (paulp@uts.amdahl.com)
- X *
- X * You can do anything you want with this software,
- X * just don't say you wrote it,
- X * and don't remove this notice.
- X *
- X * This software is provided "as is".
- X *
- X * The author supplies this software to be publicly
- X * redistributed on the understanding that the author
- X * is not responsible for the correct functioning of
- X * this software in any circumstances and is not liable
- X * for any damages caused by this software.
- X *
- X * October 1992
- X */
- X
- X/*
- X * Layout of the mount control block for a msdos
- X * file system.
- X */
- Xstruct pcfsmount {
- X struct mount *pm_mountp; /* vfs mount struct for this fs */
- X dev_t pm_dev; /* block special device mounted */
- X struct vnode *pm_devvp; /* vnode for block device mntd */
- X struct bpb50 pm_bpb; /* BIOS parameter blk for this fs */
- X long pm_fatblk; /* block # of first FAT */
- X long pm_rootdirblk; /* block # of root directory */
- X long pm_rootdirsize; /* size in blocks (not clusters) */
- X long pm_firstcluster; /* block number of first cluster */
- X long pm_nmbrofclusters; /* # of clusters in filesystem */
- X long pm_maxcluster; /* maximum cluster number */
- X long pm_freeclustercount; /* number of free clusters */
- X long pm_lookhere; /* start free cluster search here */
- X long pm_bnshift; /* shift file offset right this
- X * amount to get a block number */
- X long pm_brbomask; /* and a file offset with this
- X * mask to get block rel offset */
- X long pm_cnshift; /* shift file offset right this
- X * amount to get a cluster number */
- X long pm_crbomask; /* and a file offset with this
- X * mask to get cluster rel offset */
- X long pm_bpcluster; /* bytes per cluster */
- X long pm_depclust; /* directory entries per cluster */
- X long pm_fmod; /* ~0 if fs is modified, this can
- X * rollover to 0 */
- X char pm_ronly; /* read only if non-zero */
- X char pm_waitonfat; /* wait for writes of the fat to complt,
- X * when 0 use bdwrite, else use bwrite */
- X unsigned char *pm_inusemap; /* ptr to bitmap of in-use clusters */
- X};
- X/*
- X * How to compute pm_cnshift and pm_crbomask.
- X *
- X * pm_crbomask = (pm_SectPerClust * pm_BytesPerSect) - 1
- X * if (bytesperclust == 0) return EBADBLKSZ;
- X * bit = 1;
- X * for (i = 0; i < 32; i++) {
- X * if (bit & bytesperclust) {
- X * if (bit ^ bytesperclust) return EBADBLKSZ;
- X * pm_cnshift = i;
- X * break;
- X * }
- X * bit <<= 1;
- X * }
- X */
- X
- X/*
- X * Shorthand for fields in the bpb contained in
- X * the pcfsmount structure.
- X */
- X#define pm_BytesPerSec pm_bpb.bpbBytesPerSec
- X#define pm_SectPerClust pm_bpb.bpbSecPerClust
- X#define pm_ResSectors pm_bpb.bpbResSectors
- X#define pm_FATs pm_bpb.bpbFATs
- X#define pm_RootDirEnts pm_bpb.bpbRootDirEnts
- X#define pm_Sectors pm_bpb.bpbSectors
- X#define pm_Media pm_bpb.bpbMedia
- X#define pm_FATsecs pm_bpb.bpbFATsecs
- X#define pm_SecPerTrack pm_bpb.bpbSecPerTrack
- X#define pm_Heads pm_bpb.bpbHeads
- X#define pm_HiddenSects pm_bpb.bpbHiddenSecs
- X#define pm_HugeSectors pm_bpb.bpbHugeSectors
- X
- X/*
- X * Map a cluster number into a filesystem relative
- X * block number.
- X */
- X#define cntobn(pmp, cn) \
- X ((((cn)-CLUST_FIRST) * (pmp)->pm_SectPerClust) + (pmp)->pm_firstcluster)
- X
- X/*
- X * Map a filesystem relative block number back into
- X * a cluster number.
- X */
- X#define bntocn(pmp, bn) \
- X ((((bn) - pmp->pm_firstcluster)/ (pmp)->pm_SectPerClust) + CLUST_FIRST)
- X
- X/*
- X * Prototypes for PCFS virtual filesystem operations
- X */
- Xint pcfs_mount __P((struct mount *mp, char *path, caddr_t data,
- X struct nameidata *ndp, struct proc *p));
- Xint pcfs_start __P((struct mount *mp, int flags, struct proc *p));
- Xint pcfs_unmount __P((struct mount *mp, int mntflags, struct proc *p));
- Xint pcfs_root __P((struct mount *mp, struct vnode **vpp));
- Xint pcfs_quotactl __P((struct mount *mp, int cmds, int uid, /* should be uid_t */
- X caddr_t arg, struct proc *p));
- Xint pcfs_statfs __P((struct mount *mp, struct statfs *sbp, struct proc *p));
- Xint pcfs_sync __P((struct mount *mp, int waitfor));
- Xint pcfs_fhtovp __P((struct mount *mp, struct fid *fhp, struct vnode **vpp));
- Xint pcfs_vptofh __P((struct vnode *vp, struct fid *fhp));
- Xint pcfs_init __P(());
- END-of-/sys/pcfs/pcfsmount.h
- echo c - /usr/src/sbin/mount_pcfs
- mkdir /usr/src/sbin/mount_pcfs > /dev/null 2>&1
- echo x - /usr/src/sbin/mount_pcfs/mount_pcfs.c
- sed 's/^X//' >/usr/src/sbin/mount_pcfs/mount_pcfs.c << 'END-of-/usr/src/sbin/mount_pcfs/mount_pcfs.c'
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/mount.h>
- X
- Xchar *progname;
- X
- Xvoid
- Xusage ()
- X{
- X fprintf (stderr, "usage: %s bdev dir\n", progname);
- X exit (1);
- X}
- X
- Xint
- Xmain (argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X char *dev;
- X char *dir;
- X struct pcfs_args args;
- X int c;
- X extern char *optarg;
- X extern int optind;
- X int opts;
- X
- X progname = argv[0];
- X
- X opts = 0;
- X
- X while ((c = getopt (argc, argv, "F:")) != EOF) {
- X switch (c) {
- X case 'F':
- X opts |= atoi (optarg);
- X break;
- X default:
- X usage ();
- X }
- X }
- X
- X if (optind + 2 != argc)
- X usage ();
- X
- X dev = argv[optind];
- X dir = argv[optind + 1];
- X
- X args.fspec = dev;
- X args.exflags = 0;
- X args.exroot = 0;
- X
- X if (mount (MOUNT_PCFS, dir, opts, &args) < 0) {
- X perror ("mount");
- X exit (1);
- X }
- X
- X exit (0);
- X}
- END-of-/usr/src/sbin/mount_pcfs/mount_pcfs.c
- echo x - /usr/src/sbin/mount_pcfs/Makefile
- sed 's/^X//' >/usr/src/sbin/mount_pcfs/Makefile << 'END-of-/usr/src/sbin/mount_pcfs/Makefile'
- XPROG = mount_pcfs
- XCFLAGS += -DPCFS
- XNOMAN = noman
- X
- X.include <bsd.prog.mk>
- END-of-/usr/src/sbin/mount_pcfs/Makefile
- exit
-
-