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