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