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