1 /* $FreeBSD$ */ 2 /* $NetBSD: msdosfs_vnops.c,v 1.68 1998/02/10 14:10:04 mrg Exp $ */ 3 4 /*- 5 * SPDX-License-Identifier: BSD-4-Clause 6 * 7 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 8 * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 9 * All rights reserved. 10 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by TooLs GmbH. 23 * 4. The name of TooLs GmbH may not be used to endorse or promote products 24 * derived from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 31 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 32 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 33 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 /*- 38 * Written by Paul Popelka (paulp@uts.amdahl.com) 39 * 40 * You can do anything you want with this software, just don't say you wrote 41 * it, and don't remove this notice. 42 * 43 * This software is provided "as is". 44 * 45 * The author supplies this software to be publicly redistributed on the 46 * understanding that the author is not responsible for the correct 47 * functioning of this software in any circumstances and is not liable for 48 * any damages caused by this software. 49 * 50 * October 1992 51 */ 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/uio.h> 56 #include <sys/resourcevar.h> /* defines plimit structure in proc struct */ 57 #include <sys/kernel.h> 58 #include <sys/stat.h> 59 #include <sys/buf.h> 60 #include <sys/proc.h> 61 #include <sys/caps.h> 62 #include <sys/namei.h> 63 #include <sys/mount.h> 64 #include <sys/unistd.h> 65 #include <sys/vnode.h> 66 #include <sys/malloc.h> 67 #include <sys/dirent.h> 68 #include <sys/signalvar.h> 69 #include <sys/time.h> 70 71 #include <vm/vm.h> 72 #include <vm/vm_extern.h> 73 #include <vm/vm_zone.h> 74 #include <vm/vnode_pager.h> 75 #include <vm/vm_page2.h> 76 77 #include <sys/buf2.h> 78 79 #include <machine/inttypes.h> 80 81 #include <vfs/msdosfs/bpb.h> 82 #include <vfs/msdosfs/direntry.h> 83 #include <vfs/msdosfs/denode.h> 84 #include <vfs/msdosfs/fat.h> 85 #include <vfs/msdosfs/msdosfsmount.h> 86 87 /* 88 * Some general notes: 89 * 90 * In the ufs filesystem the inodes, superblocks, and indirect blocks are 91 * read/written using the vnode for the filesystem. Blocks that represent 92 * the contents of a file are read/written using the vnode for the file 93 * (including directories when they are read/written as files). This 94 * presents problems for the dos filesystem because data that should be in 95 * an inode (if dos had them) resides in the directory itself. Since we 96 * must update directory entries without the benefit of having the vnode 97 * for the directory we must use the vnode for the filesystem. This means 98 * that when a directory is actually read/written (via read, write, or 99 * readdir, or seek) we must use the vnode for the filesystem instead of 100 * the vnode for the directory as would happen in ufs. This is to insure we 101 * retrieve the correct block from the buffer cache since the hash value is 102 * based upon the vnode address and the desired block number. 103 */ 104 105 /* 106 * Create a regular file. On entry the directory to contain the file being 107 * created is locked. We must release before we return. We must also free 108 * the pathname buffer pointed at by cnp->cn_pnbuf, always on error, or 109 * only if the SAVESTART bit in cn_flags is clear on success. 110 */ 111 static int 112 msdosfs_create(struct vop_old_create_args *ap) 113 { 114 struct componentname *cnp = ap->a_cnp; 115 struct denode ndirent; 116 struct denode *dep; 117 struct denode *pdep = VTODE(ap->a_dvp); 118 struct timespec ts; 119 int error; 120 121 mprintf("msdosfs_create(cnp %p, vap %p\n", cnp, ap->a_vap); 122 123 /* 124 * If this is the root directory and there is no space left we 125 * can't do anything. This is because the root directory can not 126 * change size. 127 */ 128 if (pdep->de_StartCluster == MSDOSFSROOT 129 && pdep->de_fndoffset >= pdep->de_FileSize) { 130 error = ENOSPC; 131 goto bad; 132 } 133 134 /* 135 * Create a directory entry for the file, then call createde() to 136 * have it installed. NOTE: DOS files are always executable. We 137 * use the absence of the owner write bit to make the file 138 * readonly. 139 */ 140 memset(&ndirent, 0, sizeof(ndirent)); 141 error = uniqdosname(pdep, cnp, ndirent.de_Name); 142 if (error) 143 goto bad; 144 145 ndirent.de_Attributes = (ap->a_vap->va_mode & VWRITE) ? 146 ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY; 147 ndirent.de_LowerCase = 0; 148 ndirent.de_StartCluster = 0; 149 ndirent.de_FileSize = 0; 150 ndirent.de_dev = pdep->de_dev; 151 ndirent.de_devvp = pdep->de_devvp; 152 ndirent.de_pmp = pdep->de_pmp; 153 ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE; 154 vfs_timestamp(&ts); 155 DETIMES(&ndirent, &ts, &ts, &ts); 156 error = createde(&ndirent, pdep, &dep, cnp); 157 if (error) 158 goto bad; 159 *ap->a_vpp = DETOV(dep); 160 return (0); 161 162 bad: 163 return (error); 164 } 165 166 static int 167 msdosfs_mknod(struct vop_old_mknod_args *ap) 168 { 169 return (EINVAL); 170 } 171 172 static int 173 msdosfs_open(struct vop_open_args *ap) 174 { 175 return(vop_stdopen(ap)); 176 } 177 178 static int 179 msdosfs_close(struct vop_close_args *ap) 180 { 181 struct vnode *vp = ap->a_vp; 182 struct denode *dep = VTODE(vp); 183 struct timespec ts; 184 185 if (VREFCNT(vp) > 1) { 186 vfs_timestamp(&ts); 187 DETIMES(dep, &ts, &ts, &ts); 188 } 189 return (vop_stdclose(ap)); 190 } 191 192 static int 193 msdosfs_access(struct vop_access_args *ap) 194 { 195 struct denode *dep = VTODE(ap->a_vp); 196 struct msdosfsmount *pmp = dep->de_pmp; 197 mode_t file_mode; 198 199 file_mode = (S_IXUSR|S_IXGRP|S_IXOTH) | (S_IRUSR|S_IRGRP|S_IROTH) | 200 ((dep->de_Attributes & ATTR_READONLY) ? 201 0 : (S_IWUSR|S_IWGRP|S_IWOTH)); 202 file_mode &= (ap->a_vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask); 203 204 return (vop_helper_access(ap, pmp->pm_uid, pmp->pm_gid, file_mode, 0)); 205 } 206 207 static int 208 msdosfs_getattr(struct vop_getattr_args *ap) 209 { 210 struct denode *dep = VTODE(ap->a_vp); 211 struct msdosfsmount *pmp = dep->de_pmp; 212 struct vattr *vap = ap->a_vap; 213 mode_t mode; 214 struct timespec ts; 215 u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); 216 uint64_t fileid; 217 218 vfs_timestamp(&ts); 219 DETIMES(dep, &ts, &ts, &ts); 220 vap->va_fsid = devid_from_dev(dep->de_dev); 221 /* 222 * The following computation of the fileid must be the same as that 223 * used in msdosfs_readdir() to compute d_fileno. If not, pwd 224 * doesn't work. 225 */ 226 if (dep->de_Attributes & ATTR_DIRECTORY) { 227 fileid = (uint64_t)cntobn(pmp, dep->de_StartCluster) * 228 dirsperblk; 229 if (dep->de_StartCluster == MSDOSFSROOT) 230 fileid = 1; 231 } else { 232 fileid = (uint64_t)cntobn(pmp, dep->de_dirclust) * 233 dirsperblk; 234 if (dep->de_dirclust == MSDOSFSROOT) 235 fileid = (uint64_t)roottobn(pmp, 0) * dirsperblk; 236 fileid += (uoff_t)dep->de_diroffset / sizeof(struct direntry); 237 } 238 vap->va_fileid = fileid; 239 if ((dep->de_Attributes & ATTR_READONLY) == 0) 240 mode = S_IRWXU|S_IRWXG|S_IRWXO; 241 else 242 mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 243 vap->va_mode = mode & 244 (ap->a_vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask); 245 vap->va_uid = pmp->pm_uid; 246 vap->va_gid = pmp->pm_gid; 247 vap->va_nlink = 1; 248 vap->va_rmajor = VNOVAL; 249 vap->va_rminor = VNOVAL; 250 vap->va_size = dep->de_FileSize; 251 fattime2timespec(dep->de_MDate, dep->de_MTime, 0, 0, &vap->va_mtime); 252 if (pmp->pm_flags & MSDOSFSMNT_LONGNAME) { 253 fattime2timespec(dep->de_ADate, 0, 0, 0, &vap->va_atime); 254 fattime2timespec(dep->de_CDate, dep->de_CTime, dep->de_CHun, 255 0, &vap->va_ctime); 256 } else { 257 vap->va_atime = vap->va_mtime; 258 vap->va_ctime = vap->va_mtime; 259 } 260 vap->va_flags = 0; 261 if ((dep->de_Attributes & ATTR_ARCHIVE) == 0) 262 vap->va_flags |= SF_ARCHIVED; 263 vap->va_gen = 0; 264 vap->va_blocksize = pmp->pm_bpcluster; 265 vap->va_bytes = 266 (dep->de_FileSize + pmp->pm_crbomask) & ~pmp->pm_crbomask; 267 vap->va_type = ap->a_vp->v_type; 268 vap->va_filerev = dep->de_modrev; 269 return (0); 270 } 271 272 static int 273 msdosfs_setattr(struct vop_setattr_args *ap) 274 { 275 struct vnode *vp = ap->a_vp; 276 struct denode *dep = VTODE(vp); 277 struct msdosfsmount *pmp = dep->de_pmp; 278 struct vattr *vap = ap->a_vap; 279 struct ucred *cred = ap->a_cred; 280 int error = 0; 281 282 mprintf("msdosfs_setattr(): vp %p, vap %p, cred %p\n", vp, vap, cred); 283 284 /* 285 * Check for unsettable attributes. 286 */ 287 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 288 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 289 (vap->va_blocksize != VNOVAL) || (vap->va_rmajor != VNOVAL) || 290 (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { 291 mprintf("msdosfs_setattr(): returning EINVAL\n"); 292 mprintf(" va_type %d, va_nlink %llx, va_fsid %llx, va_fileid %llx\n", 293 vap->va_type, (unsigned long long)vap->va_nlink, 294 (unsigned long long)vap->va_fsid, 295 (unsigned long long)vap->va_fileid); 296 mprintf(" va_blocksize %lx, va_rdev %llx, va_bytes %llx, va_gen %lx\n", 297 vap->va_blocksize, (unsigned long long)0, 298 (unsigned long long)vap->va_bytes, vap->va_gen); 299 mprintf(" va_uid %x, va_gid %x\n", 300 vap->va_uid, vap->va_gid); 301 return (EINVAL); 302 } 303 304 /* 305 * We don't allow setting attributes on the root directory. 306 * The special case for the root directory is because before 307 * FAT32, the root directory didn't have an entry for itself 308 * (and was otherwise special). With FAT32, the root 309 * directory is not so special, but still doesn't have an 310 * entry for itself. 311 */ 312 if (vp->v_flag & VROOT) 313 return (EINVAL); 314 315 if (vap->va_flags != VNOVAL) { 316 if (vp->v_mount->mnt_flag & MNT_RDONLY) 317 return (EROFS); 318 if (cred->cr_uid != pmp->pm_uid && 319 (error = caps_priv_check(cred, SYSCAP_NOVFS_SETATTR))) 320 { 321 return (error); 322 } 323 324 /* 325 * We are very inconsistent about handling unsupported 326 * attributes. We ignored the access time and the 327 * read and execute bits. We were strict for the other 328 * attributes. 329 * 330 * Here we are strict, stricter than ufs in not allowing 331 * users to attempt to set SF_SETTABLE bits or anyone to 332 * set unsupported bits. However, we ignore attempts to 333 * set ATTR_ARCHIVE for directories `cp -pr' from a more 334 * sensible file system attempts it a lot. 335 */ 336 if (cred->cr_uid != 0) { 337 if (vap->va_flags & SF_SETTABLE) 338 return EPERM; 339 } 340 if (vap->va_flags & ~SF_ARCHIVED) 341 return EOPNOTSUPP; 342 if (vap->va_flags & SF_ARCHIVED) 343 dep->de_Attributes &= ~ATTR_ARCHIVE; 344 else if (!(dep->de_Attributes & ATTR_DIRECTORY)) 345 dep->de_Attributes |= ATTR_ARCHIVE; 346 dep->de_flag |= DE_MODIFIED; 347 } 348 349 if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { 350 uid_t uid; 351 gid_t gid; 352 353 if (vp->v_mount->mnt_flag & MNT_RDONLY) 354 return (EROFS); 355 uid = vap->va_uid; 356 if (uid == (uid_t)VNOVAL) 357 uid = pmp->pm_uid; 358 gid = vap->va_gid; 359 if (gid == (gid_t)VNOVAL) 360 gid = pmp->pm_gid; 361 if ((cred->cr_uid != pmp->pm_uid || uid != pmp->pm_uid || 362 (gid != pmp->pm_gid && !groupmember(gid, cred))) && 363 (error = caps_priv_check(cred, SYSCAP_NOVFS_SETATTR))) 364 { 365 return error; 366 } 367 if (uid != pmp->pm_uid || gid != pmp->pm_gid) 368 return EINVAL; 369 } 370 371 if (vap->va_size != VNOVAL) { 372 switch (vp->v_type) { 373 case VDIR: 374 return (EISDIR); 375 case VREG: 376 /* 377 * Truncation is only supported for regular files, 378 * Disallow it if the filesystem is read-only. 379 */ 380 if (vp->v_mount->mnt_flag & MNT_RDONLY) 381 return (EROFS); 382 break; 383 default: 384 /* 385 * According to POSIX, the result is unspecified 386 * for file types other than regular files, 387 * directories and shared memory objects. We 388 * don't support any file types except regular 389 * files and directories in this file system, so 390 * this (default) case is unreachable and can do 391 * anything. Keep falling through to detrunc() 392 * for now. 393 */ 394 break; 395 } 396 error = detrunc(dep, vap->va_size, 0); 397 if (error) 398 return error; 399 } 400 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 401 if (vp->v_mount->mnt_flag & MNT_RDONLY) 402 return (EROFS); 403 if (cred->cr_uid != pmp->pm_uid && 404 (error = caps_priv_check(cred, SYSCAP_NOVFS_SETATTR)) && 405 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || 406 (error = VOP_EACCESS(vp, VWRITE, cred)))) 407 { 408 return (error); 409 } 410 if (vp->v_type != VDIR) { 411 if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && 412 vap->va_atime.tv_sec != VNOVAL) { 413 dep->de_flag &= ~DE_ACCESS; 414 timespec2fattime(&vap->va_atime, 0, 415 &dep->de_ADate, NULL, NULL); 416 } 417 if (vap->va_mtime.tv_sec != VNOVAL) { 418 dep->de_flag &= ~DE_UPDATE; 419 timespec2fattime(&vap->va_mtime, 0, 420 &dep->de_MDate, &dep->de_MTime, NULL); 421 } 422 dep->de_Attributes |= ATTR_ARCHIVE; 423 dep->de_flag |= DE_MODIFIED; 424 } 425 } 426 /* 427 * DOS files only have the ability to have their writability 428 * attribute set, so we use the owner write bit to set the readonly 429 * attribute. 430 */ 431 if (vap->va_mode != (mode_t)VNOVAL) { 432 if (vp->v_mount->mnt_flag & MNT_RDONLY) 433 return (EROFS); 434 if (cred->cr_uid != pmp->pm_uid && 435 (error = caps_priv_check(cred, SYSCAP_NOVFS_SETATTR))) 436 { 437 return (error); 438 } 439 if (vp->v_type != VDIR) { 440 /* We ignore the read and execute bits. */ 441 if (vap->va_mode & VWRITE) 442 dep->de_Attributes &= ~ATTR_READONLY; 443 else 444 dep->de_Attributes |= ATTR_READONLY; 445 dep->de_Attributes |= ATTR_ARCHIVE; 446 dep->de_flag |= DE_MODIFIED; 447 } 448 } 449 return (deupdat(dep, 0)); 450 } 451 452 static int 453 msdosfs_read(struct vop_read_args *ap) 454 { 455 int error = 0; 456 int blsize; 457 int isadir; 458 size_t orig_resid; 459 u_int n; 460 u_long diff; 461 u_long on; 462 u_long cn; 463 daddr_t lbn; 464 daddr_t rablock; 465 off_t loffset; 466 int rasize; 467 int seqcount; 468 struct buf *bp; 469 struct vnode *vp = ap->a_vp; 470 struct denode *dep = VTODE(vp); 471 struct msdosfsmount *pmp = dep->de_pmp; 472 struct uio *uio = ap->a_uio; 473 474 if (uio->uio_offset < 0) 475 return (EINVAL); 476 477 if ((uoff_t)uio->uio_offset > MSDOSFS_FILESIZE_MAX) 478 return (0); 479 /* 480 * If they didn't ask for any data, then we are done. 481 */ 482 orig_resid = uio->uio_resid; 483 if (orig_resid == 0) 484 return (0); 485 486 /* 487 * The caller is supposed to ensure that 488 * uio->uio_offset >= 0 and uio->uio_resid >= 0. 489 * We don't need to check for large offsets as in ffs because 490 * dep->de_FileSize <= MSDOSFS_FILESIZE_MAX < OFF_MAX, so large 491 * offsets cannot cause overflow even in theory. 492 */ 493 494 seqcount = ap->a_ioflag >> IO_SEQSHIFT; 495 496 isadir = dep->de_Attributes & ATTR_DIRECTORY; 497 do { 498 if (uio->uio_offset >= dep->de_FileSize) 499 break; 500 501 cn = de_cluster(pmp, uio->uio_offset); 502 loffset = de_cn2doff(pmp, cn); 503 rablock = cn + 1; 504 blsize = pmp->pm_bpcluster; 505 on = uio->uio_offset & pmp->pm_crbomask; 506 507 /* 508 * If we are operating on a directory file then be sure to 509 * do i/o with the vnode for the filesystem instead of the 510 * vnode for the directory. 511 */ 512 bp = NULL; 513 if (isadir) { 514 /* convert cluster # to block # */ 515 error = pcbmap(dep, cn, &lbn, NULL, &blsize); 516 loffset = de_bn2doff(pmp, lbn); 517 if (error == E2BIG) { 518 error = EINVAL; 519 break; 520 } else if (error) 521 break; 522 error = bread(pmp->pm_devvp, loffset, blsize, &bp); 523 } else if (de_cn2off(pmp, rablock) >= dep->de_FileSize) { 524 error = bread(vp, loffset, blsize, &bp); 525 } else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 526 error = cluster_readx(vp, 527 ((dep->de_FileSize + blsize - 1) / blsize) * blsize, 528 loffset, blsize, B_NOTMETA, on + uio->uio_resid, 529 seqcount * MAXBSIZE, &bp); 530 bp->b_flags |= B_CLUSTEROK; 531 } else if (seqcount > 1) { 532 off_t raoffset = de_cn2doff(pmp, rablock); 533 rasize = blsize; 534 error = breadn(vp, loffset, 535 blsize, &raoffset, &rasize, 1, &bp); 536 } else { 537 error = bread(vp, loffset, blsize, &bp); 538 } 539 if (error) { 540 brelse(bp); 541 break; 542 } 543 diff = pmp->pm_bpcluster - on; 544 n = szmin(uio->uio_resid, diff); 545 diff = dep->de_FileSize - uio->uio_offset; 546 if (diff < n) 547 n = diff; 548 diff = blsize - bp->b_resid; 549 if (diff < n) 550 n = diff; 551 error = uiomovebp(bp, bp->b_data + on, (size_t)n, uio); 552 bqrelse(bp); 553 } while (error == 0 && uio->uio_resid > 0 && n != 0); 554 555 if (!isadir && (error == 0 || uio->uio_resid != orig_resid) && 556 (vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0) 557 dep->de_flag |= DE_ACCESS; 558 return (error); 559 } 560 561 /* 562 * Write data to a file or directory. 563 */ 564 static int 565 msdosfs_write(struct vop_write_args *ap) 566 { 567 int n; 568 int croffset; 569 size_t resid; 570 u_long osize; 571 int error = 0; 572 u_long count; 573 int seqcount; 574 daddr_t cn, lastcn; 575 struct buf *bp = NULL; 576 int ioflag = ap->a_ioflag; 577 struct uio *uio = ap->a_uio; 578 struct thread *td = uio->uio_td; 579 struct vnode *vp = ap->a_vp; 580 struct vnode *thisvp; 581 struct denode *dep = VTODE(vp); 582 struct msdosfsmount *pmp = dep->de_pmp; 583 struct proc *p = (td ? td->td_proc : NULL); 584 struct lwp *lp = (td ? td->td_lwp : NULL); 585 586 mprintf("msdosfs_write(vp %p, uio %p, ioflag %x, cred %p\n", 587 vp, uio, ioflag, ap->a_cred); 588 mprintf("msdosfs_write(): diroff %lu, dirclust %lu, startcluster %lu\n", 589 dep->de_diroffset, dep->de_dirclust, dep->de_StartCluster); 590 591 switch (vp->v_type) { 592 case VREG: 593 if (ioflag & IO_APPEND) 594 uio->uio_offset = dep->de_FileSize; 595 thisvp = vp; 596 break; 597 case VDIR: 598 return EISDIR; 599 default: 600 panic("msdosfs_write(): bad file type"); 601 } 602 603 if (uio->uio_offset < 0) 604 return (EFBIG); 605 606 /* 607 * This is needed (unlike in ffs_write()) because we extend the 608 * file outside of the loop but we don't want to extend the file 609 * for writes of 0 bytes. 610 */ 611 if (uio->uio_resid == 0) 612 return (0); 613 614 /* 615 * The caller is supposed to ensure that 616 * uio->uio_offset >= 0 and uio->uio_resid >= 0. 617 */ 618 if ((uoff_t)uio->uio_offset + uio->uio_resid > MSDOSFS_FILESIZE_MAX) 619 return (EFBIG); 620 621 /* 622 * If they've exceeded their filesize limit, tell them about it. 623 */ 624 if (p && 625 ((uoff_t)uio->uio_offset + uio->uio_resid > 626 p->p_rlimit[RLIMIT_FSIZE].rlim_cur)) { 627 lwpsignal(p, lp, SIGXFSZ); 628 return (EFBIG); 629 } 630 631 /* 632 * If the offset we are starting the write at is beyond the end of 633 * the file, then they've done a seek. Unix filesystems allow 634 * files with holes in them, DOS doesn't so we must fill the hole 635 * with zeroed blocks. 636 */ 637 if (uio->uio_offset > dep->de_FileSize) { 638 error = deextend(dep, uio->uio_offset); 639 if (error) 640 return (error); 641 } 642 643 /* 644 * Remember some values in case the write fails. 645 */ 646 resid = uio->uio_resid; 647 osize = dep->de_FileSize; 648 649 /* 650 * If we write beyond the end of the file, extend it to its ultimate 651 * size ahead of the time to hopefully get a contiguous area. 652 */ 653 if (uio->uio_offset + resid > osize) { 654 count = de_clcount(pmp, uio->uio_offset + resid) - 655 de_clcount(pmp, osize); 656 error = extendfile(dep, count, NULL, NULL, 0); 657 if (error && (error != ENOSPC || (ioflag & IO_UNIT))) 658 goto errexit; 659 lastcn = dep->de_fc[FC_LASTFC].fc_frcn; 660 } else 661 lastcn = de_clcount(pmp, osize) - 1; 662 663 seqcount = ioflag >> IO_SEQSHIFT; 664 do { 665 if (de_cluster(pmp, uio->uio_offset) > lastcn) { 666 error = ENOSPC; 667 break; 668 } 669 670 croffset = uio->uio_offset & pmp->pm_crbomask; 671 n = (int)szmin(uio->uio_resid, pmp->pm_bpcluster - croffset); 672 if (uio->uio_offset + n > dep->de_FileSize) { 673 dep->de_FileSize = uio->uio_offset + n; 674 /* The object size needs to be set before buffer is allocated */ 675 vnode_pager_setsize(vp, dep->de_FileSize); 676 } 677 678 /* 679 * If either the whole cluster gets written, or we write 680 * the cluster from its start beyond EOF, then no need to 681 * read data from disk. 682 * 683 * If UIO_NOCOPY is set we have to do a read-before-write 684 * to fill in any missing pieces of the buffer since no 685 * actual overwrite will occur. 686 */ 687 cn = de_cluster(pmp, uio->uio_offset); 688 if ((uio->uio_offset & pmp->pm_crbomask) == 0 689 && uio->uio_segflg != UIO_NOCOPY 690 && (de_cluster(pmp, uio->uio_offset + uio->uio_resid) 691 > de_cluster(pmp, uio->uio_offset) 692 || uio->uio_offset + uio->uio_resid >= dep->de_FileSize)) { 693 bp = getblk(thisvp, de_cn2doff(pmp, cn), 694 pmp->pm_bpcluster, 0, 0); 695 clrbuf(bp); 696 /* 697 * Do the bmap now, since pcbmap needs buffers 698 * for the FAT table. (see msdosfs_strategy) 699 */ 700 if (bp->b_bio2.bio_offset == NOOFFSET) { 701 daddr_t dblkno; 702 703 error = pcbmap(dep, 704 de_cluster(pmp, bp->b_loffset), 705 &dblkno, NULL, NULL); 706 if (error || dblkno == (daddr_t)-1) { 707 bp->b_bio2.bio_offset = NOOFFSET; 708 } else { 709 bp->b_bio2.bio_offset = de_bn2doff(pmp, 710 dblkno); 711 } 712 } 713 if (bp->b_bio2.bio_offset == NOOFFSET) { 714 brelse(bp); 715 if (!error) 716 error = EIO; /* XXX */ 717 break; 718 } 719 } else { 720 /* 721 * The block we need to write into exists, so read 722 * it in. 723 */ 724 error = bread(thisvp, de_cn2doff(pmp, cn), 725 pmp->pm_bpcluster, &bp); 726 if (error) { 727 brelse(bp); 728 break; 729 } 730 } 731 732 /* 733 * Should these vnode_pager_* functions be done on dir 734 * files? 735 */ 736 737 /* 738 * Copy the data from user space into the buf header. 739 */ 740 error = uiomovebp(bp, bp->b_data + croffset, (size_t)n, uio); 741 if (error) { 742 brelse(bp); 743 break; 744 } 745 746 /* Prepare for clustered writes in some else clauses. */ 747 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) 748 bp->b_flags |= B_CLUSTEROK; 749 750 /* 751 * If IO_SYNC, then each buffer is written synchronously. 752 * Otherwise, if we have a severe page deficiency then 753 * write the buffer asynchronously. Otherwise, if on a 754 * cluster boundary then write the buffer asynchronously, 755 * combining it with contiguous clusters if permitted and 756 * possible, since we don't expect more writes into this 757 * buffer soon. Otherwise, do a delayed write because we 758 * expect more writes into this buffer soon. 759 */ 760 if (ioflag & IO_SYNC) 761 bwrite(bp); 762 else if (vm_paging_severe() || buf_dirty_count_severe()) 763 bawrite(bp); 764 else if (n + croffset == pmp->pm_bpcluster) { 765 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) 766 cluster_write(bp, dep->de_FileSize, 767 pmp->pm_bpcluster, seqcount); 768 else 769 bawrite(bp); 770 } else 771 bdwrite(bp); 772 dep->de_flag |= DE_UPDATE; 773 } while (error == 0 && uio->uio_resid > 0); 774 775 /* 776 * If the write failed and they want us to, truncate the file back 777 * to the size it was before the write was attempted. 778 */ 779 errexit: 780 if (error) { 781 if (ioflag & IO_UNIT) { 782 detrunc(dep, osize, ioflag & IO_SYNC); 783 uio->uio_offset -= resid - uio->uio_resid; 784 uio->uio_resid = resid; 785 } else { 786 detrunc(dep, dep->de_FileSize, ioflag & IO_SYNC); 787 if (uio->uio_resid != resid) 788 error = 0; 789 } 790 } else if (ioflag & IO_SYNC) 791 error = deupdat(dep, 1); 792 return (error); 793 } 794 795 /* 796 * Flush the blocks of a file to disk. 797 */ 798 static int 799 msdosfs_fsync(struct vop_fsync_args *ap) 800 { 801 struct vnode *vp = ap->a_vp; 802 struct vnode *devvp; 803 int allerror, error; 804 805 /* 806 * Flush all dirty buffers associated with a vnode. 807 */ 808 #ifdef DIAGNOSTIC 809 loop: 810 #endif 811 vfsync(vp, ap->a_waitfor, 0, NULL, NULL); 812 #ifdef DIAGNOSTIC 813 if (ap->a_waitfor == MNT_WAIT && !RB_EMPTY(&vp->v_rbdirty_tree)) { 814 vprint("msdosfs_fsync: dirty", vp); 815 goto loop; 816 } 817 #endif 818 /* 819 * If the syncing request comes from fsync(2), sync the entire 820 * FAT and any other metadata that happens to be on devvp. We 821 * need this mainly for the FAT. We write the FAT sloppily, and 822 * syncing it all now is the best we can easily do to get all 823 * directory entries associated with the file (not just the file) 824 * fully synced. The other metadata includes critical metadata 825 * for all directory entries, but only in the MNT_ASYNC case. We 826 * will soon sync all metadata in the file's directory entry. 827 * Non-critical metadata for associated directory entries only 828 * gets synced accidentally, as in most file systems. 829 */ 830 if (ap->a_waitfor == MNT_WAIT) { 831 devvp = VTODE(ap->a_vp)->de_pmp->pm_devvp; 832 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 833 allerror = VOP_FSYNC(devvp, MNT_WAIT, 0); 834 vn_unlock(devvp); 835 } else 836 allerror = 0; 837 838 error = deupdat(VTODE(ap->a_vp), ap->a_waitfor == MNT_WAIT); 839 if (allerror == 0) 840 allerror = error; 841 return (allerror); 842 } 843 844 static int 845 msdosfs_remove(struct vop_old_remove_args *ap) 846 { 847 struct denode *dep = VTODE(ap->a_vp); 848 struct denode *ddep = VTODE(ap->a_dvp); 849 int error; 850 851 if (ap->a_vp->v_type == VDIR) 852 error = EPERM; 853 else 854 error = removede(ddep, dep); 855 mprintf("msdosfs_remove(), dep %p, v_refcnt 0x%08x\n", 856 dep, ap->a_vp->v_refcnt); 857 return (error); 858 } 859 860 /* 861 * DOS filesystems don't know what links are. 862 */ 863 static int 864 msdosfs_link(struct vop_old_link_args *ap) 865 { 866 return (EOPNOTSUPP); 867 } 868 869 /* 870 * Renames on files require moving the denode to a new hash queue since the 871 * denode's location is used to compute which hash queue to put the file 872 * in. Unless it is a rename in place. For example "mv a b". 873 * 874 * What follows is the basic algorithm: 875 * 876 * if (file move) { 877 * if (dest file exists) { 878 * remove dest file 879 * } 880 * if (dest and src in same directory) { 881 * rewrite name in existing directory slot 882 * } else { 883 * write new entry in dest directory 884 * update offset and dirclust in denode 885 * move denode to new hash chain 886 * clear old directory entry 887 * } 888 * } else { 889 * directory move 890 * if (dest directory exists) { 891 * if (dest is not empty) { 892 * return ENOTEMPTY 893 * } 894 * remove dest directory 895 * } 896 * if (dest and src in same directory) { 897 * rewrite name in existing entry 898 * } else { 899 * be sure dest is not a child of src directory 900 * write entry in dest directory 901 * update "." and ".." in moved directory 902 * clear old directory entry for moved directory 903 * } 904 * } 905 * 906 * On entry: 907 * source's parent directory is unlocked 908 * source file or directory is unlocked 909 * destination's parent directory is locked 910 * destination file or directory is locked if it exists 911 * 912 * On exit: 913 * all denodes should be released 914 */ 915 static int 916 msdosfs_rename(struct vop_old_rename_args *ap) 917 { 918 struct vnode *tdvp = ap->a_tdvp; 919 struct vnode *fvp = ap->a_fvp; 920 struct vnode *fdvp = ap->a_fdvp; 921 struct vnode *tvp = ap->a_tvp; 922 struct componentname *tcnp = ap->a_tcnp; 923 struct componentname *fcnp = ap->a_fcnp; 924 struct denode *ip, *xp, *dp, *zp; 925 u_char toname[12], oldname[11]; 926 u_long from_diroffset, to_diroffset; 927 u_char to_count; 928 int doingdirectory = 0, newparent = 0; 929 int error; 930 u_long cn, pcl; 931 daddr_t bn; 932 struct msdosfsmount *pmp; 933 struct direntry *dotdotp; 934 struct buf *bp = NULL; 935 936 pmp = VFSTOMSDOSFS(fdvp->v_mount); 937 938 /* 939 * Check for cross-device rename. 940 */ 941 if (fvp->v_mount != tdvp->v_mount || 942 (tvp && fvp->v_mount != tvp->v_mount)) { 943 error = EXDEV; 944 abortit: 945 if (tdvp == tvp) 946 vrele(tdvp); 947 else 948 vput(tdvp); 949 if (tvp) 950 vput(tvp); 951 vrele(fdvp); 952 vrele(fvp); 953 return (error); 954 } 955 956 /* 957 * If source and dest are the same, do nothing. 958 */ 959 if (tvp == fvp) { 960 error = 0; 961 goto abortit; 962 } 963 964 /* 965 * fvp is unlocked, fdvp, tvp, tdvp are locked. Lock fvp and note 966 * that we have to unlock it to use the abortit target. 967 */ 968 error = vn_lock(fvp, LK_EXCLUSIVE | LK_FAILRECLAIM); 969 if (error) 970 goto abortit; 971 dp = VTODE(fdvp); 972 ip = VTODE(fvp); 973 974 /* 975 * Be sure we are not renaming ".", "..", or an alias of ".". This 976 * leads to a crippled directory tree. It's pretty tough to do a 977 * "ls" or "pwd" with the "." directory entry missing, and "cd .." 978 * doesn't work if the ".." entry is missing. 979 */ 980 if (ip->de_Attributes & ATTR_DIRECTORY) { 981 /* 982 * Avoid ".", "..", and aliases of "." for obvious reasons. 983 */ 984 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 985 dp == ip || 986 (fcnp->cn_flags & CNP_ISDOTDOT) || 987 (tcnp->cn_flags & CNP_ISDOTDOT) || 988 (ip->de_flag & DE_RENAME)) { 989 vn_unlock(fvp); 990 error = EINVAL; 991 goto abortit; 992 } 993 ip->de_flag |= DE_RENAME; 994 doingdirectory++; 995 } 996 997 /* 998 * fvp locked, fdvp unlocked, tvp, tdvp locked. DE_RENAME only 999 * set if doingdirectory. We will get fvp unlocked in fairly 1000 * short order. dp and xp must be setup and fvp must be unlocked 1001 * for the out and bad targets to work properly. 1002 */ 1003 dp = VTODE(tdvp); 1004 xp = tvp ? VTODE(tvp) : NULL; 1005 1006 /* 1007 * Remember direntry place to use for destination 1008 */ 1009 to_diroffset = dp->de_fndoffset; 1010 to_count = dp->de_fndcnt; 1011 1012 /* 1013 * If ".." must be changed (ie the directory gets a new 1014 * parent) then the source directory must not be in the 1015 * directory hierarchy above the target, as this would 1016 * orphan everything below the source directory. Also 1017 * the user must have write permission in the source so 1018 * as to be able to change "..". We must repeat the call 1019 * to namei, as the parent directory is unlocked by the 1020 * call to doscheckpath(). 1021 */ 1022 error = VOP_EACCESS(fvp, VWRITE, tcnp->cn_cred); 1023 vn_unlock(fvp); 1024 if (VTODE(fdvp)->de_StartCluster != VTODE(tdvp)->de_StartCluster) 1025 newparent = 1; 1026 1027 /* 1028 * ok. fvp, fdvp unlocked, tvp, tdvp locked. tvp may be NULL. 1029 * DE_RENAME only set if doingdirectory. 1030 */ 1031 if (doingdirectory && newparent) { 1032 if (error) /* write access check above */ 1033 goto bad; 1034 if (xp != NULL) { 1035 vput(tvp); 1036 xp = NULL; 1037 } 1038 /* 1039 * checkpath vput's tdvp (VTOI(dp)) on return no matter what, 1040 * get an extra ref so we wind up with just an unlocked, ref'd 1041 * tdvp. The 'out' target skips tvp and tdvp cleanups (tdvp 1042 * isn't locked so we can't use the out target). 1043 */ 1044 vref(tdvp); 1045 error = doscheckpath(ip, dp); 1046 tcnp->cn_flags |= CNP_PDIRUNLOCK; 1047 if (error) { 1048 vrele(tdvp); 1049 goto out; 1050 } 1051 /* 1052 * relookup no longer messes with the ref count. tdvp must 1053 * be unlocked on entry and on success will be locked on 1054 * return. 1055 */ 1056 error = relookup(tdvp, &tvp, tcnp); 1057 if (error) { 1058 if (tcnp->cn_flags & CNP_PDIRUNLOCK) 1059 vrele(tdvp); 1060 else 1061 vput(tdvp); 1062 goto out; 1063 } 1064 1065 /* 1066 * tvp and tdvp are now locked again. 1067 */ 1068 dp = VTODE(tdvp); 1069 xp = tvp ? VTODE(tvp) : NULL; 1070 } 1071 1072 /* 1073 * tvp and tdvp are now locked again, the 'bad' target can be used 1074 * to clean them up again. Delete an existant target and clean 1075 * up tvp. Set xp to NULL to indicate that tvp has been cleaned up. 1076 */ 1077 if (xp != NULL) { 1078 /* 1079 * Target must be empty if a directory and have no links 1080 * to it. Also, ensure source and target are compatible 1081 * (both directories, or both not directories). 1082 */ 1083 if (xp->de_Attributes & ATTR_DIRECTORY) { 1084 if (!dosdirempty(xp)) { 1085 error = ENOTEMPTY; 1086 goto bad; 1087 } 1088 if (!doingdirectory) { 1089 error = ENOTDIR; 1090 goto bad; 1091 } 1092 } else if (doingdirectory) { 1093 error = EISDIR; 1094 goto bad; 1095 } 1096 error = removede(dp, xp); 1097 if (error) 1098 goto bad; 1099 vput(tvp); 1100 xp = NULL; 1101 tvp = NULL; 1102 } 1103 1104 /* 1105 * Convert the filename in tcnp into a dos filename. We copy this 1106 * into the denode and directory entry for the destination 1107 * file/directory. 1108 */ 1109 error = uniqdosname(VTODE(tdvp), tcnp, toname); 1110 if (error) 1111 goto bad; 1112 1113 /* 1114 * Since from wasn't locked at various places above, we have to do 1115 * a relookup here. If the target and source are the same directory 1116 * we have to unlock the target directory in order to safely relookup 1117 * the source, because relookup expects its directory to be unlocked. 1118 * 1119 * Note that ap->a_fvp is still valid and ref'd. Any cleanup must 1120 * now take that into account. 1121 * 1122 * The tdvp locking issues make this a real mess. 1123 */ 1124 fcnp->cn_flags &= ~CNP_MODMASK; 1125 fcnp->cn_flags |= CNP_LOCKPARENT; 1126 if (newparent == 0) 1127 vn_unlock(tdvp); 1128 error = relookup(fdvp, &fvp, fcnp); 1129 if (error || fvp == NULL) { 1130 /* 1131 * From name has disappeared. Note: fdvp might == tdvp. 1132 * 1133 * DE_RENAME is only set if doingdirectory. 1134 */ 1135 if (doingdirectory) 1136 panic("rename: lost dir entry"); 1137 if (fcnp->cn_flags & CNP_PDIRUNLOCK) 1138 vrele(fdvp); 1139 else 1140 vput(fdvp); 1141 if (newparent == 0) 1142 vrele(tdvp); 1143 else 1144 vput(tdvp); 1145 vrele(ap->a_fvp); 1146 return(0); 1147 } 1148 1149 /* 1150 * No error occured. tdvp, fdvp and fvp are all locked. If 1151 * newparent was 0 be aware that fdvp == tdvp. tvp has been cleaned 1152 * up. ap->a_fvp is still refd. 1153 */ 1154 xp = VTODE(fvp); 1155 zp = VTODE(fdvp); 1156 from_diroffset = zp->de_fndoffset; 1157 1158 /* 1159 * Ensure that the directory entry still exists and has not 1160 * changed till now. If the source is a file the entry may 1161 * have been unlinked or renamed. In either case there is 1162 * no further work to be done. If the source is a directory 1163 * then it cannot have been rmdir'ed or renamed; this is 1164 * prohibited by the DE_RENAME flag. 1165 * 1166 * DE_RENAME is only set if doingdirectory. 1167 */ 1168 if (xp != ip) { 1169 if (doingdirectory) 1170 panic("rename: lost dir entry"); 1171 goto done; 1172 } else { 1173 u_long new_dirclust; 1174 u_long new_diroffset; 1175 1176 /* 1177 * First write a new entry in the destination 1178 * directory and mark the entry in the source directory 1179 * as deleted. Then move the denode to the correct hash 1180 * chain for its new location in the filesystem. And, if 1181 * we moved a directory, then update its .. entry to point 1182 * to the new parent directory. 1183 */ 1184 memcpy(oldname, ip->de_Name, 11); 1185 memcpy(ip->de_Name, toname, 11); /* update denode */ 1186 dp->de_fndoffset = to_diroffset; 1187 dp->de_fndcnt = to_count; 1188 error = createde(ip, dp, NULL, tcnp); 1189 if (error) { 1190 memcpy(ip->de_Name, oldname, 11); 1191 goto done; 1192 } 1193 /* 1194 * If ip is for a directory, then its name should always 1195 * be "." since it is for the directory entry in the 1196 * directory itself (msdosfs_lookup() always translates 1197 * to the "." entry so as to get a unique denode, except 1198 * for the root directory there are different 1199 * complications). However, we just corrupted its name 1200 * to pass the correct name to createde(). Undo this. 1201 */ 1202 if ((ip->de_Attributes & ATTR_DIRECTORY) != 0) 1203 memcpy(ip->de_Name, oldname, 11); 1204 ip->de_refcnt++; 1205 zp->de_fndoffset = from_diroffset; 1206 error = removede(zp, ip); 1207 if (error) { 1208 /* XXX should downgrade to ro here, fs is corrupt */ 1209 goto done; 1210 } 1211 if (!doingdirectory) { 1212 error = pcbmap(dp, de_cluster(pmp, to_diroffset), 1213 NULL, &new_dirclust, NULL); 1214 if (error) { 1215 /* XXX should downgrade to ro here, fs is corrupt */ 1216 goto done; 1217 } 1218 if (new_dirclust == MSDOSFSROOT) 1219 new_diroffset = to_diroffset; 1220 else 1221 new_diroffset = to_diroffset & pmp->pm_crbomask; 1222 msdosfs_reinsert(ip, new_dirclust, new_diroffset); 1223 } 1224 } 1225 1226 /* 1227 * If we moved a directory to a new parent directory, then we must 1228 * fixup the ".." entry in the moved directory. 1229 */ 1230 if (doingdirectory && newparent) { 1231 cn = ip->de_StartCluster; 1232 if (cn == MSDOSFSROOT) { 1233 /* this should never happen */ 1234 panic("msdosfs_rename(): updating .. in root directory?"); 1235 } else { 1236 bn = cntobn(pmp, cn); 1237 } 1238 error = bread(pmp->pm_devvp, de_bn2doff(pmp, bn), 1239 pmp->pm_bpcluster, &bp); 1240 if (error) { 1241 /* XXX should downgrade to ro here, fs is corrupt */ 1242 brelse(bp); 1243 goto done; 1244 } 1245 dotdotp = (struct direntry *)bp->b_data + 1; 1246 pcl = dp->de_StartCluster; 1247 if (FAT32(pmp) && pcl == pmp->pm_rootdirblk) 1248 pcl = MSDOSFSROOT; 1249 putushort(dotdotp->deStartCluster, pcl); 1250 if (FAT32(pmp)) 1251 putushort(dotdotp->deHighClust, pcl >> 16); 1252 if (DOINGASYNC(fvp)) 1253 bdwrite(bp); 1254 else if ((error = bwrite(bp)) != 0) { 1255 /* XXX should downgrade to ro here, fs is corrupt */ 1256 goto done; 1257 } 1258 } 1259 1260 /* 1261 * done case fvp, fdvp, tdvp are locked. ap->a_fvp is refd 1262 */ 1263 done: 1264 if (doingdirectory) 1265 ip->de_flag &= ~DE_RENAME; /* XXX fvp not locked */ 1266 vput(fvp); 1267 if (newparent) 1268 vput(fdvp); 1269 else 1270 vrele(fdvp); 1271 vput(tdvp); 1272 vrele(ap->a_fvp); 1273 return (error); 1274 1275 /* 1276 * 'bad' target: xp governs tvp. tvp and tdvp are locked, fdvp and fvp 1277 * are not locked. ip points to fvp's inode which may have DE_RENAME 1278 * set. 1279 */ 1280 bad: 1281 if (xp) 1282 vput(tvp); 1283 vput(tdvp); 1284 out: 1285 /* 1286 * 'out' target: tvp and tdvp have already been cleaned up. 1287 */ 1288 if (doingdirectory) 1289 ip->de_flag &= ~DE_RENAME; 1290 vrele(fdvp); 1291 vrele(fvp); 1292 return (error); 1293 1294 } 1295 1296 static struct { 1297 struct direntry dot; 1298 struct direntry dotdot; 1299 } dosdirtemplate = { 1300 { ". ", /* the . entry */ 1301 ATTR_DIRECTORY, /* file attribute */ 1302 0, /* reserved */ 1303 0, { 0, 0 }, { 0, 0 }, /* create time & date */ 1304 { 0, 0 }, /* access date */ 1305 { 0, 0 }, /* high bits of start cluster */ 1306 { 210, 4 }, { 210, 4 }, /* modify time & date */ 1307 { 0, 0 }, /* startcluster */ 1308 { 0, 0, 0, 0 } /* filesize */ 1309 }, 1310 { ".. ", /* the .. entry */ 1311 ATTR_DIRECTORY, /* file attribute */ 1312 0, /* reserved */ 1313 0, { 0, 0 }, { 0, 0 }, /* create time & date */ 1314 { 0, 0 }, /* access date */ 1315 { 0, 0 }, /* high bits of start cluster */ 1316 { 210, 4 }, { 210, 4 }, /* modify time & date */ 1317 { 0, 0 }, /* startcluster */ 1318 { 0, 0, 0, 0 } /* filesize */ 1319 } 1320 }; 1321 1322 static int 1323 msdosfs_mkdir(struct vop_old_mkdir_args *ap) 1324 { 1325 struct componentname *cnp = ap->a_cnp; 1326 struct denode *dep; 1327 struct denode *pdep = VTODE(ap->a_dvp); 1328 struct direntry *denp; 1329 struct msdosfsmount *pmp = pdep->de_pmp; 1330 struct buf *bp; 1331 u_long newcluster, pcl; 1332 int bn; 1333 int error; 1334 struct denode ndirent; 1335 struct timespec ts; 1336 1337 /* 1338 * If this is the root directory and there is no space left we 1339 * can't do anything. This is because the root directory can not 1340 * change size. 1341 */ 1342 if (pdep->de_StartCluster == MSDOSFSROOT 1343 && pdep->de_fndoffset >= pdep->de_FileSize) { 1344 error = ENOSPC; 1345 goto bad2; 1346 } 1347 1348 /* 1349 * Allocate a cluster to hold the about to be created directory. 1350 */ 1351 error = clusteralloc(pmp, 0, 1, CLUST_EOFE, &newcluster, NULL); 1352 if (error) 1353 goto bad2; 1354 1355 memset(&ndirent, 0, sizeof(ndirent)); 1356 ndirent.de_pmp = pmp; 1357 ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE; 1358 vfs_timestamp(&ts); 1359 DETIMES(&ndirent, &ts, &ts, &ts); 1360 1361 /* 1362 * Now fill the cluster with the "." and ".." entries. And write 1363 * the cluster to disk. This way it is there for the parent 1364 * directory to be pointing at if there were a crash. 1365 */ 1366 bn = cntobn(pmp, newcluster); 1367 /* always succeeds */ 1368 bp = getblk(pmp->pm_devvp, de_bn2doff(pmp, bn), 1369 pmp->pm_bpcluster, 0, 0); 1370 memset(bp->b_data, 0, pmp->pm_bpcluster); 1371 memcpy(bp->b_data, &dosdirtemplate, sizeof(dosdirtemplate)); 1372 denp = (struct direntry *)bp->b_data; 1373 putushort(denp[0].deStartCluster, newcluster); 1374 putushort(denp[0].deCDate, ndirent.de_CDate); 1375 putushort(denp[0].deCTime, ndirent.de_CTime); 1376 denp[0].deCHundredth = ndirent.de_CHun; 1377 putushort(denp[0].deADate, ndirent.de_ADate); 1378 putushort(denp[0].deMDate, ndirent.de_MDate); 1379 putushort(denp[0].deMTime, ndirent.de_MTime); 1380 pcl = pdep->de_StartCluster; 1381 /* 1382 * Although the root directory has a non-magic starting cluster 1383 * number for FAT32, chkdsk and fsck_msdosfs still require 1384 * references to it in dotdot entries to be magic. 1385 */ 1386 if (FAT32(pmp) && pcl == pmp->pm_rootdirblk) 1387 pcl = MSDOSFSROOT; 1388 putushort(denp[1].deStartCluster, pcl); 1389 putushort(denp[1].deCDate, ndirent.de_CDate); 1390 putushort(denp[1].deCTime, ndirent.de_CTime); 1391 denp[1].deCHundredth = ndirent.de_CHun; 1392 putushort(denp[1].deADate, ndirent.de_ADate); 1393 putushort(denp[1].deMDate, ndirent.de_MDate); 1394 putushort(denp[1].deMTime, ndirent.de_MTime); 1395 if (FAT32(pmp)) { 1396 putushort(denp[0].deHighClust, newcluster >> 16); 1397 putushort(denp[1].deHighClust, pcl >> 16); 1398 } 1399 1400 if (DOINGASYNC(ap->a_dvp)) 1401 bdwrite(bp); 1402 else if ((error = bwrite(bp)) != 0) 1403 goto bad; 1404 1405 /* 1406 * Now build up a directory entry pointing to the newly allocated 1407 * cluster. This will be written to an empty slot in the parent 1408 * directory. 1409 */ 1410 error = uniqdosname(pdep, cnp, ndirent.de_Name); 1411 if (error) 1412 goto bad; 1413 1414 ndirent.de_Attributes = ATTR_DIRECTORY; 1415 ndirent.de_LowerCase = 0; 1416 ndirent.de_StartCluster = newcluster; 1417 ndirent.de_FileSize = 0; 1418 ndirent.de_dev = pdep->de_dev; 1419 ndirent.de_devvp = pdep->de_devvp; 1420 error = createde(&ndirent, pdep, &dep, cnp); 1421 if (error) 1422 goto bad; 1423 *ap->a_vpp = DETOV(dep); 1424 return (0); 1425 1426 bad: 1427 clusterfree(pmp, newcluster); 1428 bad2: 1429 return (error); 1430 } 1431 1432 static int 1433 msdosfs_rmdir(struct vop_old_rmdir_args *ap) 1434 { 1435 struct vnode *vp = ap->a_vp; 1436 struct vnode *dvp = ap->a_dvp; 1437 struct denode *ip, *dp; 1438 int error; 1439 1440 ip = VTODE(vp); 1441 dp = VTODE(dvp); 1442 1443 /* 1444 * Verify the directory is empty (and valid). 1445 * (Rmdir ".." won't be valid since 1446 * ".." will contain a reference to 1447 * the current directory and thus be 1448 * non-empty.) 1449 */ 1450 error = 0; 1451 if (!dosdirempty(ip) || ip->de_flag & DE_RENAME) { 1452 error = ENOTEMPTY; 1453 goto out; 1454 } 1455 /* 1456 * Delete the entry from the directory. For dos filesystems this 1457 * gets rid of the directory entry on disk, the in memory copy 1458 * still exists but the de_refcnt is <= 0. This prevents it from 1459 * being found by deget(). When the vput() on dep is done we give 1460 * up access and eventually msdosfs_reclaim() will be called which 1461 * will remove it from the denode cache. 1462 */ 1463 error = removede(dp, ip); 1464 if (error) 1465 goto out; 1466 /* 1467 * Truncate the directory that is being deleted. 1468 */ 1469 error = detrunc(ip, (u_long)0, IO_SYNC); 1470 out: 1471 return (error); 1472 } 1473 1474 /* 1475 * DOS filesystems don't know what symlinks are. 1476 */ 1477 static int 1478 msdosfs_symlink(struct vop_old_symlink_args *ap) 1479 { 1480 return (EOPNOTSUPP); 1481 } 1482 1483 static int 1484 msdosfs_readdir(struct vop_readdir_args *ap) 1485 { 1486 struct mbnambuf nb; 1487 int error = 0; 1488 int diff; 1489 long n; 1490 int blsize; 1491 long on; 1492 u_long cn; 1493 u_long dirsperblk; 1494 long bias = 0; 1495 daddr_t bn, lbn; 1496 struct buf *bp = NULL; 1497 struct denode *dep; 1498 struct msdosfsmount *pmp; 1499 struct direntry *dentp; 1500 struct dirent dirbuf; 1501 struct uio *uio = ap->a_uio; 1502 off_t *cookies = NULL; 1503 int ncookies = 0; 1504 off_t offset, off; 1505 int chksum = -1; 1506 1507 error = vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM); 1508 if (error) 1509 return (error); 1510 1511 dep = VTODE(ap->a_vp); 1512 pmp = dep->de_pmp; 1513 1514 mprintf("msdosfs_readdir(): vp %p, uio %p, cred %p, eofflagp %p\n", 1515 ap->a_vp, uio, ap->a_cred, ap->a_eofflag); 1516 1517 /* 1518 * msdosfs_readdir() won't operate properly on regular files since 1519 * it does i/o only with the filesystem vnode, and hence can 1520 * retrieve the wrong block from the buffer cache for a plain file. 1521 * So, fail attempts to readdir() on a plain file. 1522 */ 1523 if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) { 1524 error = ENOTDIR; 1525 goto done; 1526 } 1527 1528 /* 1529 * To be safe, initialize dirbuf 1530 */ 1531 memset(dirbuf.d_name, 0, sizeof(dirbuf.d_name)); 1532 1533 /* 1534 * If the user buffer is smaller than the size of one dos directory 1535 * entry or the file offset is not a multiple of the size of a 1536 * directory entry, then we fail the read. 1537 */ 1538 off = offset = uio->uio_offset; 1539 if (uio->uio_resid < sizeof(struct direntry) || 1540 (offset & (sizeof(struct direntry) - 1))) { 1541 error = EINVAL; 1542 goto done; 1543 } 1544 1545 if (ap->a_ncookies) { 1546 ncookies = uio->uio_resid / 16 + 1; 1547 if (ncookies > 1024) 1548 ncookies = 1024; 1549 cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK); 1550 *ap->a_cookies = cookies; 1551 *ap->a_ncookies = ncookies; 1552 } 1553 1554 dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); 1555 1556 #define d_fileno d_ino 1557 /* 1558 * If they are reading from the root directory then, we simulate 1559 * the . and .. entries since these don't exist in the root 1560 * directory. We also set the offset bias to make up for having to 1561 * simulate these entries. By this I mean that at file offset 64 we 1562 * read the first entry in the root directory that lives on disk. 1563 */ 1564 if (dep->de_StartCluster == MSDOSFSROOT 1565 || (FAT32(pmp) && dep->de_StartCluster == pmp->pm_rootdirblk)) { 1566 #if 0 1567 printf("msdosfs_readdir(): going after . or .. in root dir, offset %d\n", 1568 offset); 1569 #endif 1570 bias = 2 * sizeof(struct direntry); 1571 if (offset < bias) { 1572 for (n = (int)offset / sizeof(struct direntry); 1573 n < 2; n++) { 1574 dirbuf.d_fileno = FAT32(pmp) ? 1575 (uint64_t)cntobn(pmp, pmp->pm_rootdirblk) * 1576 dirsperblk : 1; 1577 dirbuf.d_type = DT_DIR; 1578 switch (n) { 1579 case 0: 1580 dirbuf.d_namlen = 1; 1581 dirbuf.d_name[0] = '.'; 1582 break; 1583 case 1: 1584 dirbuf.d_namlen = 2; 1585 dirbuf.d_name[0] = '.'; 1586 dirbuf.d_name[1] = '.'; 1587 break; 1588 } 1589 if (vop_write_dirent(&error, uio, 1590 dirbuf.d_fileno, dirbuf.d_type, 1591 dirbuf.d_namlen, dirbuf.d_name)) 1592 goto out; 1593 if (error) 1594 goto out; 1595 offset += sizeof(struct direntry); 1596 off = offset; 1597 if (cookies) { 1598 *cookies++ = offset; 1599 if (--ncookies <= 0) 1600 goto out; 1601 } 1602 } 1603 } 1604 } 1605 1606 mbnambuf_init(&nb); 1607 off = offset; 1608 1609 while (uio->uio_resid > 0) { 1610 lbn = de_cluster(pmp, offset - bias); 1611 on = (offset - bias) & pmp->pm_crbomask; 1612 n = szmin(pmp->pm_bpcluster - on, uio->uio_resid); 1613 diff = dep->de_FileSize - (offset - bias); 1614 if (diff <= 0) 1615 break; 1616 n = min(n, diff); 1617 error = pcbmap(dep, lbn, &bn, &cn, &blsize); 1618 if (error) 1619 break; 1620 error = bread(pmp->pm_devvp, de_bn2doff(pmp, bn), blsize, &bp); 1621 if (error) { 1622 brelse(bp); 1623 goto done; 1624 } 1625 n = min(n, blsize - bp->b_resid); 1626 if (n == 0) { 1627 brelse(bp); 1628 error = EIO; 1629 goto done; 1630 } 1631 1632 /* 1633 * Convert from dos directory entries to fs-independent 1634 * directory entries. 1635 */ 1636 for (dentp = (struct direntry *)(bp->b_data + on); 1637 (char *)dentp < bp->b_data + on + n; 1638 dentp++, offset += sizeof(struct direntry)) { 1639 #if 0 1640 printf("rd: dentp %08x prev %08x crnt %08x deName %02x attr %02x\n", 1641 dentp, prev, crnt, dentp->deName[0], dentp->deAttributes); 1642 #endif 1643 /* 1644 * If this is an unused entry, we can stop. 1645 */ 1646 if (dentp->deName[0] == SLOT_EMPTY) { 1647 brelse(bp); 1648 goto out; 1649 } 1650 /* 1651 * Skip deleted entries. 1652 */ 1653 if (dentp->deName[0] == SLOT_DELETED) { 1654 chksum = -1; 1655 mbnambuf_init(&nb); 1656 continue; 1657 } 1658 1659 /* 1660 * Handle Win95 long directory entries 1661 */ 1662 if (dentp->deAttributes == ATTR_WIN95) { 1663 if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) 1664 continue; 1665 chksum = win2unixfn(&nb, 1666 (struct winentry *)dentp, chksum, pmp); 1667 continue; 1668 } 1669 1670 /* 1671 * Skip volume labels 1672 */ 1673 if (dentp->deAttributes & ATTR_VOLUME) { 1674 chksum = -1; 1675 mbnambuf_init(&nb); 1676 continue; 1677 } 1678 /* 1679 * This computation of d_fileno must match 1680 * the computation of va_fileid in 1681 * msdosfs_getattr. 1682 */ 1683 if (dentp->deAttributes & ATTR_DIRECTORY) { 1684 cn = getushort(dentp->deStartCluster); 1685 if (FAT32(pmp)) { 1686 cn |= getushort(dentp->deHighClust) << 1687 16; 1688 if (cn == MSDOSFSROOT) 1689 cn = pmp->pm_rootdirblk; 1690 } 1691 if (cn == MSDOSFSROOT && !FAT32(pmp)) 1692 dirbuf.d_fileno = 1; 1693 else 1694 dirbuf.d_fileno = cntobn(pmp, cn) * 1695 dirsperblk; 1696 dirbuf.d_type = DT_DIR; 1697 } else { 1698 dirbuf.d_fileno = (uoff_t)offset / 1699 sizeof(struct direntry); 1700 dirbuf.d_type = DT_REG; 1701 } 1702 1703 if (chksum != winChksum(dentp->deName)) { 1704 dirbuf.d_namlen = dos2unixfn(dentp->deName, 1705 (u_char *)dirbuf.d_name, 1706 dentp->deLowerCase | 1707 ((pmp->pm_flags & MSDOSFSMNT_SHORTNAME) ? 1708 (LCASE_BASE | LCASE_EXT) : 0), 1709 pmp); 1710 mbnambuf_init(&nb); 1711 } else 1712 mbnambuf_flush(&nb, &dirbuf); 1713 chksum = -1; 1714 if (vop_write_dirent(&error, uio, dirbuf.d_fileno, 1715 dirbuf.d_type, dirbuf.d_namlen, dirbuf.d_name)) { 1716 brelse(bp); 1717 goto out; 1718 } 1719 if (error) { 1720 brelse(bp); 1721 goto out; 1722 } 1723 1724 if (cookies) { 1725 *cookies++ = offset + sizeof(struct direntry); 1726 if (--ncookies <= 0) { 1727 brelse(bp); 1728 goto out; 1729 } 1730 } 1731 off = offset + sizeof(struct direntry); 1732 } 1733 brelse(bp); 1734 } 1735 out: 1736 /* Subtract unused cookies */ 1737 if (ap->a_ncookies) 1738 *ap->a_ncookies -= ncookies; 1739 1740 uio->uio_offset = off; 1741 1742 /* 1743 * Set the eofflag (NFS uses it) 1744 */ 1745 if (ap->a_eofflag) { 1746 if (dep->de_FileSize - (offset - bias) <= 0) 1747 *ap->a_eofflag = 1; 1748 else 1749 *ap->a_eofflag = 0; 1750 } 1751 done: 1752 vn_unlock(ap->a_vp); 1753 return (error); 1754 } 1755 1756 /*- 1757 * a_vp - pointer to the file's vnode 1758 * a_runp - where to return the "run past" a_bn. This is the count of logical 1759 * blocks whose physical blocks (together with a_bn's physical block) 1760 * are contiguous. 1761 * a_runb - where to return the "run before" a_bn. 1762 */ 1763 static int 1764 msdosfs_bmap(struct vop_bmap_args *ap) 1765 { 1766 struct fatcache savefc; 1767 struct denode *dep; 1768 struct mount *mp; 1769 struct msdosfsmount *pmp; 1770 struct vnode *vp; 1771 daddr_t dbn, runbn; 1772 u_long cn; 1773 int bnpercn, error, maxio, maxrun, run; 1774 1775 vp = ap->a_vp; 1776 dep = VTODE(vp); 1777 pmp = dep->de_pmp; 1778 1779 if (ap->a_doffsetp == NULL) 1780 return (0); 1781 if (ap->a_runp != NULL) 1782 *ap->a_runp = 0; 1783 if (ap->a_runb != NULL) 1784 *ap->a_runb = 0; 1785 1786 KKASSERT(((int)ap->a_loffset & ((1 << pmp->pm_cnshift) - 1)) == 0); 1787 error = pcbmap(dep, de_cluster(pmp, ap->a_loffset), &dbn, NULL, NULL); 1788 if (error || dbn == (daddr_t)-1) 1789 *ap->a_doffsetp = NOOFFSET; 1790 else 1791 *ap->a_doffsetp = de_bn2doff(pmp, dbn); 1792 if (error != 0 || dbn == (daddr_t)-1 || 1793 (ap->a_runp == NULL && ap->a_runb == NULL)) 1794 return (error); 1795 1796 /* 1797 * Prepare to back out updates of the fatchain cache after the one 1798 * for the first block done by pcbmap() above. Without the backout, 1799 * then whenever the caller doesn't do i/o to all of the blocks that 1800 * we find, the single useful cache entry would be too far in advance 1801 * of the actual i/o to work for the next sequential i/o. Then the 1802 * FAT would be searched from the beginning. With the backout, the 1803 * FAT is searched starting at most a few blocks early. This wastes 1804 * much less time. Time is also wasted finding more blocks than the 1805 * caller will do i/o to. This is necessary because the runlength 1806 * parameters are output-only. 1807 */ 1808 savefc = dep->de_fc[FC_LASTMAP]; 1809 1810 cn = de_cluster(pmp, ap->a_loffset); 1811 mp = vp->v_mount; 1812 maxio = mp->mnt_iosize_max / mp->mnt_stat.f_iosize; 1813 bnpercn = de_cn2bn(pmp, 1); 1814 if (ap->a_runp != NULL) { 1815 maxrun = ulmin(maxio - 1, pmp->pm_maxcluster - cn); 1816 for (run = 1; run <= maxrun; run++) { 1817 if (pcbmap(dep, cn + run, &runbn, NULL, NULL) != 0 || 1818 runbn != dbn + run * bnpercn) 1819 break; 1820 } 1821 *ap->a_runp = run - 1; 1822 } 1823 if (ap->a_runb != NULL) { 1824 maxrun = ulmin(maxio - 1, cn); 1825 for (run = 1; run < maxrun; run++) { 1826 if (pcbmap(dep, cn - run, &runbn, NULL, NULL) != 0 || 1827 runbn != dbn - run * bnpercn) 1828 break; 1829 } 1830 *ap->a_runb = run - 1; 1831 } 1832 dep->de_fc[FC_LASTMAP] = savefc; 1833 1834 return (0); 1835 } 1836 1837 static int 1838 msdosfs_strategy(struct vop_strategy_args *ap) 1839 { 1840 struct bio *bio = ap->a_bio; 1841 struct bio *nbio; 1842 struct buf *bp = bio->bio_buf; 1843 struct vnode *vp = ap->a_vp; 1844 struct denode *dep = VTODE(vp); 1845 struct msdosfsmount *pmp = dep->de_pmp; 1846 int error = 0; 1847 daddr_t dblkno; 1848 1849 if (vp->v_type == VBLK || vp->v_type == VCHR) 1850 panic("msdosfs_strategy: spec"); 1851 /* 1852 * If we don't already know the filesystem relative block number 1853 * then get it using pcbmap(). If pcbmap() returns the block 1854 * number as -1 then we've got a hole in the file. DOS filesystems 1855 * don't allow files with holes, so we shouldn't ever see this. 1856 */ 1857 nbio = push_bio(bio); 1858 if (nbio->bio_offset == NOOFFSET) { 1859 error = pcbmap(dep, de_cluster(pmp, bio->bio_offset), 1860 &dblkno, NULL, NULL); 1861 if (error) { 1862 bp->b_error = error; 1863 bp->b_flags |= B_ERROR; 1864 /* I/O was never started on nbio, must biodone(bio) */ 1865 biodone(bio); 1866 return (error); 1867 } 1868 if (dblkno == (daddr_t)-1) { 1869 nbio->bio_offset = NOOFFSET; 1870 vfs_bio_clrbuf(bp); 1871 } else { 1872 nbio->bio_offset = de_bn2doff(pmp, dblkno); 1873 } 1874 } 1875 if (nbio->bio_offset == NOOFFSET) { 1876 /* I/O was never started on nbio, must biodone(bio) */ 1877 biodone(bio); 1878 return (0); 1879 } 1880 /* 1881 * Read/write the block from/to the disk that contains the desired 1882 * file block. 1883 */ 1884 vn_strategy(dep->de_devvp, nbio); 1885 return (0); 1886 } 1887 1888 static int 1889 msdosfs_print(struct vop_print_args *ap) 1890 { 1891 struct denode *dep = VTODE(ap->a_vp); 1892 1893 kprintf("tag VT_MSDOSFS, startcluster %lu, dircluster %lu, " 1894 "diroffset %lu, dev %d, %d", 1895 dep->de_StartCluster, dep->de_dirclust, dep->de_diroffset, 1896 major(dep->de_dev), minor(dep->de_dev)); 1897 lockmgr_printinfo(&ap->a_vp->v_lock); 1898 return (0); 1899 } 1900 1901 static int 1902 msdosfs_pathconf(struct vop_pathconf_args *ap) 1903 { 1904 struct msdosfsmount *pmp = VTODE(ap->a_vp)->de_pmp; 1905 1906 switch (ap->a_name) { 1907 case _PC_FILESIZEBITS: 1908 *ap->a_retval = FAT12(pmp) ? 32 : 33; 1909 return (0); 1910 case _PC_LINK_MAX: 1911 *ap->a_retval = 1; 1912 return (0); 1913 case _PC_NAME_MAX: 1914 *ap->a_retval = 1915 pmp->pm_flags & MSDOSFSMNT_LONGNAME ? WIN_MAXLEN : 12; 1916 return (0); 1917 case _PC_CHOWN_RESTRICTED: 1918 *ap->a_retval = 1; 1919 return (0); 1920 case _PC_NO_TRUNC: 1921 *ap->a_retval = 0; 1922 return (0); 1923 default: 1924 return (vop_stdpathconf(ap)); 1925 } 1926 /* NOTREACHED */ 1927 } 1928 1929 /* Global vfs data structures for msdosfs */ 1930 struct vop_ops msdosfs_vnode_vops = { 1931 .vop_default = vop_defaultop, 1932 .vop_access = msdosfs_access, 1933 .vop_bmap = msdosfs_bmap, 1934 .vop_getpages = vop_stdgetpages, 1935 .vop_putpages = vop_stdputpages, 1936 .vop_open = msdosfs_open, 1937 .vop_close = msdosfs_close, 1938 .vop_old_create = msdosfs_create, 1939 .vop_fsync = msdosfs_fsync, 1940 .vop_getattr = msdosfs_getattr, 1941 .vop_inactive = msdosfs_inactive, 1942 .vop_old_link = msdosfs_link, 1943 .vop_old_lookup = msdosfs_lookup, 1944 .vop_old_mkdir = msdosfs_mkdir, 1945 .vop_old_mknod = msdosfs_mknod, 1946 .vop_pathconf = msdosfs_pathconf, 1947 .vop_print = msdosfs_print, 1948 .vop_read = msdosfs_read, 1949 .vop_readdir = msdosfs_readdir, 1950 .vop_reclaim = msdosfs_reclaim, 1951 .vop_old_remove = msdosfs_remove, 1952 .vop_old_rename = msdosfs_rename, 1953 .vop_old_rmdir = msdosfs_rmdir, 1954 .vop_setattr = msdosfs_setattr, 1955 .vop_strategy = msdosfs_strategy, 1956 .vop_old_symlink = msdosfs_symlink, 1957 .vop_write = msdosfs_write, 1958 }; 1959