Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* |
2 | * Written by Paul Popelka (paulp@uts.amdahl.com) | |
3 | * | |
4 | * You can do anything you want with this software, | |
5 | * just don't say you wrote it, | |
6 | * and don't remove this notice. | |
7 | * | |
8 | * This software is provided "as is". | |
9 | * | |
10 | * The author supplies this software to be publicly | |
11 | * redistributed on the understanding that the author | |
12 | * is not responsible for the correct functioning of | |
13 | * this software in any circumstances and is not liable | |
14 | * for any damages caused by this software. | |
15 | * | |
16 | * October 1992 | |
17 | * | |
78ed81a3 | 18 | * $Id$ |
15637ed4 RG |
19 | */ |
20 | ||
21 | /* | |
22 | * This is the pc filesystem specific portion of the | |
23 | * vnode structure. | |
24 | * To describe a file uniquely the de_dirclust, de_diroffset, | |
25 | * and de_de.deStartCluster fields are used. de_dirclust | |
26 | * contains the cluster number of the directory cluster containing | |
27 | * the entry for a file or directory. de_diroffset is the | |
28 | * index into the cluster for the entry describing a file | |
29 | * or directory. de_de.deStartCluster is the number of the | |
30 | * first cluster of the file or directory. Now to describe the | |
31 | * quirks of the pc filesystem. | |
32 | * - Clusters 0 and 1 are reserved. | |
33 | * - The first allocatable cluster is 2. | |
34 | * - The root directory is of fixed size and all blocks that | |
35 | * make it up are contiguous. | |
36 | * - Cluster 0 refers to the root directory when it is found | |
37 | * in the startcluster field of a directory entry that points | |
38 | * to another directory. | |
39 | * - Cluster 0 implies a 0 length file when found in the start | |
40 | * cluster field of a directory entry that points to a file. | |
41 | * - You can't use the cluster number 0 to derive | |
42 | * the address of the root directory. | |
43 | * - Multiple directory entries can point to a directory. | |
44 | * The entry in the parent directory points to a child | |
45 | * directory. Any directories in the child directory contain | |
46 | * a ".." entry that points back to the child. The child | |
47 | * directory itself contains a "." entry that points to | |
48 | * itself. | |
49 | * - The root directory does not contain a "." or ".." entry. | |
50 | * - Directory entries for directories are never changed once | |
51 | * they are created (except when removed). The size stays | |
52 | * 0, and the last modification time is never changed. This | |
53 | * is because so many directory entries can point to the physical | |
54 | * clusters that make up a directory. It would lead to an update | |
55 | * nightmare. | |
56 | * - The length field in a directory entry pointing to a directory | |
57 | * contains 0 (always). The only way to find the end of a directory | |
58 | * is to follow the cluster chain until the "last cluster" | |
59 | * marker is found. | |
60 | * My extensions to make this house of cards work. These apply | |
61 | * only to the in memory copy of the directory entry. | |
62 | * - A reference count for each denode will be kept since dos doesn't | |
63 | * keep such things. | |
64 | */ | |
65 | ||
66 | /* Internal pseudo-offset for (nonexistent) directory entry for the root dir | |
67 | * in the root dir */ | |
68 | #define PCFSROOT_OFS 0x1fffffff | |
69 | ||
70 | /* | |
71 | * The fat cache structure. | |
72 | * fc_fsrcn is the filesystem relative cluster number | |
73 | * that corresponds to the file relative cluster number | |
74 | * in this structure (fc_frcn). | |
75 | */ | |
76 | struct fatcache { | |
77 | u_short fc_frcn; /* file relative cluster number */ | |
78 | u_short fc_fsrcn; /* filesystem relative cluster number */ | |
79 | }; | |
80 | ||
81 | /* | |
82 | * The fat entry cache as it stands helps make extending | |
83 | * files a "quick" operation by avoiding having to scan | |
84 | * the fat to discover the last cluster of the file. | |
85 | * The cache also helps sequential reads by remembering | |
86 | * the last cluster read from the file. This also prevents | |
87 | * us from having to rescan the fat to find the next cluster | |
88 | * to read. This cache is probably pretty worthless if a | |
89 | * file is opened by multiple processes. | |
90 | */ | |
91 | #define FC_SIZE 2 /* number of entries in the cache */ | |
92 | #define FC_LASTMAP 0 /* entry the last call to pcbmap() resolved to */ | |
93 | #define FC_LASTFC 1 /* entry for the last cluster in the file */ | |
94 | ||
95 | #define FCE_EMPTY 0xffff /* doesn't represent an actual cluster # */ | |
96 | ||
97 | /* | |
98 | * Set a slot in the fat cache. | |
99 | */ | |
100 | #define fc_setcache(dep, slot, frcn, fsrcn) \ | |
101 | (dep)->de_fc[slot].fc_frcn = frcn; \ | |
102 | (dep)->de_fc[slot].fc_fsrcn = fsrcn; | |
103 | ||
104 | /* | |
105 | * This is the in memory variant of a dos directory | |
106 | * entry. It is usually contained within a vnode. | |
107 | */ | |
108 | struct denode { | |
109 | struct denode *de_chain[2]; /* hash chain ptrs */ | |
110 | struct vnode *de_vnode; /* addr of vnode we are part of */ | |
111 | struct vnode *de_devvp; /* vnode of blk dev we live on */ | |
112 | u_long de_flag; /* flag bits */ | |
113 | dev_t de_dev; /* device where direntry lives */ | |
114 | u_long de_dirclust; /* cluster of the directory file | |
115 | * containing this entry */ | |
116 | u_long de_diroffset; /* ordinal of this entry in the | |
117 | * directory */ | |
118 | long de_refcnt; /* reference count */ | |
119 | struct pcfsmount *de_pmp; /* addr of our mount struct */ | |
120 | struct lockf *de_lockf; /* byte level lock list */ | |
121 | long de_spare0; /* current lock holder */ | |
122 | long de_spare1; /* lock wanter */ | |
123 | struct direntry de_de; /* the actual directory entry */ | |
124 | struct fatcache de_fc[FC_SIZE]; /* fat cache */ | |
125 | }; | |
126 | ||
127 | /* | |
128 | * Values for the de_flag field of the denode. | |
129 | */ | |
130 | #define DELOCKED 0x0001 /* directory entry is locked */ | |
131 | #define DEWANT 0x0002 /* someone wants this de */ | |
132 | #define DERENAME 0x0004 /* de is being renamed */ | |
133 | #define DEUPD 0x0008 /* file has been modified */ | |
134 | #define DESHLOCK 0x0010 /* file has shared lock */ | |
135 | #define DEEXLOCK 0x0020 /* file has exclusive lock */ | |
136 | #define DELWAIT 0x0040 /* someone waiting on file lock */ | |
137 | #define DEMOD 0x0080 /* denode wants to be written back | |
138 | * to disk */ | |
139 | ||
140 | /* | |
141 | * Shorthand macros used to reference fields in the direntry | |
142 | * contained in the denode structure. | |
143 | */ | |
144 | #define de_Name de_de.deName | |
145 | #define de_Extension de_de.deExtension | |
146 | #define de_Attributes de_de.deAttributes | |
147 | #define de_Reserved de_de.deReserved | |
148 | #define de_Time de_de.deTime | |
149 | #define de_Date de_de.deDate | |
150 | #define de_StartCluster de_de.deStartCluster | |
151 | #define de_FileSize de_de.deFileSize | |
152 | #define de_forw de_chain[0] | |
153 | #define de_back de_chain[1] | |
154 | ||
155 | #if defined(KERNEL) | |
156 | ||
157 | #define VTODE(vp) ((struct denode *)(vp)->v_data) | |
158 | #define DETOV(de) ((de)->de_vnode) | |
159 | ||
160 | #define DELOCK(de) delock(de) | |
161 | #define DEUNLOCK(de) deunlock(de) | |
162 | ||
163 | #define DEUPDAT(dep, t, waitfor) \ | |
164 | if (dep->de_flag & DEUPD) \ | |
165 | (void) deupdat(dep, t, waitfor); | |
166 | ||
167 | #define DETIMES(dep, t) \ | |
168 | if (dep->de_flag & DEUPD) { \ | |
169 | (dep)->de_flag |= DEMOD; \ | |
170 | unix2dostime(t, (union dosdate *)&dep->de_Date, \ | |
171 | (union dostime *)&dep->de_Time); \ | |
172 | (dep)->de_flag &= ~DEUPD; \ | |
173 | } | |
174 | ||
175 | /* | |
176 | * This overlays the fid sturcture (see mount.h) | |
177 | */ | |
178 | struct defid { | |
179 | u_short defid_len; /* length of structure */ | |
180 | u_short defid_pad; /* force long alignment */ | |
181 | ||
182 | u_long defid_dirclust; /* cluster this dir entry came from */ | |
183 | u_long defid_dirofs; /* index of entry within the cluster */ | |
184 | ||
185 | /* u_long defid_gen; /* generation number */ | |
186 | }; | |
187 | ||
188 | /* | |
189 | * Prototypes for PCFS vnode operations | |
190 | */ | |
191 | int pcfs_lookup __P((struct vnode *vp, struct nameidata *ndp, struct proc *p)); | |
192 | int pcfs_create __P((struct nameidata *ndp, struct vattr *vap, struct proc *p)); | |
193 | int pcfs_mknod __P((struct nameidata *ndp, struct vattr *vap, struct ucred *cred, | |
194 | struct proc *p)); | |
195 | int pcfs_open __P((struct vnode *vp, int mode, struct ucred *cred, | |
196 | struct proc *p)); | |
197 | int pcfs_close __P((struct vnode *vp, int fflag, struct ucred *cred, | |
198 | struct proc *p)); | |
199 | int pcfs_access __P((struct vnode *vp, int mode, struct ucred *cred, | |
200 | struct proc *p)); | |
201 | int pcfs_getattr __P((struct vnode *vp, struct vattr *vap, struct ucred *cred, | |
202 | struct proc *p)); | |
203 | int pcfs_setattr __P((struct vnode *vp, struct vattr *vap, struct ucred *cred, | |
204 | struct proc *p)); | |
205 | int pcfs_read __P((struct vnode *vp, struct uio *uio, int ioflag, | |
206 | struct ucred *cred)); | |
207 | int pcfs_write __P((struct vnode *vp, struct uio *uio, int ioflag, | |
208 | struct ucred *cred)); | |
209 | int pcfs_ioctl __P((struct vnode *vp, int command, caddr_t data, int fflag, | |
210 | struct ucred *cred, struct proc *p)); | |
211 | int pcfs_select __P((struct vnode *vp, int which, int fflags, struct ucred *cred, | |
212 | struct proc *p)); | |
213 | int pcfs_mmap __P((struct vnode *vp, int fflags, struct ucred *cred, | |
214 | struct proc *p)); | |
215 | int pcfs_fsync __P((struct vnode *vp, int fflags, struct ucred *cred, | |
216 | int waitfor, struct proc *p)); | |
217 | int pcfs_seek __P((struct vnode *vp, off_t oldoff, off_t newoff, | |
218 | struct ucred *cred)); | |
219 | int pcfs_remove __P((struct nameidata *ndp, struct proc *p)); | |
220 | int pcfs_link __P((struct vnode *vp, struct nameidata *ndp, struct proc *p)); | |
221 | int pcfs_rename __P((struct nameidata *fndp, struct nameidata *tdnp, | |
222 | struct proc *p)); | |
223 | int pcfs_mkdir __P((struct nameidata *ndp, struct vattr *vap, struct proc *p)); | |
224 | int pcfs_rmdir __P((struct nameidata *ndp, struct proc *p)); | |
225 | int pcfs_symlink __P((struct nameidata *ndp, struct vattr *vap, char *target, | |
226 | struct proc *p)); | |
227 | int pcfs_readdir __P((struct vnode *vp, struct uio *uio, struct ucred *cred, | |
228 | int *eofflagp)); | |
229 | int pcfs_readlink __P((struct vnode *vp, struct uio *uio, struct ucred *cred)); | |
230 | int pcfs_abortop __P((struct nameidata *ndp)); | |
231 | int pcfs_inactive __P((struct vnode *vp, struct proc *p)); | |
232 | int pcfs_reclaim __P((struct vnode *vp)); | |
233 | int pcfs_lock __P((struct vnode *vp)); | |
234 | int pcfs_unlock __P((struct vnode *vp)); | |
235 | int pcfs_bmap __P((struct vnode *vp, daddr_t bn, struct vnode **vpp, | |
236 | daddr_t *bnp)); | |
237 | int pcfs_strategy __P((struct buf *bp)); | |
238 | int pcfs_print __P((struct vnode *vp)); | |
239 | int pcfs_islocked __P((struct vnode *vp)); | |
240 | int pcfs_advlock __P((struct vnode *vp, caddr_t id, int op, struct flock *fl, | |
241 | int flags)); | |
242 | ||
243 | /* | |
244 | * Internal service routine prototypes. | |
245 | */ | |
246 | int deget __P((struct pcfsmount *pmp, u_long dirclust, u_long diroffset, | |
247 | struct direntry *direntptr, struct denode **depp)); | |
248 | #endif /* defined(KERNEL) */ |