version 1.55, 2008/11/28 10:57:03 |
version 1.61.4.6, 2011/05/31 03:04:59 |
Line 60 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 60 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/buf.h> |
#include <sys/buf.h> |
#include <sys/proc.h> |
#include <sys/proc.h> |
#include <sys/mount.h> |
#include <sys/mount.h> |
|
#include <sys/fstrans.h> |
#include <sys/vnode.h> |
#include <sys/vnode.h> |
#include <sys/signalvar.h> |
#include <sys/signalvar.h> |
#include <sys/malloc.h> |
#include <sys/malloc.h> |
Line 98 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 99 __KERNEL_RCSID(0, "$NetBSD$"); |
|
|
|
/* |
/* |
* Create a regular file. On entry the directory to contain the file being |
* Create a regular file. On entry the directory to contain the file being |
* created is locked. We must release before we return. We must also free |
* created is locked. We must release before we return. |
* the pathname buffer pointed at by cnp->cn_pnbuf, always on error, or |
|
* only if the SAVESTART bit in cn_flags is clear on success. |
|
*/ |
*/ |
int |
int |
msdosfs_create(v) |
msdosfs_create(void *v) |
void *v; |
|
{ |
{ |
struct vop_create_args /* { |
struct vop_create_args /* { |
struct vnode *a_dvp; |
struct vnode *a_dvp; |
Line 122 msdosfs_create(v) |
|
Line 120 msdosfs_create(v) |
|
printf("msdosfs_create(cnp %p, vap %p\n", cnp, ap->a_vap); |
printf("msdosfs_create(cnp %p, vap %p\n", cnp, ap->a_vap); |
#endif |
#endif |
|
|
|
fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); |
/* |
/* |
* If this is the root directory and there is no space left we |
* If this is the root directory and there is no space left we |
* can't do anything. This is because the root directory can not |
* can't do anything. This is because the root directory can not |
Line 139 msdosfs_create(v) |
|
Line 138 msdosfs_create(v) |
|
* use the absence of the owner write bit to make the file |
* use the absence of the owner write bit to make the file |
* readonly. |
* readonly. |
*/ |
*/ |
#ifdef DIAGNOSTIC |
|
if ((cnp->cn_flags & HASBUF) == 0) |
|
panic("msdosfs_create: no name"); |
|
#endif |
|
memset(&ndirent, 0, sizeof(ndirent)); |
memset(&ndirent, 0, sizeof(ndirent)); |
if ((error = uniqdosname(pdep, cnp, ndirent.de_Name)) != 0) |
if ((error = uniqdosname(pdep, cnp, ndirent.de_Name)) != 0) |
goto bad; |
goto bad; |
Line 158 msdosfs_create(v) |
|
Line 153 msdosfs_create(v) |
|
DETIMES(&ndirent, NULL, NULL, NULL, pdep->de_pmp->pm_gmtoff); |
DETIMES(&ndirent, NULL, NULL, NULL, pdep->de_pmp->pm_gmtoff); |
if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0) |
if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0) |
goto bad; |
goto bad; |
if ((cnp->cn_flags & SAVESTART) == 0) |
fstrans_done(ap->a_dvp->v_mount); |
PNBUF_PUT(cnp->cn_pnbuf); |
|
VN_KNOTE(ap->a_dvp, NOTE_WRITE); |
VN_KNOTE(ap->a_dvp, NOTE_WRITE); |
vput(ap->a_dvp); |
vput(ap->a_dvp); |
*ap->a_vpp = DETOV(dep); |
*ap->a_vpp = DETOV(dep); |
return (0); |
return (0); |
|
|
bad: |
bad: |
PNBUF_PUT(cnp->cn_pnbuf); |
fstrans_done(ap->a_dvp->v_mount); |
vput(ap->a_dvp); |
vput(ap->a_dvp); |
return (error); |
return (error); |
} |
} |
|
|
int |
int |
msdosfs_mknod(v) |
msdosfs_close(void *v) |
void *v; |
|
{ |
|
struct vop_mknod_args /* { |
|
struct vnode *a_dvp; |
|
struct vnode **a_vpp; |
|
struct componentname *a_cnp; |
|
struct vattr *a_vap; |
|
} */ *ap = v; |
|
|
|
PNBUF_PUT(ap->a_cnp->cn_pnbuf); |
|
vput(ap->a_dvp); |
|
return (EINVAL); |
|
} |
|
|
|
int |
|
msdosfs_open(void *v) |
|
{ |
|
#if 0 |
|
struct vop_open_args /* { |
|
struct vnode *a_vp; |
|
int a_mode; |
|
kauth_cred_t a_cred; |
|
} */ *ap; |
|
#endif |
|
|
|
return (0); |
|
} |
|
|
|
int |
|
msdosfs_close(v) |
|
void *v; |
|
{ |
{ |
struct vop_close_args /* { |
struct vop_close_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
Line 213 msdosfs_close(v) |
|
Line 176 msdosfs_close(v) |
|
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct denode *dep = VTODE(vp); |
struct denode *dep = VTODE(vp); |
|
|
mutex_enter(&vp->v_interlock); |
fstrans_start(vp->v_mount, FSTRANS_SHARED); |
|
mutex_enter(vp->v_interlock); |
if (vp->v_usecount > 1) |
if (vp->v_usecount > 1) |
DETIMES(dep, NULL, NULL, NULL, dep->de_pmp->pm_gmtoff); |
DETIMES(dep, NULL, NULL, NULL, dep->de_pmp->pm_gmtoff); |
mutex_exit(&vp->v_interlock); |
mutex_exit(vp->v_interlock); |
|
fstrans_done(vp->v_mount); |
return (0); |
return (0); |
} |
} |
|
|
int |
static int |
msdosfs_access(v) |
msdosfs_check_possible(struct vnode *vp, struct denode *dep, mode_t mode) |
void *v; |
|
{ |
{ |
struct vop_access_args /* { |
|
struct vnode *a_vp; |
|
int a_mode; |
|
kauth_cred_t a_cred; |
|
} */ *ap = v; |
|
struct vnode *vp = ap->a_vp; |
|
struct denode *dep = VTODE(vp); |
|
struct msdosfsmount *pmp = dep->de_pmp; |
|
mode_t mode = ap->a_mode; |
|
|
|
/* |
/* |
* Disallow write attempts on read-only file systems; |
* Disallow write attempts on read-only file systems; |
Line 251 msdosfs_access(v) |
|
Line 206 msdosfs_access(v) |
|
} |
} |
} |
} |
|
|
|
return 0; |
|
} |
|
|
|
static int |
|
msdosfs_check_permitted(struct vnode *vp, struct denode *dep, mode_t mode, |
|
kauth_cred_t cred) |
|
{ |
|
struct msdosfsmount *pmp = dep->de_pmp; |
|
mode_t file_mode; |
|
|
if ((dep->de_Attributes & ATTR_READONLY) == 0) |
if ((dep->de_Attributes & ATTR_READONLY) == 0) |
mode = S_IRWXU|S_IRWXG|S_IRWXO; |
file_mode = S_IRWXU|S_IRWXG|S_IRWXO; |
else |
else |
mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; |
file_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; |
return (vaccess(ap->a_vp->v_type, |
|
mode & (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask), |
return genfs_can_access(vp->v_type, |
pmp->pm_uid, pmp->pm_gid, ap->a_mode, ap->a_cred)); |
file_mode & (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask), |
|
pmp->pm_uid, pmp->pm_gid, mode, cred); |
} |
} |
|
|
int |
int |
msdosfs_getattr(v) |
msdosfs_access(void *v) |
void *v; |
{ |
|
struct vop_access_args /* { |
|
struct vnode *a_vp; |
|
int a_mode; |
|
kauth_cred_t a_cred; |
|
} */ *ap = v; |
|
struct vnode *vp = ap->a_vp; |
|
struct denode *dep = VTODE(vp); |
|
int error; |
|
|
|
error = msdosfs_check_possible(vp, dep, ap->a_mode); |
|
if (error) |
|
return error; |
|
|
|
error = msdosfs_check_permitted(vp, dep, ap->a_mode, ap->a_cred); |
|
|
|
return error; |
|
} |
|
|
|
int |
|
msdosfs_getattr(void *v) |
{ |
{ |
struct vop_getattr_args /* { |
struct vop_getattr_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
Line 276 msdosfs_getattr(v) |
|
Line 262 msdosfs_getattr(v) |
|
u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); |
u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); |
ino_t fileid; |
ino_t fileid; |
|
|
|
fstrans_start(ap->a_vp->v_mount, FSTRANS_SHARED); |
DETIMES(dep, NULL, NULL, NULL, pmp->pm_gmtoff); |
DETIMES(dep, NULL, NULL, NULL, pmp->pm_gmtoff); |
vap->va_fsid = dep->de_dev; |
vap->va_fsid = dep->de_dev; |
/* |
/* |
Line 324 msdosfs_getattr(v) |
|
Line 311 msdosfs_getattr(v) |
|
vap->va_bytes = |
vap->va_bytes = |
(dep->de_FileSize + pmp->pm_crbomask) & ~pmp->pm_crbomask; |
(dep->de_FileSize + pmp->pm_crbomask) & ~pmp->pm_crbomask; |
vap->va_type = ap->a_vp->v_type; |
vap->va_type = ap->a_vp->v_type; |
|
fstrans_done(ap->a_vp->v_mount); |
return (0); |
return (0); |
} |
} |
|
|
int |
int |
msdosfs_setattr(v) |
msdosfs_setattr(void *v) |
void *v; |
|
{ |
{ |
struct vop_setattr_args /* { |
struct vop_setattr_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
Line 358 msdosfs_setattr(v) |
|
Line 345 msdosfs_setattr(v) |
|
(vap->va_gid != VNOVAL && vap->va_gid != pmp->pm_gid)) { |
(vap->va_gid != VNOVAL && vap->va_gid != pmp->pm_gid)) { |
#ifdef MSDOSFS_DEBUG |
#ifdef MSDOSFS_DEBUG |
printf("msdosfs_setattr(): returning EINVAL\n"); |
printf("msdosfs_setattr(): returning EINVAL\n"); |
printf(" va_type %d, va_nlink %x, va_fsid %lx, va_fileid %llx\n", |
printf(" va_type %d, va_nlink %x, va_fsid %"PRIx64", va_fileid %llx\n", |
vap->va_type, vap->va_nlink, vap->va_fsid, |
vap->va_type, vap->va_nlink, vap->va_fsid, |
(unsigned long long)vap->va_fileid); |
(unsigned long long)vap->va_fileid); |
printf(" va_blocksize %lx, va_rdev %x, va_bytes %qx, va_gen %lx\n", |
printf(" va_blocksize %lx, va_rdev %"PRIx64", va_bytes %"PRIx64", va_gen %lx\n", |
vap->va_blocksize, vap->va_rdev, (long long)vap->va_bytes, vap->va_gen); |
vap->va_blocksize, vap->va_rdev, vap->va_bytes, vap->va_gen); |
#endif |
#endif |
return (EINVAL); |
return (EINVAL); |
} |
} |
Line 372 msdosfs_setattr(v) |
|
Line 359 msdosfs_setattr(v) |
|
if (ap->a_vp->v_type == VDIR) |
if (ap->a_vp->v_type == VDIR) |
return 0; |
return 0; |
|
|
|
fstrans_start(vp->v_mount, FSTRANS_SHARED); |
if (vap->va_size != VNOVAL) { |
if (vap->va_size != VNOVAL) { |
if (vp->v_mount->mnt_flag & MNT_RDONLY) |
if (vp->v_mount->mnt_flag & MNT_RDONLY) { |
return (EROFS); |
error = EROFS; |
|
goto bad; |
|
} |
error = detrunc(dep, (u_long)vap->va_size, 0, cred); |
error = detrunc(dep, (u_long)vap->va_size, 0, cred); |
if (error) |
if (error) |
return (error); |
goto bad; |
de_changed = 1; |
de_changed = 1; |
} |
} |
if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { |
if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { |
if (vp->v_mount->mnt_flag & MNT_RDONLY) |
if (vp->v_mount->mnt_flag & MNT_RDONLY) { |
return (EROFS); |
error = EROFS; |
if (kauth_cred_geteuid(cred) != pmp->pm_uid && |
goto bad; |
(error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, |
} |
NULL)) && |
error = genfs_can_chtimes(ap->a_vp, vap->va_vaflags, |
((vap->va_vaflags & VA_UTIMES_NULL) == 0 || |
pmp->pm_uid, cred); |
(error = VOP_ACCESS(ap->a_vp, VWRITE, cred)))) |
if (error) |
return (error); |
goto bad; |
if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && |
if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && |
vap->va_atime.tv_sec != VNOVAL) |
vap->va_atime.tv_sec != VNOVAL) |
unix2dostime(&vap->va_atime, pmp->pm_gmtoff, &dep->de_ADate, NULL, NULL); |
unix2dostime(&vap->va_atime, pmp->pm_gmtoff, &dep->de_ADate, NULL, NULL); |
Line 404 msdosfs_setattr(v) |
|
Line 394 msdosfs_setattr(v) |
|
* attribute. |
* attribute. |
*/ |
*/ |
if (vap->va_mode != (mode_t)VNOVAL) { |
if (vap->va_mode != (mode_t)VNOVAL) { |
if (vp->v_mount->mnt_flag & MNT_RDONLY) |
if (vp->v_mount->mnt_flag & MNT_RDONLY) { |
return (EROFS); |
error = EROFS; |
|
goto bad; |
|
} |
if (kauth_cred_geteuid(cred) != pmp->pm_uid && |
if (kauth_cred_geteuid(cred) != pmp->pm_uid && |
(error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, |
(error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, |
NULL))) |
NULL))) |
return (error); |
goto bad; |
/* We ignore the read and execute bits. */ |
/* We ignore the read and execute bits. */ |
if (vap->va_mode & S_IWUSR) |
if (vap->va_mode & S_IWUSR) |
dep->de_Attributes &= ~ATTR_READONLY; |
dep->de_Attributes &= ~ATTR_READONLY; |
Line 422 msdosfs_setattr(v) |
|
Line 414 msdosfs_setattr(v) |
|
* Allow the `archived' bit to be toggled. |
* Allow the `archived' bit to be toggled. |
*/ |
*/ |
if (vap->va_flags != VNOVAL) { |
if (vap->va_flags != VNOVAL) { |
if (vp->v_mount->mnt_flag & MNT_RDONLY) |
if (vp->v_mount->mnt_flag & MNT_RDONLY) { |
return (EROFS); |
error = EROFS; |
|
goto bad; |
|
} |
if (kauth_cred_geteuid(cred) != pmp->pm_uid && |
if (kauth_cred_geteuid(cred) != pmp->pm_uid && |
(error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, |
(error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, |
NULL))) |
NULL))) |
return (error); |
goto bad; |
if (vap->va_flags & SF_ARCHIVED) |
if (vap->va_flags & SF_ARCHIVED) |
dep->de_Attributes &= ~ATTR_ARCHIVE; |
dep->de_Attributes &= ~ATTR_ARCHIVE; |
else |
else |
Line 438 msdosfs_setattr(v) |
|
Line 432 msdosfs_setattr(v) |
|
|
|
if (de_changed) { |
if (de_changed) { |
VN_KNOTE(vp, NOTE_ATTRIB); |
VN_KNOTE(vp, NOTE_ATTRIB); |
return (deupdat(dep, 1)); |
error = deupdat(dep, 1); |
} else |
if (error) |
return (0); |
goto bad; |
|
} |
|
|
|
bad: |
|
fstrans_done(vp->v_mount); |
|
return error; |
} |
} |
|
|
int |
int |
msdosfs_read(v) |
msdosfs_read(void *v) |
void *v; |
|
{ |
{ |
struct vop_read_args /* { |
struct vop_read_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
|
|
if (uio->uio_offset >= dep->de_FileSize) |
if (uio->uio_offset >= dep->de_FileSize) |
return (0); |
return (0); |
|
|
|
fstrans_start(vp->v_mount, FSTRANS_SHARED); |
if (vp->v_type == VREG) { |
if (vp->v_type == VREG) { |
const int advice = IO_ADV_DECODE(ap->a_ioflag); |
const int advice = IO_ADV_DECODE(ap->a_ioflag); |
|
|
|
|
/* convert cluster # to sector # */ |
/* convert cluster # to sector # */ |
error = pcbmap(dep, lbn, &lbn, 0, &blsize); |
error = pcbmap(dep, lbn, &lbn, 0, &blsize); |
if (error) |
if (error) |
return (error); |
goto bad; |
|
|
/* |
/* |
* If we are operating on a directory file then be sure to |
* If we are operating on a directory file then be sure to |
|
|
n = MIN(n, pmp->pm_bpcluster - bp->b_resid); |
n = MIN(n, pmp->pm_bpcluster - bp->b_resid); |
if (error) { |
if (error) { |
brelse(bp, 0); |
brelse(bp, 0); |
return (error); |
goto bad; |
} |
} |
error = uiomove((char *)bp->b_data + on, (int) n, uio); |
error = uiomove((char *)bp->b_data + on, (int) n, uio); |
brelse(bp, 0); |
brelse(bp, 0); |
|
|
out: |
out: |
if ((ap->a_ioflag & IO_SYNC) == IO_SYNC) |
if ((ap->a_ioflag & IO_SYNC) == IO_SYNC) |
error = deupdat(dep, 1); |
error = deupdat(dep, 1); |
|
bad: |
|
fstrans_done(vp->v_mount); |
return (error); |
return (error); |
} |
} |
|
|
|
|
* Write data to a file or directory. |
* Write data to a file or directory. |
*/ |
*/ |
int |
int |
msdosfs_write(v) |
msdosfs_write(void *v) |
void *v; |
|
{ |
{ |
struct vop_write_args /* { |
struct vop_write_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
Line 554 msdosfs_write(v) |
|
Line 554 msdosfs_write(v) |
|
u_long count; |
u_long count; |
vsize_t bytelen; |
vsize_t bytelen; |
off_t oldoff; |
off_t oldoff; |
|
size_t rem; |
struct uio *uio = ap->a_uio; |
struct uio *uio = ap->a_uio; |
struct proc *p = curproc; |
|
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct denode *dep = VTODE(vp); |
struct denode *dep = VTODE(vp); |
struct msdosfsmount *pmp = dep->de_pmp; |
struct msdosfsmount *pmp = dep->de_pmp; |
Line 590 msdosfs_write(v) |
|
Line 590 msdosfs_write(v) |
|
if (uio->uio_offset + uio->uio_resid > MSDOSFS_FILESIZE_MAX) |
if (uio->uio_offset + uio->uio_resid > MSDOSFS_FILESIZE_MAX) |
return (EFBIG); |
return (EFBIG); |
|
|
/* |
fstrans_start(vp->v_mount, FSTRANS_SHARED); |
* If they've exceeded their filesize limit, tell them about it. |
|
*/ |
|
if (((uio->uio_offset + uio->uio_resid) > |
|
p->p_rlimit[RLIMIT_FSIZE].rlim_cur)) { |
|
mutex_enter(proc_lock); |
|
psignal(p, SIGXFSZ); |
|
mutex_exit(proc_lock); |
|
return (EFBIG); |
|
} |
|
|
|
/* |
/* |
* If the offset we are starting the write at is beyond the end of |
* If the offset we are starting the write at is beyond the end of |
* the file, then they've done a seek. Unix filesystems allow |
* the file, then they've done a seek. Unix filesystems allow |
Line 608 msdosfs_write(v) |
|
Line 598 msdosfs_write(v) |
|
* with zeroed blocks. |
* with zeroed blocks. |
*/ |
*/ |
if (uio->uio_offset > dep->de_FileSize) { |
if (uio->uio_offset > dep->de_FileSize) { |
if ((error = deextend(dep, uio->uio_offset, cred)) != 0) |
if ((error = deextend(dep, uio->uio_offset, cred)) != 0) { |
|
fstrans_done(vp->v_mount); |
return (error); |
return (error); |
|
} |
} |
} |
|
|
/* |
/* |
Line 632 msdosfs_write(v) |
|
Line 624 msdosfs_write(v) |
|
dep->de_FileSize = uio->uio_offset + resid; |
dep->de_FileSize = uio->uio_offset + resid; |
/* hint uvm to not read in extended part */ |
/* hint uvm to not read in extended part */ |
uvm_vnp_setwritesize(vp, dep->de_FileSize); |
uvm_vnp_setwritesize(vp, dep->de_FileSize); |
|
/* zero out the remainder of the last page */ |
|
rem = round_page(dep->de_FileSize) - dep->de_FileSize; |
|
if (rem > 0) |
|
uvm_vnp_zerorange(vp, (off_t)dep->de_FileSize, rem); |
extended = 1; |
extended = 1; |
} |
} |
|
|
Line 650 msdosfs_write(v) |
|
Line 646 msdosfs_write(v) |
|
*/ |
*/ |
|
|
if (!async && oldoff >> 16 != uio->uio_offset >> 16) { |
if (!async && oldoff >> 16 != uio->uio_offset >> 16) { |
mutex_enter(&vp->v_interlock); |
mutex_enter(vp->v_interlock); |
error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16, |
error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16, |
(uio->uio_offset >> 16) << 16, PGO_CLEANIT); |
(uio->uio_offset >> 16) << 16, PGO_CLEANIT); |
} |
} |
Line 659 msdosfs_write(v) |
|
Line 655 msdosfs_write(v) |
|
/* set final size */ |
/* set final size */ |
uvm_vnp_setsize(vp, dep->de_FileSize); |
uvm_vnp_setsize(vp, dep->de_FileSize); |
if (error == 0 && ioflag & IO_SYNC) { |
if (error == 0 && ioflag & IO_SYNC) { |
mutex_enter(&vp->v_interlock); |
mutex_enter(vp->v_interlock); |
error = VOP_PUTPAGES(vp, trunc_page(oldoff), |
error = VOP_PUTPAGES(vp, trunc_page(oldoff), |
round_page(oldoff + bytelen), PGO_CLEANIT | PGO_SYNCIO); |
round_page(oldoff + bytelen), PGO_CLEANIT | PGO_SYNCIO); |
} |
} |
|
|
uio->uio_resid = resid; |
uio->uio_resid = resid; |
} else if ((ioflag & IO_SYNC) == IO_SYNC) |
} else if ((ioflag & IO_SYNC) == IO_SYNC) |
error = deupdat(dep, 1); |
error = deupdat(dep, 1); |
|
fstrans_done(vp->v_mount); |
KASSERT(vp->v_size == dep->de_FileSize); |
KASSERT(vp->v_size == dep->de_FileSize); |
return (error); |
return (error); |
} |
} |
Line 721 msdosfs_update(struct vnode *vp, const s |
|
Line 718 msdosfs_update(struct vnode *vp, const s |
|
* could just do a sync if they try an fsync on a directory file. |
* could just do a sync if they try an fsync on a directory file. |
*/ |
*/ |
int |
int |
msdosfs_remove(v) |
msdosfs_remove(void *v) |
void *v; |
|
{ |
{ |
struct vop_remove_args /* { |
struct vop_remove_args /* { |
struct vnode *a_dvp; |
struct vnode *a_dvp; |
Line 733 msdosfs_remove(v) |
|
Line 729 msdosfs_remove(v) |
|
struct denode *ddep = VTODE(ap->a_dvp); |
struct denode *ddep = VTODE(ap->a_dvp); |
int error; |
int error; |
|
|
|
fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); |
if (ap->a_vp->v_type == VDIR) |
if (ap->a_vp->v_type == VDIR) |
error = EPERM; |
error = EPERM; |
else |
else |
Line 749 msdosfs_remove(v) |
|
Line 746 msdosfs_remove(v) |
|
vput(ap->a_vp); /* causes msdosfs_inactive() to be called |
vput(ap->a_vp); /* causes msdosfs_inactive() to be called |
* via vrele() */ |
* via vrele() */ |
vput(ap->a_dvp); |
vput(ap->a_dvp); |
|
fstrans_done(ap->a_dvp->v_mount); |
return (error); |
return (error); |
} |
} |
|
|
/* |
/* |
* DOS filesystems don't know what links are. But since we already called |
|
* msdosfs_lookup() with create and lockparent, the parent is locked so we |
|
* have to free it before we return the error. |
|
*/ |
|
int |
|
msdosfs_link(v) |
|
void *v; |
|
{ |
|
struct vop_link_args /* { |
|
struct vnode *a_dvp; |
|
struct vnode *a_vp; |
|
struct componentname *a_cnp; |
|
} */ *ap = v; |
|
|
|
VOP_ABORTOP(ap->a_dvp, ap->a_cnp); |
|
vput(ap->a_dvp); |
|
return (EOPNOTSUPP); |
|
} |
|
|
|
/* |
|
* Renames on files require moving the denode to a new hash queue since the |
* Renames on files require moving the denode to a new hash queue since the |
* denode's location is used to compute which hash queue to put the file |
* denode's location is used to compute which hash queue to put the file |
* in. Unless it is a rename in place. For example "mv a b". |
* in. Unless it is a rename in place. For example "mv a b". |
|
|
* This routine needs help. badly. |
* This routine needs help. badly. |
*/ |
*/ |
int |
int |
msdosfs_rename(v) |
msdosfs_rename(void *v) |
void *v; |
|
{ |
{ |
struct vop_rename_args /* { |
struct vop_rename_args /* { |
struct vnode *a_fdvp; |
struct vnode *a_fdvp; |
Line 847 msdosfs_rename(v) |
|
Line 824 msdosfs_rename(v) |
|
struct componentname *tcnp = ap->a_tcnp; |
struct componentname *tcnp = ap->a_tcnp; |
struct componentname *fcnp = ap->a_fcnp; |
struct componentname *fcnp = ap->a_fcnp; |
struct denode *ip, *xp, *dp, *zp; |
struct denode *ip, *xp, *dp, *zp; |
u_char toname[11], oldname[11]; |
u_char toname[12], oldname[12]; |
u_long from_diroffset, to_diroffset; |
u_long from_diroffset, to_diroffset; |
u_char to_count; |
u_char to_count; |
int doingdirectory = 0, newparent = 0; |
int doingdirectory = 0, newparent = 0; |
Line 857 msdosfs_rename(v) |
|
Line 834 msdosfs_rename(v) |
|
struct msdosfsmount *pmp; |
struct msdosfsmount *pmp; |
struct direntry *dotdotp; |
struct direntry *dotdotp; |
struct buf *bp; |
struct buf *bp; |
int fdvp_dorele = 0; |
|
|
|
pmp = VFSTOMSDOSFS(fdvp->v_mount); |
pmp = VFSTOMSDOSFS(fdvp->v_mount); |
|
|
#ifdef DIAGNOSTIC |
|
if ((tcnp->cn_flags & HASBUF) == 0 || |
|
(fcnp->cn_flags & HASBUF) == 0) |
|
panic("msdosfs_rename: no name"); |
|
#endif |
|
/* |
/* |
* Check for cross-device rename. |
* Check for cross-device rename. |
*/ |
*/ |
|
|
(fcnp->cn_flags & ISDOTDOT) || |
(fcnp->cn_flags & ISDOTDOT) || |
(tcnp->cn_flags & ISDOTDOT) || |
(tcnp->cn_flags & ISDOTDOT) || |
(ip->de_flag & DE_RENAME)) { |
(ip->de_flag & DE_RENAME)) { |
VOP_UNLOCK(fvp, 0); |
VOP_UNLOCK(fvp); |
error = EINVAL; |
error = EINVAL; |
goto abortit; |
goto abortit; |
} |
} |
|
|
} |
} |
VN_KNOTE(fdvp, NOTE_WRITE); /* XXXLUKEM/XXX: right place? */ |
VN_KNOTE(fdvp, NOTE_WRITE); /* XXXLUKEM/XXX: right place? */ |
|
|
|
fstrans_start(fdvp->v_mount, FSTRANS_SHARED); |
/* |
/* |
* When the target exists, both the directory |
* When the target exists, both the directory |
* and target vnodes are returned locked. |
* and target vnodes are returned locked. |
|
|
* call to doscheckpath(). |
* call to doscheckpath(). |
*/ |
*/ |
error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred); |
error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred); |
VOP_UNLOCK(fvp, 0); |
VOP_UNLOCK(fvp); |
if (VTODE(fdvp)->de_StartCluster != VTODE(tdvp)->de_StartCluster) |
if (VTODE(fdvp)->de_StartCluster != VTODE(tdvp)->de_StartCluster) |
newparent = 1; |
newparent = 1; |
|
|
/* |
|
* XXX: We can do this here because rename uses SAVEFART and |
|
* therefore fdvp has at least two references (one doesn't |
|
* belong to us, though, and that's evil). We'll get |
|
* another "extra" reference when we do relookup(), so we |
|
* need to compensate. We should *NOT* be doing this, but |
|
* it works, so whatever. |
|
*/ |
|
vrele(fdvp); |
|
|
|
if (doingdirectory && newparent) { |
if (doingdirectory && newparent) { |
if (error) /* write access check above */ |
if (error) /* write access check above */ |
goto tdvpbad; |
goto tdvpbad; |
|
|
vput(tvp); |
vput(tvp); |
tvp = NULL; |
tvp = NULL; |
/* |
/* |
* doscheckpath() vput()'s dp, |
* doscheckpath() vput()'s tdvp (dp == VTODE(tdvp)), |
* so we have to do a relookup afterwards |
* so we have to get an extra ref to it first, and |
|
* because it's been unlocked we need to do a relookup |
|
* afterwards in case tvp has changed. |
*/ |
*/ |
|
vref(tdvp); |
if ((error = doscheckpath(ip, dp)) != 0) |
if ((error = doscheckpath(ip, dp)) != 0) |
goto out; |
goto bad; |
if ((tcnp->cn_flags & SAVESTART) == 0) |
|
panic("msdosfs_rename: lost to startdir"); |
|
vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY); |
vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY); |
if ((error = relookup(tdvp, &tvp, tcnp)) != 0) { |
if ((error = relookup(tdvp, &tvp, tcnp, 0)) != 0) { |
VOP_UNLOCK(tdvp, 0); |
VOP_UNLOCK(tdvp); |
goto out; |
goto bad; |
} |
} |
/* |
|
* XXX: SAVESTART causes us to get a reference, but |
|
* that's released already above in doscheckpath() |
|
*/ |
|
dp = VTODE(tdvp); |
dp = VTODE(tdvp); |
xp = tvp ? VTODE(tvp) : NULL; |
xp = tvp ? VTODE(tvp) : NULL; |
} |
} |
|
|
* into the denode and directory entry for the destination |
* into the denode and directory entry for the destination |
* file/directory. |
* file/directory. |
*/ |
*/ |
if ((error = uniqdosname(VTODE(tdvp), tcnp, toname)) != 0) |
if ((error = uniqdosname(VTODE(tdvp), tcnp, toname)) != 0) { |
|
fstrans_done(fdvp->v_mount); |
goto abortit; |
goto abortit; |
|
} |
|
|
/* |
/* |
* Since from wasn't locked at various places above, |
* Since from wasn't locked at various places above, |
|
|
*/ |
*/ |
fcnp->cn_flags &= ~MODMASK; |
fcnp->cn_flags &= ~MODMASK; |
fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; |
fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; |
if ((fcnp->cn_flags & SAVESTART) == 0) |
VOP_UNLOCK(tdvp); |
panic("msdosfs_rename: lost from startdir"); |
|
VOP_UNLOCK(tdvp, 0); |
|
vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY); |
vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY); |
if ((error = relookup(fdvp, &fvp, fcnp))) { |
if ((error = relookup(fdvp, &fvp, fcnp, 0))) { |
VOP_UNLOCK(fdvp, 0); |
VOP_UNLOCK(fdvp); |
vrele(ap->a_fvp); |
vrele(ap->a_fvp); |
vrele(tdvp); |
vrele(tdvp); |
|
fstrans_done(fdvp->v_mount); |
return (error); |
return (error); |
} |
} |
if (fvp == NULL) { |
if (fvp == NULL) { |
|
|
vput(fdvp); |
vput(fdvp); |
vrele(ap->a_fvp); |
vrele(ap->a_fvp); |
vrele(tdvp); |
vrele(tdvp); |
|
fstrans_done(fdvp->v_mount); |
return 0; |
return 0; |
} |
} |
fdvp_dorele = 1; |
VOP_UNLOCK(fdvp); |
VOP_UNLOCK(fdvp, 0); |
|
xp = VTODE(fvp); |
xp = VTODE(fvp); |
zp = VTODE(fdvp); |
zp = VTODE(fdvp); |
from_diroffset = zp->de_fndoffset; |
from_diroffset = zp->de_fndoffset; |
|
|
if (doingdirectory) |
if (doingdirectory) |
panic("rename: lost dir entry"); |
panic("rename: lost dir entry"); |
vrele(ap->a_fvp); |
vrele(ap->a_fvp); |
VOP_UNLOCK(fvp, 0); |
|
xp = NULL; |
xp = NULL; |
} else { |
} else { |
vrele(fvp); |
vrele(fvp); |
|
|
error = createde(ip, dp, (struct denode **)0, tcnp); |
error = createde(ip, dp, (struct denode **)0, tcnp); |
if (error) { |
if (error) { |
memcpy(ip->de_Name, oldname, 11); |
memcpy(ip->de_Name, oldname, 11); |
VOP_UNLOCK(fvp, 0); |
VOP_UNLOCK(fvp); |
goto bad; |
goto bad; |
} |
} |
ip->de_refcnt++; |
ip->de_refcnt++; |
zp->de_fndoffset = from_diroffset; |
zp->de_fndoffset = from_diroffset; |
if ((error = removede(zp, ip)) != 0) { |
if ((error = removede(zp, ip)) != 0) { |
/* XXX should really panic here, fs is corrupt */ |
/* XXX should really panic here, fs is corrupt */ |
VOP_UNLOCK(fvp, 0); |
VOP_UNLOCK(fvp); |
goto bad; |
goto bad; |
} |
} |
cache_purge(fvp); |
cache_purge(fvp); |
|
|
&ip->de_dirclust, 0); |
&ip->de_dirclust, 0); |
if (error) { |
if (error) { |
/* XXX should really panic here, fs is corrupt */ |
/* XXX should really panic here, fs is corrupt */ |
VOP_UNLOCK(fvp, 0); |
VOP_UNLOCK(fvp); |
goto bad; |
goto bad; |
} |
} |
ip->de_diroffset = to_diroffset; |
ip->de_diroffset = to_diroffset; |
|
|
if (error) { |
if (error) { |
/* XXX should really panic here, fs is corrupt */ |
/* XXX should really panic here, fs is corrupt */ |
brelse(bp, 0); |
brelse(bp, 0); |
VOP_UNLOCK(fvp, 0); |
VOP_UNLOCK(fvp); |
goto bad; |
goto bad; |
} |
} |
dotdotp = (struct direntry *)bp->b_data + 1; |
dotdotp = (struct direntry *)bp->b_data + 1; |
|
|
} |
} |
if ((error = bwrite(bp)) != 0) { |
if ((error = bwrite(bp)) != 0) { |
/* XXX should really panic here, fs is corrupt */ |
/* XXX should really panic here, fs is corrupt */ |
VOP_UNLOCK(fvp, 0); |
VOP_UNLOCK(fvp); |
goto bad; |
goto bad; |
} |
} |
} |
} |
|
|
VN_KNOTE(fvp, NOTE_RENAME); |
VN_KNOTE(fvp, NOTE_RENAME); |
VOP_UNLOCK(fvp, 0); |
VOP_UNLOCK(fvp); |
bad: |
bad: |
if (tvp) |
if (tvp) |
vput(tvp); |
vput(tvp); |
vrele(tdvp); |
vrele(tdvp); |
out: |
|
ip->de_flag &= ~DE_RENAME; |
ip->de_flag &= ~DE_RENAME; |
if (fdvp_dorele) |
vrele(fdvp); |
vrele(fdvp); |
|
vrele(fvp); |
vrele(fvp); |
|
fstrans_done(fdvp->v_mount); |
return (error); |
return (error); |
|
|
/* XXX: uuuh */ |
/* XXX: uuuh */ |
tdvpbad: |
tdvpbad: |
VOP_UNLOCK(tdvp, 0); |
VOP_UNLOCK(tdvp); |
goto bad; |
goto bad; |
} |
} |
|
|
Line 1200 static const struct { |
|
Line 1158 static const struct { |
|
}; |
}; |
|
|
int |
int |
msdosfs_mkdir(v) |
msdosfs_mkdir(void *v) |
void *v; |
|
{ |
{ |
struct vop_mkdir_args /* { |
struct vop_mkdir_args /* { |
struct vnode *a_dvp; |
struct vnode *a_dvp; |
Line 1222 msdosfs_mkdir(v) |
|
Line 1179 msdosfs_mkdir(v) |
|
struct buf *bp; |
struct buf *bp; |
int async = pdep->de_pmp->pm_mountp->mnt_flag & MNT_ASYNC; |
int async = pdep->de_pmp->pm_mountp->mnt_flag & MNT_ASYNC; |
|
|
|
fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); |
/* |
/* |
* If this is the root directory and there is no space left we |
* If this is the root directory and there is no space left we |
* can't do anything. This is because the root directory can not |
* can't do anything. This is because the root directory can not |
Line 1292 msdosfs_mkdir(v) |
|
Line 1250 msdosfs_mkdir(v) |
|
* cluster. This will be written to an empty slot in the parent |
* cluster. This will be written to an empty slot in the parent |
* directory. |
* directory. |
*/ |
*/ |
#ifdef DIAGNOSTIC |
|
if ((cnp->cn_flags & HASBUF) == 0) |
|
panic("msdosfs_mkdir: no name"); |
|
#endif |
|
if ((error = uniqdosname(pdep, cnp, ndirent.de_Name)) != 0) |
if ((error = uniqdosname(pdep, cnp, ndirent.de_Name)) != 0) |
goto bad; |
goto bad; |
|
|
Line 1306 msdosfs_mkdir(v) |
|
Line 1260 msdosfs_mkdir(v) |
|
ndirent.de_devvp = pdep->de_devvp; |
ndirent.de_devvp = pdep->de_devvp; |
if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0) |
if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0) |
goto bad; |
goto bad; |
if ((cnp->cn_flags & SAVESTART) == 0) |
|
PNBUF_PUT(cnp->cn_pnbuf); |
|
VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK); |
VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK); |
vput(ap->a_dvp); |
vput(ap->a_dvp); |
*ap->a_vpp = DETOV(dep); |
*ap->a_vpp = DETOV(dep); |
|
fstrans_done(ap->a_dvp->v_mount); |
return (0); |
return (0); |
|
|
bad: |
bad: |
clusterfree(pmp, newcluster, NULL); |
clusterfree(pmp, newcluster, NULL); |
bad2: |
bad2: |
PNBUF_PUT(cnp->cn_pnbuf); |
|
vput(ap->a_dvp); |
vput(ap->a_dvp); |
|
fstrans_done(ap->a_dvp->v_mount); |
return (error); |
return (error); |
} |
} |
|
|
int |
int |
msdosfs_rmdir(v) |
msdosfs_rmdir(void *v) |
void *v; |
|
{ |
{ |
struct vop_rmdir_args /* { |
struct vop_rmdir_args /* { |
struct vnode *a_dvp; |
struct vnode *a_dvp; |
Line 1346 msdosfs_rmdir(v) |
|
Line 1298 msdosfs_rmdir(v) |
|
vput(vp); |
vput(vp); |
return (EINVAL); |
return (EINVAL); |
} |
} |
|
fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); |
/* |
/* |
* Verify the directory is empty (and valid). |
* Verify the directory is empty (and valid). |
* (Rmdir ".." won't be valid since |
* (Rmdir ".." won't be valid since |
|
|
if (dvp) |
if (dvp) |
vput(dvp); |
vput(dvp); |
vput(vp); |
vput(vp); |
|
fstrans_done(ap->a_dvp->v_mount); |
return (error); |
return (error); |
} |
} |
|
|
/* |
|
* DOS filesystems don't know what symlinks are. |
|
*/ |
|
int |
int |
msdosfs_symlink(v) |
msdosfs_readdir(void *v) |
void *v; |
|
{ |
|
struct vop_symlink_args /* { |
|
struct vnode *a_dvp; |
|
struct vnode **a_vpp; |
|
struct componentname *a_cnp; |
|
struct vattr *a_vap; |
|
char *a_target; |
|
} */ *ap = v; |
|
|
|
VOP_ABORTOP(ap->a_dvp, ap->a_cnp); |
|
vput(ap->a_dvp); |
|
return (EOPNOTSUPP); |
|
} |
|
|
|
int |
|
msdosfs_readdir(v) |
|
void *v; |
|
{ |
{ |
struct vop_readdir_args /* { |
struct vop_readdir_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
Line 1473 msdosfs_readdir(v) |
|
Line 1406 msdosfs_readdir(v) |
|
uio->uio_resid = count; |
uio->uio_resid = count; |
uio_off = uio->uio_offset; |
uio_off = uio->uio_offset; |
|
|
|
fstrans_start(ap->a_vp->v_mount, FSTRANS_SHARED); |
|
|
/* Allocate a temporary dirent buffer. */ |
/* Allocate a temporary dirent buffer. */ |
dirbuf = malloc(sizeof(struct dirent), M_MSDOSFSTMP, M_WAITOK | M_ZERO); |
dirbuf = malloc(sizeof(struct dirent), M_MSDOSFSTMP, M_WAITOK | M_ZERO); |
|
|
Line 1552 msdosfs_readdir(v) |
|
Line 1487 msdosfs_readdir(v) |
|
NOCRED, 0, &bp); |
NOCRED, 0, &bp); |
if (error) { |
if (error) { |
brelse(bp, 0); |
brelse(bp, 0); |
free(dirbuf, M_MSDOSFSTMP); |
goto bad; |
return (error); |
|
} |
} |
n = MIN(n, blsize - bp->b_resid); |
n = MIN(n, blsize - bp->b_resid); |
|
|
|
|
} else |
} else |
*ap->a_ncookies = ncookies; |
*ap->a_ncookies = ncookies; |
} |
} |
|
|
|
bad: |
free(dirbuf, M_MSDOSFSTMP); |
free(dirbuf, M_MSDOSFSTMP); |
|
fstrans_done(ap->a_vp->v_mount); |
return (error); |
return (error); |
} |
} |
|
|
/* |
/* |
* DOS filesystems don't know what symlinks are. |
|
*/ |
|
int |
|
msdosfs_readlink(void *v) |
|
{ |
|
#if 0 |
|
struct vop_readlink_args /* { |
|
struct vnode *a_vp; |
|
struct uio *a_uio; |
|
kauth_cred_t a_cred; |
|
} */ *ap; |
|
#endif |
|
|
|
return (EINVAL); |
|
} |
|
|
|
/* |
|
* vp - address of vnode file the file |
* vp - address of vnode file the file |
* bn - which cluster we are interested in mapping to a filesystem block number. |
* bn - which cluster we are interested in mapping to a filesystem block number. |
* vpp - returns the vnode for the block special file holding the filesystem |
* vpp - returns the vnode for the block special file holding the filesystem |
Line 1703 msdosfs_readlink(void *v) |
|
Line 1623 msdosfs_readlink(void *v) |
|
* bnp - address of where to return the filesystem relative block number |
* bnp - address of where to return the filesystem relative block number |
*/ |
*/ |
int |
int |
msdosfs_bmap(v) |
msdosfs_bmap(void *v) |
void *v; |
|
{ |
{ |
struct vop_bmap_args /* { |
struct vop_bmap_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
Line 1753 msdosfs_bmap(v) |
|
Line 1672 msdosfs_bmap(v) |
|
} |
} |
|
|
int |
int |
msdosfs_strategy(v) |
msdosfs_strategy(void *v) |
void *v; |
|
{ |
{ |
struct vop_strategy_args /* { |
struct vop_strategy_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
Line 1798 msdosfs_strategy(v) |
|
Line 1716 msdosfs_strategy(v) |
|
} |
} |
|
|
int |
int |
msdosfs_print(v) |
msdosfs_print(void *v) |
void *v; |
|
{ |
{ |
struct vop_print_args /* { |
struct vop_print_args /* { |
struct vnode *vp; |
struct vnode *vp; |
Line 1809 msdosfs_print(v) |
|
Line 1726 msdosfs_print(v) |
|
printf( |
printf( |
"tag VT_MSDOSFS, startcluster %ld, dircluster %ld, diroffset %ld ", |
"tag VT_MSDOSFS, startcluster %ld, dircluster %ld, diroffset %ld ", |
dep->de_StartCluster, dep->de_dirclust, dep->de_diroffset); |
dep->de_StartCluster, dep->de_dirclust, dep->de_diroffset); |
printf(" dev %d, %d ", major(dep->de_dev), minor(dep->de_dev)); |
printf(" dev %llu, %llu ", (unsigned long long)major(dep->de_dev), |
|
(unsigned long long)minor(dep->de_dev)); |
printf("\n"); |
printf("\n"); |
return (0); |
return (0); |
} |
} |
|
|
int |
int |
msdosfs_advlock(v) |
msdosfs_advlock(void *v) |
void *v; |
|
{ |
{ |
struct vop_advlock_args /* { |
struct vop_advlock_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
Line 1831 msdosfs_advlock(v) |
|
Line 1748 msdosfs_advlock(v) |
|
} |
} |
|
|
int |
int |
msdosfs_pathconf(v) |
msdosfs_pathconf(void *v) |
void *v; |
|
{ |
{ |
struct vop_pathconf_args /* { |
struct vop_pathconf_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
Line 1869 msdosfs_pathconf(v) |
|
Line 1785 msdosfs_pathconf(v) |
|
} |
} |
|
|
int |
int |
msdosfs_fsync(v) |
msdosfs_fsync(void *v) |
void *v; |
|
{ |
{ |
struct vop_fsync_args /* { |
struct vop_fsync_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
Line 1883 msdosfs_fsync(v) |
|
Line 1798 msdosfs_fsync(v) |
|
int wait; |
int wait; |
int error; |
int error; |
|
|
|
fstrans_start(vp->v_mount, FSTRANS_LAZY); |
wait = (ap->a_flags & FSYNC_WAIT) != 0; |
wait = (ap->a_flags & FSYNC_WAIT) != 0; |
vflushbuf(vp, wait); |
error = vflushbuf(vp, wait); |
if ((ap->a_flags & FSYNC_DATAONLY) != 0) |
if (error == 0 && (ap->a_flags & FSYNC_DATAONLY) == 0) |
error = 0; |
|
else |
|
error = msdosfs_update(vp, NULL, NULL, wait ? UPDATE_WAIT : 0); |
error = msdosfs_update(vp, NULL, NULL, wait ? UPDATE_WAIT : 0); |
|
|
if (error == 0 && ap->a_flags & FSYNC_CACHE) { |
if (error == 0 && ap->a_flags & FSYNC_CACHE) { |
Line 1898 msdosfs_fsync(v) |
|
Line 1812 msdosfs_fsync(v) |
|
error = VOP_IOCTL(devvp, DIOCCACHESYNC, &l, FWRITE, |
error = VOP_IOCTL(devvp, DIOCCACHESYNC, &l, FWRITE, |
curlwp->l_cred); |
curlwp->l_cred); |
} |
} |
|
fstrans_done(vp->v_mount); |
|
|
return (error); |
return (error); |
} |
} |
Line 1944 const struct vnodeopv_entry_desc msdosfs |
|
Line 1859 const struct vnodeopv_entry_desc msdosfs |
|
{ &vop_default_desc, vn_default_error }, |
{ &vop_default_desc, vn_default_error }, |
{ &vop_lookup_desc, msdosfs_lookup }, /* lookup */ |
{ &vop_lookup_desc, msdosfs_lookup }, /* lookup */ |
{ &vop_create_desc, msdosfs_create }, /* create */ |
{ &vop_create_desc, msdosfs_create }, /* create */ |
{ &vop_mknod_desc, msdosfs_mknod }, /* mknod */ |
{ &vop_mknod_desc, genfs_eopnotsupp }, /* mknod */ |
{ &vop_open_desc, msdosfs_open }, /* open */ |
{ &vop_open_desc, genfs_nullop }, /* open */ |
{ &vop_close_desc, msdosfs_close }, /* close */ |
{ &vop_close_desc, msdosfs_close }, /* close */ |
{ &vop_access_desc, msdosfs_access }, /* access */ |
{ &vop_access_desc, msdosfs_access }, /* access */ |
{ &vop_getattr_desc, msdosfs_getattr }, /* getattr */ |
{ &vop_getattr_desc, msdosfs_getattr }, /* getattr */ |
Line 1961 const struct vnodeopv_entry_desc msdosfs |
|
Line 1876 const struct vnodeopv_entry_desc msdosfs |
|
{ &vop_fsync_desc, msdosfs_fsync }, /* fsync */ |
{ &vop_fsync_desc, msdosfs_fsync }, /* fsync */ |
{ &vop_seek_desc, msdosfs_seek }, /* seek */ |
{ &vop_seek_desc, msdosfs_seek }, /* seek */ |
{ &vop_remove_desc, msdosfs_remove }, /* remove */ |
{ &vop_remove_desc, msdosfs_remove }, /* remove */ |
{ &vop_link_desc, msdosfs_link }, /* link */ |
{ &vop_link_desc, genfs_eopnotsupp }, /* link */ |
{ &vop_rename_desc, msdosfs_rename }, /* rename */ |
{ &vop_rename_desc, msdosfs_rename }, /* rename */ |
{ &vop_mkdir_desc, msdosfs_mkdir }, /* mkdir */ |
{ &vop_mkdir_desc, msdosfs_mkdir }, /* mkdir */ |
{ &vop_rmdir_desc, msdosfs_rmdir }, /* rmdir */ |
{ &vop_rmdir_desc, msdosfs_rmdir }, /* rmdir */ |
{ &vop_symlink_desc, msdosfs_symlink }, /* symlink */ |
{ &vop_symlink_desc, genfs_eopnotsupp }, /* symlink */ |
{ &vop_readdir_desc, msdosfs_readdir }, /* readdir */ |
{ &vop_readdir_desc, msdosfs_readdir }, /* readdir */ |
{ &vop_readlink_desc, msdosfs_readlink }, /* readlink */ |
{ &vop_readlink_desc, genfs_einval }, /* readlink */ |
{ &vop_abortop_desc, msdosfs_abortop }, /* abortop */ |
{ &vop_abortop_desc, msdosfs_abortop }, /* abortop */ |
{ &vop_inactive_desc, msdosfs_inactive }, /* inactive */ |
{ &vop_inactive_desc, msdosfs_inactive }, /* inactive */ |
{ &vop_reclaim_desc, msdosfs_reclaim }, /* reclaim */ |
{ &vop_reclaim_desc, msdosfs_reclaim }, /* reclaim */ |