ext2_lookup.c (194296) | ext2_lookup.c (202283) |
---|---|
1/*- 2 * modified for Lites 1.1 3 * 4 * Aug 1995, Godmar Back (gback@cs.utah.edu) 5 * University of Utah, Department of Computer Science 6 */ 7/*- 8 * Copyright (c) 1989, 1993 --- 24 unchanged lines hidden (view full) --- 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94 | 1/*- 2 * modified for Lites 1.1 3 * 4 * Aug 1995, Godmar Back (gback@cs.utah.edu) 5 * University of Utah, Department of Computer Science 6 */ 7/*- 8 * Copyright (c) 1989, 1993 --- 24 unchanged lines hidden (view full) --- 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94 |
41 * $FreeBSD: head/sys/gnu/fs/ext2fs/ext2_lookup.c 194296 2009-06-16 15:13:45Z kib $ | 41 * $FreeBSD: head/sys/fs/ext2fs/ext2_lookup.c 202283 2010-01-14 14:30:54Z lulf $ |
42 */ 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/namei.h> 47#include <sys/bio.h> 48#include <sys/buf.h> 49#include <sys/endian.h> 50#include <sys/mount.h> 51#include <sys/vnode.h> 52#include <sys/malloc.h> 53#include <sys/dirent.h> 54#include <sys/sysctl.h> 55 56#include <ufs/ufs/dir.h> 57 | 42 */ 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/namei.h> 47#include <sys/bio.h> 48#include <sys/buf.h> 49#include <sys/endian.h> 50#include <sys/mount.h> 51#include <sys/vnode.h> 52#include <sys/malloc.h> 53#include <sys/dirent.h> 54#include <sys/sysctl.h> 55 56#include <ufs/ufs/dir.h> 57 |
58#include <gnu/fs/ext2fs/inode.h> 59#include <gnu/fs/ext2fs/ext2_mount.h> 60#include <gnu/fs/ext2fs/ext2_extern.h> 61#include <gnu/fs/ext2fs/ext2_fs.h> 62#include <gnu/fs/ext2fs/ext2_fs_sb.h> | 58#include 59#include 60#include 61#include <fs/ext2fs/ext2fs.h> 62#include <fs/ext2fs/ext2_dir.h> |
63 64#ifdef DIAGNOSTIC 65static int dirchk = 1; 66#else 67static int dirchk = 0; 68#endif 69 70static SYSCTL_NODE(_vfs, OID_AUTO, e2fs, CTLFLAG_RD, 0, "EXT2FS filesystem"); --- 36 unchanged lines hidden (view full) --- 107 EXT2_FT_SOCK, /* DT_SOCK */ 108 EXT2_FT_UNKNOWN, /* unused */ 109 EXT2_FT_UNKNOWN, /* DT_WHT */ 110}; 111#define DTTOFT(dt) \ 112 ((dt) > sizeof(dt_to_ext2_ft) / sizeof(dt_to_ext2_ft[0]) ? \ 113 EXT2_FT_UNKNOWN : dt_to_ext2_ft[(dt)]) 114 | 63 64#ifdef DIAGNOSTIC 65static int dirchk = 1; 66#else 67static int dirchk = 0; 68#endif 69 70static SYSCTL_NODE(_vfs, OID_AUTO, e2fs, CTLFLAG_RD, 0, "EXT2FS filesystem"); --- 36 unchanged lines hidden (view full) --- 107 EXT2_FT_SOCK, /* DT_SOCK */ 108 EXT2_FT_UNKNOWN, /* unused */ 109 EXT2_FT_UNKNOWN, /* DT_WHT */ 110}; 111#define DTTOFT(dt) \ 112 ((dt) > sizeof(dt_to_ext2_ft) / sizeof(dt_to_ext2_ft[0]) ? \ 113 EXT2_FT_UNKNOWN : dt_to_ext2_ft[(dt)]) 114 |
115static int ext2_dirbadentry(struct vnode *dp, struct ext2_dir_entry_2 *de, | 115static int ext2_dirbadentry(struct vnode *dp, struct ext2fs_direct_2 *de, |
116 int entryoffsetinblock); 117 118/* 119 * Vnode op for reading directories. 120 * 121 * The routine below assumes that the on-disk format of a directory 122 * is the same as that defined by <sys/dirent.h>. If the on-disk 123 * format changes, then it will be necessary to do a conversion --- 15 unchanged lines hidden (view full) --- 139 struct vnode *a_vp; 140 struct uio *a_uio; 141 struct ucred *a_cred; 142 } */ *ap; 143{ 144 struct uio *uio = ap->a_uio; 145 int count, error; 146 | 116 int entryoffsetinblock); 117 118/* 119 * Vnode op for reading directories. 120 * 121 * The routine below assumes that the on-disk format of a directory 122 * is the same as that defined by <sys/dirent.h>. If the on-disk 123 * format changes, then it will be necessary to do a conversion --- 15 unchanged lines hidden (view full) --- 139 struct vnode *a_vp; 140 struct uio *a_uio; 141 struct ucred *a_cred; 142 } */ *ap; 143{ 144 struct uio *uio = ap->a_uio; 145 int count, error; 146 |
147 struct ext2_dir_entry_2 *edp, *dp; | 147 struct ext2fs_direct_2 *edp, *dp; |
148 int ncookies; 149 struct dirent dstdp; 150 struct uio auio; 151 struct iovec aiov; 152 caddr_t dirbuf; | 148 int ncookies; 149 struct dirent dstdp; 150 struct uio auio; 151 struct iovec aiov; 152 caddr_t dirbuf; |
153 int DIRBLKSIZ = VTOI(ap->a_vp)->i_e2fs->s_blocksize; | 153 int DIRBLKSIZ = VTOI(ap->a_vp)->i_e2fs->e2fs_bsize; |
154 int readcnt; 155 off_t startoffset = uio->uio_offset; 156 157 count = uio->uio_resid; 158 /* 159 * Avoid complications for partial directory entries by adjusting 160 * the i/o to end at a block boundary. Don't give up (like ufs 161 * does) if the initial adjustment gives a negative count, since 162 * many callers don't supply a large enough buffer. The correct 163 * size is a little larger than DIRBLKSIZ to allow for expansion 164 * of directory entries, but some callers just use 512. 165 */ 166 count -= (uio->uio_offset + count) & (DIRBLKSIZ -1); 167 if (count <= 0) 168 count += DIRBLKSIZ; | 154 int readcnt; 155 off_t startoffset = uio->uio_offset; 156 157 count = uio->uio_resid; 158 /* 159 * Avoid complications for partial directory entries by adjusting 160 * the i/o to end at a block boundary. Don't give up (like ufs 161 * does) if the initial adjustment gives a negative count, since 162 * many callers don't supply a large enough buffer. The correct 163 * size is a little larger than DIRBLKSIZ to allow for expansion 164 * of directory entries, but some callers just use 512. 165 */ 166 count -= (uio->uio_offset + count) & (DIRBLKSIZ -1); 167 if (count <= 0) 168 count += DIRBLKSIZ; |
169 170#ifdef EXT2FS_DEBUG 171 printf("ext2_readdir: uio_offset = %lld, uio_resid = %d, count = %d\n", 172 uio->uio_offset, uio->uio_resid, count); 173#endif 174 | |
175 auio = *uio; 176 auio.uio_iov = &aiov; 177 auio.uio_iovcnt = 1; 178 auio.uio_resid = count; 179 auio.uio_segflg = UIO_SYSSPACE; 180 aiov.iov_len = count; 181 dirbuf = malloc(count, M_TEMP, M_WAITOK); 182 aiov.iov_base = dirbuf; 183 error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); 184 if (error == 0) { 185 readcnt = count - auio.uio_resid; | 169 auio = *uio; 170 auio.uio_iov = &aiov; 171 auio.uio_iovcnt = 1; 172 auio.uio_resid = count; 173 auio.uio_segflg = UIO_SYSSPACE; 174 aiov.iov_len = count; 175 dirbuf = malloc(count, M_TEMP, M_WAITOK); 176 aiov.iov_base = dirbuf; 177 error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); 178 if (error == 0) { 179 readcnt = count - auio.uio_resid; |
186 edp = (struct ext2_dir_entry_2 *)&dirbuf[readcnt]; | 180 edp = (struct ext2fs_direct_2 *)&dirbuf[readcnt]; |
187 ncookies = 0; 188 bzero(&dstdp, offsetof(struct dirent, d_name)); | 181 ncookies = 0; 182 bzero(&dstdp, offsetof(struct dirent, d_name)); |
189 for (dp = (struct ext2_dir_entry_2 *)dirbuf; | 183 for (dp = (struct ext2fs_direct_2 *)dirbuf; |
190 !error && uio->uio_resid > 0 && dp < edp; ) { 191 /*- 192 * "New" ext2fs directory entries differ in 3 ways 193 * from ufs on-disk ones: 194 * - the name is not necessarily NUL-terminated. 195 * - the file type field always exists and always 196 * follows the name length field. 197 * - the file type is encoded in a different way. 198 * 199 * "Old" ext2fs directory entries need no special 200 * conversions, since they are binary compatible 201 * with "new" entries having a file type of 0 (i.e., 202 * EXT2_FT_UNKNOWN). Splitting the old name length 203 * field didn't make a mess like it did in ufs, 204 * because ext2fs uses a machine-independent disk 205 * layout. 206 */ | 184 !error && uio->uio_resid > 0 && dp < edp; ) { 185 /*- 186 * "New" ext2fs directory entries differ in 3 ways 187 * from ufs on-disk ones: 188 * - the name is not necessarily NUL-terminated. 189 * - the file type field always exists and always 190 * follows the name length field. 191 * - the file type is encoded in a different way. 192 * 193 * "Old" ext2fs directory entries need no special 194 * conversions, since they are binary compatible 195 * with "new" entries having a file type of 0 (i.e., 196 * EXT2_FT_UNKNOWN). Splitting the old name length 197 * field didn't make a mess like it did in ufs, 198 * because ext2fs uses a machine-independent disk 199 * layout. 200 */ |
207 dstdp.d_fileno = dp->inode; 208 dstdp.d_type = FTTODT(dp->file_type); 209 dstdp.d_namlen = dp->name_len; | 201 dstdp.d_fileno = dp->e2d_ino; 202 dstdp.d_type = FTTODT(dp->e2d_type); 203 dstdp.d_namlen = dp->e2d_namlen; |
210 dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp); | 204 dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp); |
211 bcopy(dp->name, dstdp.d_name, dstdp.d_namlen); | 205 bcopy(dp->e2d_name, dstdp.d_name, dstdp.d_namlen); |
212 bzero(dstdp.d_name + dstdp.d_namlen, 213 dstdp.d_reclen - offsetof(struct dirent, d_name) - 214 dstdp.d_namlen); 215 | 206 bzero(dstdp.d_name + dstdp.d_namlen, 207 dstdp.d_reclen - offsetof(struct dirent, d_name) - 208 dstdp.d_namlen); 209 |
216 if (dp->rec_len > 0) { | 210 if (dp->e2d_reclen > 0) { |
217 if(dstdp.d_reclen <= uio->uio_resid) { 218 /* advance dp */ | 211 if(dstdp.d_reclen <= uio->uio_resid) { 212 /* advance dp */ |
219 dp = (struct ext2_dir_entry_2 *) 220 ((char *)dp + dp->rec_len); | 213 dp = (struct ext2fs_direct_2 *) 214 ((char *)dp + dp->e2d_reclen); |
221 error = 222 uiomove(&dstdp, dstdp.d_reclen, uio); 223 if (!error) 224 ncookies++; 225 } else 226 break; 227 } else { 228 error = EIO; --- 7 unchanged lines hidden (view full) --- 236 u_long *cookiep, *cookies, *ecookies; 237 off_t off; 238 239 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 240 panic("ext2_readdir: unexpected uio from NFS server"); 241 cookies = malloc(ncookies * sizeof(u_long), M_TEMP, 242 M_WAITOK); 243 off = startoffset; | 215 error = 216 uiomove(&dstdp, dstdp.d_reclen, uio); 217 if (!error) 218 ncookies++; 219 } else 220 break; 221 } else { 222 error = EIO; --- 7 unchanged lines hidden (view full) --- 230 u_long *cookiep, *cookies, *ecookies; 231 off_t off; 232 233 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) 234 panic("ext2_readdir: unexpected uio from NFS server"); 235 cookies = malloc(ncookies * sizeof(u_long), M_TEMP, 236 M_WAITOK); 237 off = startoffset; |
244 for (dp = (struct ext2_dir_entry_2 *)dirbuf, | 238 for (dp = (struct ext2fs_direct_2 *)dirbuf, |
245 cookiep = cookies, ecookies = cookies + ncookies; 246 cookiep < ecookies; | 239 cookiep = cookies, ecookies = cookies + ncookies; 240 cookiep < ecookies; |
247 dp = (struct ext2_dir_entry_2 *)((caddr_t) dp + dp->rec_len)) { 248 off += dp->rec_len; | 241 dp = (struct ext2fs_direct_2 *)((caddr_t) dp + dp->e2d_reclen)) { 242 off += dp->e2d_reclen; |
249 *cookiep++ = (u_long) off; 250 } 251 *ap->a_ncookies = ncookies; 252 *ap->a_cookies = cookies; 253 } 254 } 255 free(dirbuf, M_TEMP); 256 if (ap->a_eofflag) --- 37 unchanged lines hidden (view full) --- 294 struct vnode *a_dvp; 295 struct vnode **a_vpp; 296 struct componentname *a_cnp; 297 } */ *ap; 298{ 299 struct vnode *vdp; /* vnode for directory being searched */ 300 struct inode *dp; /* inode for directory being searched */ 301 struct buf *bp; /* a buffer of directory entries */ | 243 *cookiep++ = (u_long) off; 244 } 245 *ap->a_ncookies = ncookies; 246 *ap->a_cookies = cookies; 247 } 248 } 249 free(dirbuf, M_TEMP); 250 if (ap->a_eofflag) --- 37 unchanged lines hidden (view full) --- 288 struct vnode *a_dvp; 289 struct vnode **a_vpp; 290 struct componentname *a_cnp; 291 } */ *ap; 292{ 293 struct vnode *vdp; /* vnode for directory being searched */ 294 struct inode *dp; /* inode for directory being searched */ 295 struct buf *bp; /* a buffer of directory entries */ |
302 struct ext2_dir_entry_2 *ep; /* the current directory entry */ | 296 struct ext2fs_direct_2 *ep; /* the current directory entry */ |
303 int entryoffsetinblock; /* offset of ep in bp's buffer */ 304 enum {NONE, COMPACT, FOUND} slotstatus; 305 doff_t slotoffset; /* offset of area with free space */ 306 int slotsize; /* size of area at slotoffset */ | 297 int entryoffsetinblock; /* offset of ep in bp's buffer */ 298 enum {NONE, COMPACT, FOUND} slotstatus; 299 doff_t slotoffset; /* offset of area with free space */ 300 int slotsize; /* size of area at slotoffset */ |
301 doff_t i_diroff; /* cached i_diroff value */ 302 doff_t i_offset; /* cached i_offset value */ |
|
307 int slotfreespace; /* amount of space free in slot */ 308 int slotneeded; /* size of the entry we're seeking */ 309 int numdirpasses; /* strategy for directory search */ 310 doff_t endsearch; /* offset to end directory search */ 311 doff_t prevoff; /* prev entry dp->i_offset */ 312 struct vnode *pdp; /* saved dp during symlink work */ 313 struct vnode *tdp; /* returned by VFS_VGET */ 314 doff_t enduseful; /* pointer past last used dir slot */ 315 u_long bmask; /* block offset mask */ 316 int namlen, error; 317 struct vnode **vpp = ap->a_vpp; 318 struct componentname *cnp = ap->a_cnp; 319 struct ucred *cred = cnp->cn_cred; 320 int flags = cnp->cn_flags; 321 int nameiop = cnp->cn_nameiop; | 303 int slotfreespace; /* amount of space free in slot */ 304 int slotneeded; /* size of the entry we're seeking */ 305 int numdirpasses; /* strategy for directory search */ 306 doff_t endsearch; /* offset to end directory search */ 307 doff_t prevoff; /* prev entry dp->i_offset */ 308 struct vnode *pdp; /* saved dp during symlink work */ 309 struct vnode *tdp; /* returned by VFS_VGET */ 310 doff_t enduseful; /* pointer past last used dir slot */ 311 u_long bmask; /* block offset mask */ 312 int namlen, error; 313 struct vnode **vpp = ap->a_vpp; 314 struct componentname *cnp = ap->a_cnp; 315 struct ucred *cred = cnp->cn_cred; 316 int flags = cnp->cn_flags; 317 int nameiop = cnp->cn_nameiop; |
322 ino_t saved_ino; | 318 ino_t ino; 319 int ltype; |
323 | 320 |
324 int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->s_blocksize; | 321 int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->e2fs_bsize; |
325 326 bp = NULL; 327 slotoffset = -1; 328 *vpp = NULL; 329 vdp = ap->a_dvp; 330 dp = VTOI(vdp); 331 /* 332 * We now have a segment name to search for, and a directory to search. 333 */ 334 335 /* 336 * Suppress search for slots unless creating 337 * file and at end of pathname, in which case 338 * we watch for a place to put the new file in 339 * case it doesn't already exist. 340 */ | 322 323 bp = NULL; 324 slotoffset = -1; 325 *vpp = NULL; 326 vdp = ap->a_dvp; 327 dp = VTOI(vdp); 328 /* 329 * We now have a segment name to search for, and a directory to search. 330 */ 331 332 /* 333 * Suppress search for slots unless creating 334 * file and at end of pathname, in which case 335 * we watch for a place to put the new file in 336 * case it doesn't already exist. 337 */ |
338 ino = 0; 339 i_diroff = dp->i_diroff; |
|
341 slotstatus = FOUND; 342 slotfreespace = slotsize = slotneeded = 0; 343 if ((nameiop == CREATE || nameiop == RENAME) && 344 (flags & ISLASTCN)) { 345 slotstatus = NONE; 346 slotneeded = EXT2_DIR_REC_LEN(cnp->cn_namelen); 347 /* was 348 slotneeded = (sizeof(struct direct) - MAXNAMLEN + --- 7 unchanged lines hidden (view full) --- 356 * and have the greatest payoff. Caching CREATE has little 357 * benefit as it usually must search the entire directory 358 * to determine that the entry does not exist. Caching the 359 * location of the last DELETE or RENAME has not reduced 360 * profiling time and hence has been removed in the interest 361 * of simplicity. 362 */ 363 bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; | 340 slotstatus = FOUND; 341 slotfreespace = slotsize = slotneeded = 0; 342 if ((nameiop == CREATE || nameiop == RENAME) && 343 (flags & ISLASTCN)) { 344 slotstatus = NONE; 345 slotneeded = EXT2_DIR_REC_LEN(cnp->cn_namelen); 346 /* was 347 slotneeded = (sizeof(struct direct) - MAXNAMLEN + --- 7 unchanged lines hidden (view full) --- 355 * and have the greatest payoff. Caching CREATE has little 356 * benefit as it usually must search the entire directory 357 * to determine that the entry does not exist. Caching the 358 * location of the last DELETE or RENAME has not reduced 359 * profiling time and hence has been removed in the interest 360 * of simplicity. 361 */ 362 bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; |
364 if (nameiop != LOOKUP || dp->i_diroff == 0 || 365 dp->i_diroff > dp->i_size) { | 363 if (nameiop != LOOKUP || i_diroff == 0 || 364 i_diroff > dp->i_size) { |
366 entryoffsetinblock = 0; | 365 entryoffsetinblock = 0; |
367 dp->i_offset = 0; | 366 i_offset = 0; |
368 numdirpasses = 1; 369 } else { | 367 numdirpasses = 1; 368 } else { |
370 dp->i_offset = dp->i_diroff; 371 if ((entryoffsetinblock = dp->i_offset & bmask) && 372 (error = ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL, | 369 i_offset = i_diroff; 370 if ((entryoffsetinblock = i_offset & bmask) && 371 (error = ext2_blkatoff(vdp, (off_t)i_offset, NULL, |
373 &bp))) 374 return (error); 375 numdirpasses = 2; 376 nchstats.ncs_2passes++; 377 } | 372 &bp))) 373 return (error); 374 numdirpasses = 2; 375 nchstats.ncs_2passes++; 376 } |
378 prevoff = dp->i_offset; 379 endsearch = roundup(dp->i_size, DIRBLKSIZ); | 377 prevoff = i_offset; 378 endsearch = roundup2(dp->i_size, DIRBLKSIZ); |
380 enduseful = 0; 381 382searchloop: | 379 enduseful = 0; 380 381searchloop: |
383 while (dp->i_offset < endsearch) { | 382 while (i_offset < endsearch) { |
384 /* 385 * If necessary, get the next directory block. 386 */ | 383 /* 384 * If necessary, get the next directory block. 385 */ |
387 if ((dp->i_offset & bmask) == 0) { | 386 if ((i_offset & bmask) == 0) { |
388 if (bp != NULL) 389 brelse(bp); 390 if ((error = | 387 if (bp != NULL) 388 brelse(bp); 389 if ((error = |
391 ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL, | 390 ext2_blkatoff(vdp, (off_t)i_offset, NULL, |
392 &bp)) != 0) 393 return (error); 394 entryoffsetinblock = 0; 395 } 396 /* 397 * If still looking for a slot, and at a DIRBLKSIZE 398 * boundary, have to start looking for free space again. 399 */ --- 4 unchanged lines hidden (view full) --- 404 } 405 /* 406 * Get pointer to next entry. 407 * Full validation checks are slow, so we only check 408 * enough to insure forward progress through the 409 * directory. Complete checks can be run by setting 410 * "vfs.e2fs.dirchk" to be true. 411 */ | 391 &bp)) != 0) 392 return (error); 393 entryoffsetinblock = 0; 394 } 395 /* 396 * If still looking for a slot, and at a DIRBLKSIZE 397 * boundary, have to start looking for free space again. 398 */ --- 4 unchanged lines hidden (view full) --- 403 } 404 /* 405 * Get pointer to next entry. 406 * Full validation checks are slow, so we only check 407 * enough to insure forward progress through the 408 * directory. Complete checks can be run by setting 409 * "vfs.e2fs.dirchk" to be true. 410 */ |
412 ep = (struct ext2_dir_entry_2 *) | 411 ep = (struct ext2fs_direct_2 *) |
413 ((char *)bp->b_data + entryoffsetinblock); | 412 ((char *)bp->b_data + entryoffsetinblock); |
414 if (ep->rec_len == 0 || | 413 if (ep->e2d_reclen == 0 || |
415 (dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) { 416 int i; | 414 (dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) { 415 int i; |
417 ext2_dirbad(dp, dp->i_offset, "mangled entry"); | 416 ext2_dirbad(dp, i_offset, "mangled entry"); |
418 i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)); | 417 i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)); |
419 dp->i_offset += i; | 418 i_offset += i; |
420 entryoffsetinblock += i; 421 continue; 422 } 423 424 /* 425 * If an appropriate sized slot has not yet been found, 426 * check to see if one is available. Also accumulate space 427 * in the current block so that we can determine if 428 * compaction is viable. 429 */ 430 if (slotstatus != FOUND) { | 419 entryoffsetinblock += i; 420 continue; 421 } 422 423 /* 424 * If an appropriate sized slot has not yet been found, 425 * check to see if one is available. Also accumulate space 426 * in the current block so that we can determine if 427 * compaction is viable. 428 */ 429 if (slotstatus != FOUND) { |
431 int size = ep->rec_len; | 430 int size = ep->e2d_reclen; |
432 | 431 |
433 if (ep->inode != 0) 434 size -= EXT2_DIR_REC_LEN(ep->name_len); | 432 if (ep->e2d_ino != 0) 433 size -= EXT2_DIR_REC_LEN(ep->e2d_namlen); |
435 if (size > 0) { 436 if (size >= slotneeded) { 437 slotstatus = FOUND; | 434 if (size > 0) { 435 if (size >= slotneeded) { 436 slotstatus = FOUND; |
438 slotoffset = dp->i_offset; 439 slotsize = ep->rec_len; | 437 slotoffset = i_offset; 438 slotsize = ep->e2d_reclen; |
440 } else if (slotstatus == NONE) { 441 slotfreespace += size; 442 if (slotoffset == -1) | 439 } else if (slotstatus == NONE) { 440 slotfreespace += size; 441 if (slotoffset == -1) |
443 slotoffset = dp->i_offset; | 442 slotoffset = i_offset; |
444 if (slotfreespace >= slotneeded) { 445 slotstatus = COMPACT; | 443 if (slotfreespace >= slotneeded) { 444 slotstatus = COMPACT; |
446 slotsize = dp->i_offset + 447 ep->rec_len - slotoffset; | 445 slotsize = i_offset + 446 ep->e2d_reclen - slotoffset; |
448 } 449 } 450 } 451 } 452 453 /* 454 * Check for a name match. 455 */ | 447 } 448 } 449 } 450 } 451 452 /* 453 * Check for a name match. 454 */ |
456 if (ep->inode) { 457 namlen = ep->name_len; | 455 if (ep->e2d_ino) { 456 namlen = ep->e2d_namlen; |
458 if (namlen == cnp->cn_namelen && | 457 if (namlen == cnp->cn_namelen && |
459 !bcmp(cnp->cn_nameptr, ep->name, | 458 !bcmp(cnp->cn_nameptr, ep->e2d_name, |
460 (unsigned)namlen)) { 461 /* 462 * Save directory entry's inode number and 463 * reclen in ndp->ni_ufs area, and release 464 * directory buffer. 465 */ | 459 (unsigned)namlen)) { 460 /* 461 * Save directory entry's inode number and 462 * reclen in ndp->ni_ufs area, and release 463 * directory buffer. 464 */ |
466 dp->i_ino = ep->inode; 467 dp->i_reclen = ep->rec_len; | 465 ino = ep->e2d_ino; |
468 goto found; 469 } 470 } | 466 goto found; 467 } 468 } |
471 prevoff = dp->i_offset; 472 dp->i_offset += ep->rec_len; 473 entryoffsetinblock += ep->rec_len; 474 if (ep->inode) 475 enduseful = dp->i_offset; | 469 prevoff = i_offset; 470 i_offset += ep->e2d_reclen; 471 entryoffsetinblock += ep->e2d_reclen; 472 if (ep->e2d_ino) 473 enduseful = i_offset; |
476 } 477/* notfound: */ 478 /* 479 * If we started in the middle of the directory and failed 480 * to find our target, we must check the beginning as well. 481 */ 482 if (numdirpasses == 2) { 483 numdirpasses--; | 474 } 475/* notfound: */ 476 /* 477 * If we started in the middle of the directory and failed 478 * to find our target, we must check the beginning as well. 479 */ 480 if (numdirpasses == 2) { 481 numdirpasses--; |
484 dp->i_offset = 0; 485 endsearch = dp->i_diroff; | 482 i_offset = 0; 483 endsearch = i_diroff; |
486 goto searchloop; 487 } | 484 goto searchloop; 485 } |
486 dp->i_offset = i_offset; |
|
488 if (bp != NULL) 489 brelse(bp); 490 /* 491 * If creating, and at end of pathname and current 492 * directory has not been removed, then can consider 493 * allowing file to be created. 494 */ 495 if ((nameiop == CREATE || nameiop == RENAME) && --- 9 unchanged lines hidden (view full) --- 505 * entry should be put. If we didn't find a slot, 506 * then set dp->i_count to 0 indicating 507 * that the new slot belongs at the end of the 508 * directory. If we found a slot, then the new entry 509 * can be put in the range from dp->i_offset to 510 * dp->i_offset + dp->i_count. 511 */ 512 if (slotstatus == NONE) { | 487 if (bp != NULL) 488 brelse(bp); 489 /* 490 * If creating, and at end of pathname and current 491 * directory has not been removed, then can consider 492 * allowing file to be created. 493 */ 494 if ((nameiop == CREATE || nameiop == RENAME) && --- 9 unchanged lines hidden (view full) --- 504 * entry should be put. If we didn't find a slot, 505 * then set dp->i_count to 0 indicating 506 * that the new slot belongs at the end of the 507 * directory. If we found a slot, then the new entry 508 * can be put in the range from dp->i_offset to 509 * dp->i_offset + dp->i_count. 510 */ 511 if (slotstatus == NONE) { |
513 dp->i_offset = roundup(dp->i_size, DIRBLKSIZ); | 512 dp->i_offset = roundup2(dp->i_size, DIRBLKSIZ); |
514 dp->i_count = 0; 515 enduseful = dp->i_offset; 516 } else { 517 dp->i_offset = slotoffset; 518 dp->i_count = slotsize; 519 if (enduseful < slotoffset + slotsize) 520 enduseful = slotoffset + slotsize; 521 } | 513 dp->i_count = 0; 514 enduseful = dp->i_offset; 515 } else { 516 dp->i_offset = slotoffset; 517 dp->i_count = slotsize; 518 if (enduseful < slotoffset + slotsize) 519 enduseful = slotoffset + slotsize; 520 } |
522 dp->i_endoff = roundup(enduseful, DIRBLKSIZ); | 521 dp->i_endoff = roundup2(enduseful, DIRBLKSIZ); |
523 dp->i_flag |= IN_CHANGE | IN_UPDATE; 524 /* 525 * We return with the directory locked, so that 526 * the parameters we set up above will still be 527 * valid if we actually decide to do a direnter(). 528 * We return ni_vp == NULL to indicate that the entry 529 * does not currently exist; we leave a pointer to 530 * the (locked) directory inode in ndp->ni_dvp. --- 15 unchanged lines hidden (view full) --- 546 547found: 548 if (numdirpasses == 2) 549 nchstats.ncs_pass2++; 550 /* 551 * Check that directory length properly reflects presence 552 * of this entry. 553 */ | 522 dp->i_flag |= IN_CHANGE | IN_UPDATE; 523 /* 524 * We return with the directory locked, so that 525 * the parameters we set up above will still be 526 * valid if we actually decide to do a direnter(). 527 * We return ni_vp == NULL to indicate that the entry 528 * does not currently exist; we leave a pointer to 529 * the (locked) directory inode in ndp->ni_dvp. --- 15 unchanged lines hidden (view full) --- 545 546found: 547 if (numdirpasses == 2) 548 nchstats.ncs_pass2++; 549 /* 550 * Check that directory length properly reflects presence 551 * of this entry. 552 */ |
554 if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->name_len) | 553 if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->e2d_namlen) |
555 > dp->i_size) { | 554 > dp->i_size) { |
556 ext2_dirbad(dp, dp->i_offset, "i_size too small"); 557 dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->name_len); | 555 ext2_dirbad(dp, i_offset, "i_size too small"); 556 dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->e2d_namlen); |
558 dp->i_flag |= IN_CHANGE | IN_UPDATE; 559 } 560 brelse(bp); 561 562 /* 563 * Found component in pathname. 564 * If the final component of path name, save information 565 * in the cache as to where the entry was found. 566 */ 567 if ((flags & ISLASTCN) && nameiop == LOOKUP) | 557 dp->i_flag |= IN_CHANGE | IN_UPDATE; 558 } 559 brelse(bp); 560 561 /* 562 * Found component in pathname. 563 * If the final component of path name, save information 564 * in the cache as to where the entry was found. 565 */ 566 if ((flags & ISLASTCN) && nameiop == LOOKUP) |
568 dp->i_diroff = dp->i_offset &~ (DIRBLKSIZ - 1); 569 | 567 dp->i_diroff = i_offset &~ (DIRBLKSIZ - 1); 568 dp->i_offset = i_offset; |
570 /* 571 * If deleting, and at end of pathname, return 572 * parameters which can be used to remove file. 573 */ 574 if (nameiop == DELETE && (flags & ISLASTCN)) { 575 /* 576 * Write access to directory required to delete files. 577 */ --- 4 unchanged lines hidden (view full) --- 582 * and distance past previous entry (if there 583 * is a previous entry in this block) in dp->i_count. 584 * Save directory inode pointer in ndp->ni_dvp for dirremove(). 585 */ 586 if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) 587 dp->i_count = 0; 588 else 589 dp->i_count = dp->i_offset - prevoff; | 569 /* 570 * If deleting, and at end of pathname, return 571 * parameters which can be used to remove file. 572 */ 573 if (nameiop == DELETE && (flags & ISLASTCN)) { 574 /* 575 * Write access to directory required to delete files. 576 */ --- 4 unchanged lines hidden (view full) --- 581 * and distance past previous entry (if there 582 * is a previous entry in this block) in dp->i_count. 583 * Save directory inode pointer in ndp->ni_dvp for dirremove(). 584 */ 585 if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) 586 dp->i_count = 0; 587 else 588 dp->i_count = dp->i_offset - prevoff; |
590 if (dp->i_number == dp->i_ino) { | 589 if (dp->i_number == ino) { |
591 VREF(vdp); 592 *vpp = vdp; 593 return (0); 594 } | 590 VREF(vdp); 591 *vpp = vdp; 592 return (0); 593 } |
595 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE, | 594 if ((error = VFS_VGET(vdp->v_mount, ino, LK_EXCLUSIVE, |
596 &tdp)) != 0) 597 return (error); 598 /* 599 * If directory is "sticky", then user must own 600 * the directory, or the file in it, else she 601 * may not delete it (unless she's root). This 602 * implements append-only directories. 603 */ --- 16 unchanged lines hidden (view full) --- 620 */ 621 if (nameiop == RENAME && (flags & ISLASTCN)) { 622 if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)) != 0) 623 return (error); 624 /* 625 * Careful about locking second inode. 626 * This can only occur if the target is ".". 627 */ | 595 &tdp)) != 0) 596 return (error); 597 /* 598 * If directory is "sticky", then user must own 599 * the directory, or the file in it, else she 600 * may not delete it (unless she's root). This 601 * implements append-only directories. 602 */ --- 16 unchanged lines hidden (view full) --- 619 */ 620 if (nameiop == RENAME && (flags & ISLASTCN)) { 621 if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)) != 0) 622 return (error); 623 /* 624 * Careful about locking second inode. 625 * This can only occur if the target is ".". 626 */ |
628 if (dp->i_number == dp->i_ino) | 627 if (dp->i_number == ino) |
629 return (EISDIR); | 628 return (EISDIR); |
630 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE, | 629 if ((error = VFS_VGET(vdp->v_mount, ino, LK_EXCLUSIVE, |
631 &tdp)) != 0) 632 return (error); 633 *vpp = tdp; 634 cnp->cn_flags |= SAVENAME; 635 return (0); 636 } 637 638 /* --- 12 unchanged lines hidden (view full) --- 651 * infrequently since we cannot avoid this race condition without 652 * implementing a sophisticated deadlock detection algorithm. 653 * Note also that this simple deadlock detection scheme will not 654 * work if the file system has any hard links other than ".." 655 * that point backwards in the directory structure. 656 */ 657 pdp = vdp; 658 if (flags & ISDOTDOT) { | 630 &tdp)) != 0) 631 return (error); 632 *vpp = tdp; 633 cnp->cn_flags |= SAVENAME; 634 return (0); 635 } 636 637 /* --- 12 unchanged lines hidden (view full) --- 650 * infrequently since we cannot avoid this race condition without 651 * implementing a sophisticated deadlock detection algorithm. 652 * Note also that this simple deadlock detection scheme will not 653 * work if the file system has any hard links other than ".." 654 * that point backwards in the directory structure. 655 */ 656 pdp = vdp; 657 if (flags & ISDOTDOT) { |
659 saved_ino = dp->i_ino; | 658 ltype = VOP_ISLOCKED(pdp); |
660 VOP_UNLOCK(pdp, 0); /* race to get the inode */ | 659 VOP_UNLOCK(pdp, 0); /* race to get the inode */ |
661 error = VFS_VGET(vdp->v_mount, saved_ino, LK_EXCLUSIVE, &tdp); 662 vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY); | 660 error = VFS_VGET(vdp->v_mount, ino, cnp->cn_lkflags, &tdp); 661 vn_lock(pdp, ltype | LK_RETRY); |
663 if (error != 0) 664 return (error); 665 *vpp = tdp; | 662 if (error != 0) 663 return (error); 664 *vpp = tdp; |
666 } else if (dp->i_number == dp->i_ino) { | 665 } else if (dp->i_number == ino) { |
667 VREF(vdp); /* we want ourself, ie "." */ | 666 VREF(vdp); /* we want ourself, ie "." */ |
667 /* 668 * When we lookup "." we still can be asked to lock it 669 * differently. 670 */ 671 ltype = cnp->cn_lkflags & LK_TYPE_MASK; 672 if (ltype != VOP_ISLOCKED(vdp)) { 673 if (ltype == LK_EXCLUSIVE) 674 vn_lock(vdp, LK_UPGRADE | LK_RETRY); 675 else /* if (ltype == LK_SHARED) */ 676 vn_lock(vdp, LK_DOWNGRADE | LK_RETRY); 677 } |
|
668 *vpp = vdp; 669 } else { | 678 *vpp = vdp; 679 } else { |
670 if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE, | 680 if ((error = VFS_VGET(vdp->v_mount, ino, cnp->cn_lkflags, |
671 &tdp)) != 0) 672 return (error); 673 *vpp = tdp; 674 } 675 676 /* 677 * Insert name into cache if appropriate. 678 */ --- 6 unchanged lines hidden (view full) --- 685ext2_dirbad(ip, offset, how) 686 struct inode *ip; 687 doff_t offset; 688 char *how; 689{ 690 struct mount *mp; 691 692 mp = ITOV(ip)->v_mount; | 681 &tdp)) != 0) 682 return (error); 683 *vpp = tdp; 684 } 685 686 /* 687 * Insert name into cache if appropriate. 688 */ --- 6 unchanged lines hidden (view full) --- 695ext2_dirbad(ip, offset, how) 696 struct inode *ip; 697 doff_t offset; 698 char *how; 699{ 700 struct mount *mp; 701 702 mp = ITOV(ip)->v_mount; |
693 (void)printf("%s: bad dir ino %lu at offset %ld: %s\n", 694 mp->mnt_stat.f_mntonname, (u_long)ip->i_number, (long)offset, how); | |
695 if ((mp->mnt_flag & MNT_RDONLY) == 0) | 703 if ((mp->mnt_flag & MNT_RDONLY) == 0) |
696 panic("ext2_dirbad: bad dir"); | 704 panic("ext2_dirbad: %s: bad dir ino %lu at offset %ld: %s\n", 705 mp->mnt_stat.f_mntonname, (u_long)ip->i_number,(long)offset, how); 706 else 707 (void)printf("%s: bad dir ino %lu at offset %ld: %s\n", 708 mp->mnt_stat.f_mntonname, (u_long)ip->i_number, (long)offset, how); 709 |
697} 698 699/* 700 * Do consistency checking on a directory entry: 701 * record length must be multiple of 4 702 * entry must fit in rest of its DIRBLKSIZ block 703 * record must be large enough to contain entry 704 * name is not longer than MAXNAMLEN 705 * name must be as long as advertised, and null terminated 706 */ 707/* 708 * changed so that it confirms to ext2_check_dir_entry 709 */ 710static int 711ext2_dirbadentry(dp, de, entryoffsetinblock) 712 struct vnode *dp; | 710} 711 712/* 713 * Do consistency checking on a directory entry: 714 * record length must be multiple of 4 715 * entry must fit in rest of its DIRBLKSIZ block 716 * record must be large enough to contain entry 717 * name is not longer than MAXNAMLEN 718 * name must be as long as advertised, and null terminated 719 */ 720/* 721 * changed so that it confirms to ext2_check_dir_entry 722 */ 723static int 724ext2_dirbadentry(dp, de, entryoffsetinblock) 725 struct vnode *dp; |
713 struct ext2_dir_entry_2 *de; | 726 struct ext2fs_direct_2 *de; |
714 int entryoffsetinblock; 715{ | 727 int entryoffsetinblock; 728{ |
716 int DIRBLKSIZ = VTOI(dp)->i_e2fs->s_blocksize; | 729 int DIRBLKSIZ = VTOI(dp)->i_e2fs->e2fs_bsize; |
717 718 char * error_msg = NULL; 719 | 730 731 char * error_msg = NULL; 732 |
720 if (de->rec_len < EXT2_DIR_REC_LEN(1)) | 733 if (de->e2d_reclen < EXT2_DIR_REC_LEN(1)) |
721 error_msg = "rec_len is smaller than minimal"; | 734 error_msg = "rec_len is smaller than minimal"; |
722 else if (de->rec_len % 4 != 0) | 735 else if (de->e2d_reclen % 4 != 0) |
723 error_msg = "rec_len % 4 != 0"; | 736 error_msg = "rec_len % 4 != 0"; |
724 else if (de->rec_len < EXT2_DIR_REC_LEN(de->name_len)) | 737 else if (de->e2d_reclen < EXT2_DIR_REC_LEN(de->e2d_namlen)) |
725 error_msg = "reclen is too small for name_len"; | 738 error_msg = "reclen is too small for name_len"; |
726 else if (entryoffsetinblock + de->rec_len > DIRBLKSIZ) | 739 else if (entryoffsetinblock + de->e2d_reclen > DIRBLKSIZ) |
727 error_msg = "directory entry across blocks"; 728 /* else LATER 729 if (de->inode > dir->i_sb->u.ext2_sb.s_es->s_inodes_count) 730 error_msg = "inode out of bounds"; 731 */ 732 733 if (error_msg != NULL) { 734 printf("bad directory entry: %s\n", error_msg); 735 printf("offset=%d, inode=%lu, rec_len=%u, name_len=%u\n", | 740 error_msg = "directory entry across blocks"; 741 /* else LATER 742 if (de->inode > dir->i_sb->u.ext2_sb.s_es->s_inodes_count) 743 error_msg = "inode out of bounds"; 744 */ 745 746 if (error_msg != NULL) { 747 printf("bad directory entry: %s\n", error_msg); 748 printf("offset=%d, inode=%lu, rec_len=%u, name_len=%u\n", |
736 entryoffsetinblock, (unsigned long)de->inode, 737 de->rec_len, de->name_len); | 749 entryoffsetinblock, (unsigned long)de->e2d_ino, 750 de->e2d_reclen, de->e2d_namlen); |
738 } 739 return error_msg == NULL ? 0 : 1; 740} 741 742/* 743 * Write a directory entry after a call to namei, using the parameters 744 * that it left in nameidata. The argument ip is the inode which the new 745 * directory entry will refer to. Dvp is a pointer to the directory to 746 * be written, which was left locked by namei. Remaining parameters 747 * (dp->i_offset, dp->i_count) indicate how the space for the new 748 * entry is to be obtained. 749 */ 750int 751ext2_direnter(ip, dvp, cnp) 752 struct inode *ip; 753 struct vnode *dvp; 754 struct componentname *cnp; 755{ | 751 } 752 return error_msg == NULL ? 0 : 1; 753} 754 755/* 756 * Write a directory entry after a call to namei, using the parameters 757 * that it left in nameidata. The argument ip is the inode which the new 758 * directory entry will refer to. Dvp is a pointer to the directory to 759 * be written, which was left locked by namei. Remaining parameters 760 * (dp->i_offset, dp->i_count) indicate how the space for the new 761 * entry is to be obtained. 762 */ 763int 764ext2_direnter(ip, dvp, cnp) 765 struct inode *ip; 766 struct vnode *dvp; 767 struct componentname *cnp; 768{ |
756 struct ext2_dir_entry_2 *ep, *nep; | 769 struct ext2fs_direct_2 *ep, *nep; |
757 struct inode *dp; 758 struct buf *bp; | 770 struct inode *dp; 771 struct buf *bp; |
759 struct ext2_dir_entry_2 newdir; | 772 struct ext2fs_direct_2 newdir; |
760 struct iovec aiov; 761 struct uio auio; 762 u_int dsize; 763 int error, loc, newentrysize, spacefree; 764 char *dirbuf; | 773 struct iovec aiov; 774 struct uio auio; 775 u_int dsize; 776 int error, loc, newentrysize, spacefree; 777 char *dirbuf; |
765 int DIRBLKSIZ = ip->i_e2fs->s_blocksize; | 778 int DIRBLKSIZ = ip->i_e2fs->e2fs_bsize; |
766 767 768#ifdef DIAGNOSTIC 769 if ((cnp->cn_flags & SAVENAME) == 0) 770 panic("direnter: missing name"); 771#endif 772 dp = VTOI(dvp); | 779 780 781#ifdef DIAGNOSTIC 782 if ((cnp->cn_flags & SAVENAME) == 0) 783 panic("direnter: missing name"); 784#endif 785 dp = VTOI(dvp); |
773 newdir.inode = ip->i_number; 774 newdir.name_len = cnp->cn_namelen; | 786 newdir.e2d_ino = ip->i_number; 787 newdir.e2d_namlen = cnp->cn_namelen; |
775 if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, | 788 if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, |
776 EXT2_FEATURE_INCOMPAT_FILETYPE)) 777 newdir.file_type = DTTOFT(IFTODT(ip->i_mode)); | 789 EXT2F_INCOMPAT_FTYPE)) 790 newdir.e2d_type = DTTOFT(IFTODT(ip->i_mode)); |
778 else | 791 else |
779 newdir.file_type = EXT2_FT_UNKNOWN; 780 bcopy(cnp->cn_nameptr, newdir.name, (unsigned)cnp->cn_namelen + 1); 781 newentrysize = EXT2_DIR_REC_LEN(newdir.name_len); | 792 newdir.e2d_type = EXT2_FT_UNKNOWN; 793 bcopy(cnp->cn_nameptr, newdir.e2d_name, (unsigned)cnp->cn_namelen + 1); 794 newentrysize = EXT2_DIR_REC_LEN(newdir.e2d_namlen); |
782 if (dp->i_count == 0) { 783 /* 784 * If dp->i_count is 0, then namei could find no 785 * space in the directory. Here, dp->i_offset will 786 * be on a directory block boundary and we will write the 787 * new entry into a fresh block. 788 */ 789 if (dp->i_offset & (DIRBLKSIZ - 1)) 790 panic("ext2_direnter: newblk"); 791 auio.uio_offset = dp->i_offset; | 795 if (dp->i_count == 0) { 796 /* 797 * If dp->i_count is 0, then namei could find no 798 * space in the directory. Here, dp->i_offset will 799 * be on a directory block boundary and we will write the 800 * new entry into a fresh block. 801 */ 802 if (dp->i_offset & (DIRBLKSIZ - 1)) 803 panic("ext2_direnter: newblk"); 804 auio.uio_offset = dp->i_offset; |
792 newdir.rec_len = DIRBLKSIZ; | 805 newdir.e2d_reclen = DIRBLKSIZ; |
793 auio.uio_resid = newentrysize; 794 aiov.iov_len = newentrysize; 795 aiov.iov_base = (caddr_t)&newdir; 796 auio.uio_iov = &aiov; 797 auio.uio_iovcnt = 1; 798 auio.uio_rw = UIO_WRITE; 799 auio.uio_segflg = UIO_SYSSPACE; 800 auio.uio_td = (struct thread *)0; 801 error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred); 802 if (DIRBLKSIZ > 803 VFSTOEXT2(dvp->v_mount)->um_mountp->mnt_stat.f_bsize) 804 /* XXX should grow with balloc() */ 805 panic("ext2_direnter: frag size"); 806 else if (!error) { | 806 auio.uio_resid = newentrysize; 807 aiov.iov_len = newentrysize; 808 aiov.iov_base = (caddr_t)&newdir; 809 auio.uio_iov = &aiov; 810 auio.uio_iovcnt = 1; 811 auio.uio_rw = UIO_WRITE; 812 auio.uio_segflg = UIO_SYSSPACE; 813 auio.uio_td = (struct thread *)0; 814 error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred); 815 if (DIRBLKSIZ > 816 VFSTOEXT2(dvp->v_mount)->um_mountp->mnt_stat.f_bsize) 817 /* XXX should grow with balloc() */ 818 panic("ext2_direnter: frag size"); 819 else if (!error) { |
807 dp->i_size = roundup(dp->i_size, DIRBLKSIZ); | 820 dp->i_size = roundup2(dp->i_size, DIRBLKSIZ); |
808 dp->i_flag |= IN_CHANGE; 809 } 810 return (error); 811 } 812 813 /* 814 * If dp->i_count is non-zero, then namei found space 815 * for the new entry in the range dp->i_offset to --- 20 unchanged lines hidden (view full) --- 836 return (error); 837 /* 838 * Find space for the new entry. In the simple case, the entry at 839 * offset base will have the space. If it does not, then namei 840 * arranged that compacting the region dp->i_offset to 841 * dp->i_offset + dp->i_count would yield the 842 * space. 843 */ | 821 dp->i_flag |= IN_CHANGE; 822 } 823 return (error); 824 } 825 826 /* 827 * If dp->i_count is non-zero, then namei found space 828 * for the new entry in the range dp->i_offset to --- 20 unchanged lines hidden (view full) --- 849 return (error); 850 /* 851 * Find space for the new entry. In the simple case, the entry at 852 * offset base will have the space. If it does not, then namei 853 * arranged that compacting the region dp->i_offset to 854 * dp->i_offset + dp->i_count would yield the 855 * space. 856 */ |
844 ep = (struct ext2_dir_entry_2 *)dirbuf; 845 dsize = EXT2_DIR_REC_LEN(ep->name_len); 846 spacefree = ep->rec_len - dsize; 847 for (loc = ep->rec_len; loc < dp->i_count; ) { 848 nep = (struct ext2_dir_entry_2 *)(dirbuf + loc); 849 if (ep->inode) { | 857 ep = (struct ext2fs_direct_2 *)dirbuf; 858 dsize = EXT2_DIR_REC_LEN(ep->e2d_namlen); 859 spacefree = ep->e2d_reclen - dsize; 860 for (loc = ep->e2d_reclen; loc < dp->i_count; ) { 861 nep = (struct ext2fs_direct_2 *)(dirbuf + loc); 862 if (ep->e2d_ino) { |
850 /* trim the existing slot */ | 863 /* trim the existing slot */ |
851 ep->rec_len = dsize; 852 ep = (struct ext2_dir_entry_2 *)((char *)ep + dsize); | 864 ep->e2d_reclen = dsize; 865 ep = (struct ext2fs_direct_2 *)((char *)ep + dsize); |
853 } else { 854 /* overwrite; nothing there; header is ours */ 855 spacefree += dsize; 856 } | 866 } else { 867 /* overwrite; nothing there; header is ours */ 868 spacefree += dsize; 869 } |
857 dsize = EXT2_DIR_REC_LEN(nep->name_len); 858 spacefree += nep->rec_len - dsize; 859 loc += nep->rec_len; | 870 dsize = EXT2_DIR_REC_LEN(nep->e2d_namlen); 871 spacefree += nep->e2d_reclen - dsize; 872 loc += nep->e2d_reclen; |
860 bcopy((caddr_t)nep, (caddr_t)ep, dsize); 861 } 862 /* 863 * Update the pointer fields in the previous entry (if any), 864 * copy in the new entry, and write out the block. 865 */ | 873 bcopy((caddr_t)nep, (caddr_t)ep, dsize); 874 } 875 /* 876 * Update the pointer fields in the previous entry (if any), 877 * copy in the new entry, and write out the block. 878 */ |
866 if (ep->inode == 0) { | 879 if (ep->e2d_ino == 0) { |
867 if (spacefree + dsize < newentrysize) 868 panic("ext2_direnter: compact1"); | 880 if (spacefree + dsize < newentrysize) 881 panic("ext2_direnter: compact1"); |
869 newdir.rec_len = spacefree + dsize; | 882 newdir.e2d_reclen = spacefree + dsize; |
870 } else { 871 if (spacefree < newentrysize) 872 panic("ext2_direnter: compact2"); | 883 } else { 884 if (spacefree < newentrysize) 885 panic("ext2_direnter: compact2"); |
873 newdir.rec_len = spacefree; 874 ep->rec_len = dsize; 875 ep = (struct ext2_dir_entry_2 *)((char *)ep + dsize); | 886 newdir.e2d_reclen = spacefree; 887 ep->e2d_reclen = dsize; 888 ep = (struct ext2fs_direct_2 *)((char *)ep + dsize); |
876 } 877 bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize); 878 error = bwrite(bp); 879 dp->i_flag |= IN_CHANGE | IN_UPDATE; 880 if (!error && dp->i_endoff && dp->i_endoff < dp->i_size) 881 error = ext2_truncate(dvp, (off_t)dp->i_endoff, IO_SYNC, 882 cnp->cn_cred, cnp->cn_thread); 883 return (error); --- 12 unchanged lines hidden (view full) --- 896 * to the size of the previous entry. 897 */ 898int 899ext2_dirremove(dvp, cnp) 900 struct vnode *dvp; 901 struct componentname *cnp; 902{ 903 struct inode *dp; | 889 } 890 bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize); 891 error = bwrite(bp); 892 dp->i_flag |= IN_CHANGE | IN_UPDATE; 893 if (!error && dp->i_endoff && dp->i_endoff < dp->i_size) 894 error = ext2_truncate(dvp, (off_t)dp->i_endoff, IO_SYNC, 895 cnp->cn_cred, cnp->cn_thread); 896 return (error); --- 12 unchanged lines hidden (view full) --- 909 * to the size of the previous entry. 910 */ 911int 912ext2_dirremove(dvp, cnp) 913 struct vnode *dvp; 914 struct componentname *cnp; 915{ 916 struct inode *dp; |
904 struct ext2_dir_entry_2 *ep; | 917 struct ext2fs_direct_2 *ep, *rep; |
905 struct buf *bp; 906 int error; 907 908 dp = VTOI(dvp); 909 if (dp->i_count == 0) { 910 /* 911 * First entry in block: set d_ino to zero. 912 */ 913 if ((error = 914 ext2_blkatoff(dvp, (off_t)dp->i_offset, (char **)&ep, 915 &bp)) != 0) 916 return (error); | 918 struct buf *bp; 919 int error; 920 921 dp = VTOI(dvp); 922 if (dp->i_count == 0) { 923 /* 924 * First entry in block: set d_ino to zero. 925 */ 926 if ((error = 927 ext2_blkatoff(dvp, (off_t)dp->i_offset, (char **)&ep, 928 &bp)) != 0) 929 return (error); |
917 ep->inode = 0; | 930 ep->e2d_ino = 0; |
918 error = bwrite(bp); 919 dp->i_flag |= IN_CHANGE | IN_UPDATE; 920 return (error); 921 } 922 /* 923 * Collapse new free space into previous entry. 924 */ 925 if ((error = ext2_blkatoff(dvp, (off_t)(dp->i_offset - dp->i_count), 926 (char **)&ep, &bp)) != 0) 927 return (error); | 931 error = bwrite(bp); 932 dp->i_flag |= IN_CHANGE | IN_UPDATE; 933 return (error); 934 } 935 /* 936 * Collapse new free space into previous entry. 937 */ 938 if ((error = ext2_blkatoff(dvp, (off_t)(dp->i_offset - dp->i_count), 939 (char **)&ep, &bp)) != 0) 940 return (error); |
928 ep->rec_len += dp->i_reclen; | 941 942 /* Set 'rep' to the entry being removed. */ 943 if (dp->i_count == 0) 944 rep = ep; 945 else 946 rep = (struct ext2fs_direct_2 *)((char *)ep + ep->e2d_reclen); 947 ep->e2d_reclen += rep->e2d_reclen; |
929 error = bwrite(bp); 930 dp->i_flag |= IN_CHANGE | IN_UPDATE; 931 return (error); 932} 933 934/* 935 * Rewrite an existing directory entry to point at the inode 936 * supplied. The parameters describing the directory entry are 937 * set up by a call to namei. 938 */ 939int 940ext2_dirrewrite(dp, ip, cnp) 941 struct inode *dp, *ip; 942 struct componentname *cnp; 943{ 944 struct buf *bp; | 948 error = bwrite(bp); 949 dp->i_flag |= IN_CHANGE | IN_UPDATE; 950 return (error); 951} 952 953/* 954 * Rewrite an existing directory entry to point at the inode 955 * supplied. The parameters describing the directory entry are 956 * set up by a call to namei. 957 */ 958int 959ext2_dirrewrite(dp, ip, cnp) 960 struct inode *dp, *ip; 961 struct componentname *cnp; 962{ 963 struct buf *bp; |
945 struct ext2_dir_entry_2 *ep; | 964 struct ext2fs_direct_2 *ep; |
946 struct vnode *vdp = ITOV(dp); 947 int error; 948 949 if ((error = ext2_blkatoff(vdp, (off_t)dp->i_offset, (char **)&ep, 950 &bp)) != 0) 951 return (error); | 965 struct vnode *vdp = ITOV(dp); 966 int error; 967 968 if ((error = ext2_blkatoff(vdp, (off_t)dp->i_offset, (char **)&ep, 969 &bp)) != 0) 970 return (error); |
952 ep->inode = ip->i_number; | 971 ep->e2d_ino = ip->i_number; |
953 if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, | 972 if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, |
954 EXT2_FEATURE_INCOMPAT_FILETYPE)) 955 ep->file_type = DTTOFT(IFTODT(ip->i_mode)); | 973 EXT2F_INCOMPAT_FTYPE)) 974 ep->e2d_type = DTTOFT(IFTODT(ip->i_mode)); |
956 else | 975 else |
957 ep->file_type = EXT2_FT_UNKNOWN; | 976 ep->e2d_type = EXT2_FT_UNKNOWN; |
958 error = bwrite(bp); 959 dp->i_flag |= IN_CHANGE | IN_UPDATE; 960 return (error); 961} 962 963/* 964 * Check if a directory is empty or not. 965 * Inode supplied must be locked. --- 6 unchanged lines hidden (view full) --- 972int 973ext2_dirempty(ip, parentino, cred) 974 struct inode *ip; 975 ino_t parentino; 976 struct ucred *cred; 977{ 978 off_t off; 979 struct dirtemplate dbuf; | 977 error = bwrite(bp); 978 dp->i_flag |= IN_CHANGE | IN_UPDATE; 979 return (error); 980} 981 982/* 983 * Check if a directory is empty or not. 984 * Inode supplied must be locked. --- 6 unchanged lines hidden (view full) --- 991int 992ext2_dirempty(ip, parentino, cred) 993 struct inode *ip; 994 ino_t parentino; 995 struct ucred *cred; 996{ 997 off_t off; 998 struct dirtemplate dbuf; |
980 struct ext2_dir_entry_2 *dp = (struct ext2_dir_entry_2 *)&dbuf; | 999 struct ext2fs_direct_2 *dp = (struct ext2fs_direct_2 *)&dbuf; |
981 int error, count, namlen; 982#define MINDIRSIZ (sizeof (struct dirtemplate) / 2) 983 | 1000 int error, count, namlen; 1001#define MINDIRSIZ (sizeof (struct dirtemplate) / 2) 1002 |
984 for (off = 0; off < ip->i_size; off += dp->rec_len) { | 1003 for (off = 0; off < ip->i_size; off += dp->e2d_reclen) { |
985 error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, 986 off, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, cred, 987 NOCRED, &count, (struct thread *)0); 988 /* 989 * Since we read MINDIRSIZ, residual must 990 * be 0 unless we're at end of file. 991 */ 992 if (error || count != 0) 993 return (0); 994 /* avoid infinite loops */ | 1004 error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, 1005 off, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, cred, 1006 NOCRED, &count, (struct thread *)0); 1007 /* 1008 * Since we read MINDIRSIZ, residual must 1009 * be 0 unless we're at end of file. 1010 */ 1011 if (error || count != 0) 1012 return (0); 1013 /* avoid infinite loops */ |
995 if (dp->rec_len == 0) | 1014 if (dp->e2d_reclen == 0) |
996 return (0); 997 /* skip empty entries */ | 1015 return (0); 1016 /* skip empty entries */ |
998 if (dp->inode == 0) | 1017 if (dp->e2d_ino == 0) |
999 continue; 1000 /* accept only "." and ".." */ | 1018 continue; 1019 /* accept only "." and ".." */ |
1001 namlen = dp->name_len; | 1020 namlen = dp->e2d_namlen; |
1002 if (namlen > 2) 1003 return (0); | 1021 if (namlen > 2) 1022 return (0); |
1004 if (dp->name[0] != '.') | 1023 if (dp->e2d_name[0] != '.') |
1005 return (0); 1006 /* 1007 * At this point namlen must be 1 or 2. 1008 * 1 implies ".", 2 implies ".." if second 1009 * char is also "." 1010 */ 1011 if (namlen == 1) 1012 continue; | 1024 return (0); 1025 /* 1026 * At this point namlen must be 1 or 2. 1027 * 1 implies ".", 2 implies ".." if second 1028 * char is also "." 1029 */ 1030 if (namlen == 1) 1031 continue; |
1013 if (dp->name[1] == '.' && dp->inode == parentino) | 1032 if (dp->e2d_name[1] == '.' && dp->e2d_ino == parentino) |
1014 continue; 1015 return (0); 1016 } 1017 return (1); 1018} 1019 1020/* 1021 * Check if source directory is in the path of the target directory. --- 61 unchanged lines hidden --- | 1033 continue; 1034 return (0); 1035 } 1036 return (1); 1037} 1038 1039/* 1040 * Check if source directory is in the path of the target directory. --- 61 unchanged lines hidden --- |