1 1.69 mlelstv /* $NetBSD: sysvbfs_vnops.c,v 1.69 2022/07/31 13:08:18 mlelstv Exp $ */ 2 1.1 tsutsui 3 1.1 tsutsui /*- 4 1.1 tsutsui * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 1.1 tsutsui * All rights reserved. 6 1.1 tsutsui * 7 1.1 tsutsui * This code is derived from software contributed to The NetBSD Foundation 8 1.1 tsutsui * by UCHIYAMA Yasushi. 9 1.1 tsutsui * 10 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 11 1.1 tsutsui * modification, are permitted provided that the following conditions 12 1.1 tsutsui * are met: 13 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 14 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 15 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 17 1.1 tsutsui * documentation and/or other materials provided with the distribution. 18 1.1 tsutsui * 19 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 tsutsui * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 tsutsui * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 tsutsui * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 tsutsui * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 tsutsui * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 tsutsui * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 tsutsui * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 tsutsui * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 tsutsui * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 tsutsui * POSSIBILITY OF SUCH DAMAGE. 30 1.1 tsutsui */ 31 1.1 tsutsui 32 1.1 tsutsui #include <sys/cdefs.h> 33 1.69 mlelstv __KERNEL_RCSID(0, "$NetBSD: sysvbfs_vnops.c,v 1.69 2022/07/31 13:08:18 mlelstv Exp $"); 34 1.1 tsutsui 35 1.1 tsutsui #include <sys/param.h> 36 1.1 tsutsui #include <sys/kernel.h> 37 1.1 tsutsui #include <sys/resource.h> 38 1.1 tsutsui #include <sys/vnode.h> 39 1.1 tsutsui #include <sys/namei.h> 40 1.1 tsutsui #include <sys/dirent.h> 41 1.1 tsutsui #include <sys/malloc.h> 42 1.1 tsutsui #include <sys/lockf.h> 43 1.1 tsutsui #include <sys/unistd.h> 44 1.1 tsutsui #include <sys/fcntl.h> 45 1.3 yamt #include <sys/kauth.h> 46 1.20 pooka #include <sys/buf.h> 47 1.1 tsutsui 48 1.22 elad #include <miscfs/genfs/genfs.h> 49 1.22 elad 50 1.1 tsutsui #include <fs/sysvbfs/sysvbfs.h> 51 1.1 tsutsui #include <fs/sysvbfs/bfs.h> 52 1.1 tsutsui 53 1.1 tsutsui #ifdef SYSVBFS_VNOPS_DEBUG 54 1.1 tsutsui #define DPRINTF(fmt, args...) printf(fmt, ##args) 55 1.1 tsutsui #else 56 1.1 tsutsui #define DPRINTF(arg...) ((void)0) 57 1.1 tsutsui #endif 58 1.1 tsutsui #define ROUND_SECTOR(x) (((x) + 511) & ~511) 59 1.1 tsutsui 60 1.12 pooka MALLOC_JUSTDEFINE(M_SYSVBFS_VNODE, "sysvbfs vnode", "sysvbfs vnode structures"); 61 1.14 rumble MALLOC_DECLARE(M_BFS); 62 1.1 tsutsui 63 1.45 tsutsui static void sysvbfs_file_setsize(struct vnode *, size_t); 64 1.45 tsutsui 65 1.1 tsutsui int 66 1.1 tsutsui sysvbfs_lookup(void *arg) 67 1.1 tsutsui { 68 1.53 hannken struct vop_lookup_v2_args /* { 69 1.1 tsutsui struct vnode *a_dvp; 70 1.1 tsutsui struct vnode **a_vpp; 71 1.1 tsutsui struct componentname *a_cnp; 72 1.1 tsutsui } */ *a = arg; 73 1.1 tsutsui struct vnode *v = a->a_dvp; 74 1.1 tsutsui struct sysvbfs_node *bnode = v->v_data; 75 1.1 tsutsui struct bfs *bfs = bnode->bmp->bfs; /* my filesystem */ 76 1.1 tsutsui struct vnode *vpp = NULL; 77 1.1 tsutsui struct bfs_dirent *dirent = NULL; 78 1.1 tsutsui struct componentname *cnp = a->a_cnp; 79 1.1 tsutsui int nameiop = cnp->cn_nameiop; 80 1.1 tsutsui const char *name = cnp->cn_nameptr; 81 1.1 tsutsui int namelen = cnp->cn_namelen; 82 1.1 tsutsui int error; 83 1.1 tsutsui 84 1.19 ad DPRINTF("%s: %s op=%d %d\n", __func__, name, nameiop, 85 1.1 tsutsui cnp->cn_flags); 86 1.1 tsutsui 87 1.27 pooka *a->a_vpp = NULL; 88 1.27 pooka 89 1.6 chs KASSERT((cnp->cn_flags & ISDOTDOT) == 0); 90 1.36 njoly 91 1.15 pooka if ((error = VOP_ACCESS(a->a_dvp, VEXEC, cnp->cn_cred)) != 0) { 92 1.32 njoly return error; /* directory permission. */ 93 1.1 tsutsui } 94 1.1 tsutsui 95 1.36 njoly /* Deny last component write operation on a read-only mount */ 96 1.36 njoly if ((cnp->cn_flags & ISLASTCN) && (v->v_mount->mnt_flag & MNT_RDONLY) && 97 1.36 njoly (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 98 1.36 njoly return EROFS; 99 1.36 njoly 100 1.1 tsutsui if (namelen == 1 && name[0] == '.') { /* "." */ 101 1.26 pooka vref(v); 102 1.1 tsutsui *a->a_vpp = v; 103 1.1 tsutsui } else { /* Regular file */ 104 1.1 tsutsui if (!bfs_dirent_lookup_by_name(bfs, cnp->cn_nameptr, 105 1.1 tsutsui &dirent)) { 106 1.1 tsutsui if (nameiop != CREATE && nameiop != RENAME) { 107 1.1 tsutsui DPRINTF("%s: no such a file. (1)\n", 108 1.16 perry __func__); 109 1.1 tsutsui return ENOENT; 110 1.1 tsutsui } 111 1.15 pooka if ((error = VOP_ACCESS(v, VWRITE, cnp->cn_cred)) != 0) 112 1.1 tsutsui return error; 113 1.1 tsutsui return EJUSTRETURN; 114 1.1 tsutsui } 115 1.1 tsutsui 116 1.1 tsutsui /* Allocate v-node */ 117 1.64 ad error = sysvbfs_vget(v->v_mount, dirent->inode, 118 1.64 ad LK_EXCLUSIVE, &vpp); 119 1.64 ad if (error != 0) { 120 1.16 perry DPRINTF("%s: can't get vnode.\n", __func__); 121 1.1 tsutsui return error; 122 1.1 tsutsui } 123 1.53 hannken VOP_UNLOCK(vpp); 124 1.1 tsutsui *a->a_vpp = vpp; 125 1.1 tsutsui } 126 1.1 tsutsui 127 1.1 tsutsui return 0; 128 1.1 tsutsui } 129 1.1 tsutsui 130 1.1 tsutsui int 131 1.1 tsutsui sysvbfs_create(void *arg) 132 1.1 tsutsui { 133 1.52 hannken struct vop_create_v3_args /* { 134 1.1 tsutsui struct vnode *a_dvp; 135 1.1 tsutsui struct vnode **a_vpp; 136 1.1 tsutsui struct componentname *a_cnp; 137 1.1 tsutsui struct vattr *a_vap; 138 1.1 tsutsui } */ *a = arg; 139 1.1 tsutsui struct sysvbfs_node *bnode = a->a_dvp->v_data; 140 1.1 tsutsui struct sysvbfs_mount *bmp = bnode->bmp; 141 1.1 tsutsui struct bfs *bfs = bmp->bfs; 142 1.1 tsutsui struct mount *mp = bmp->mountp; 143 1.1 tsutsui struct bfs_dirent *dirent; 144 1.1 tsutsui struct bfs_fileattr attr; 145 1.1 tsutsui struct vattr *va = a->a_vap; 146 1.2 elad kauth_cred_t cr = a->a_cnp->cn_cred; 147 1.1 tsutsui int err = 0; 148 1.1 tsutsui 149 1.16 perry DPRINTF("%s: %s\n", __func__, a->a_cnp->cn_nameptr); 150 1.1 tsutsui KDASSERT(a->a_vap->va_type == VREG); 151 1.3 yamt attr.uid = kauth_cred_geteuid(cr); 152 1.3 yamt attr.gid = kauth_cred_getegid(cr); 153 1.1 tsutsui attr.mode = va->va_mode; 154 1.1 tsutsui 155 1.1 tsutsui if ((err = bfs_file_create(bfs, a->a_cnp->cn_nameptr, 0, 0, &attr)) 156 1.1 tsutsui != 0) { 157 1.16 perry DPRINTF("%s: bfs_file_create failed.\n", __func__); 158 1.51 hannken return err; 159 1.1 tsutsui } 160 1.1 tsutsui 161 1.1 tsutsui if (!bfs_dirent_lookup_by_name(bfs, a->a_cnp->cn_nameptr, &dirent)) 162 1.1 tsutsui panic("no dirent for created file."); 163 1.1 tsutsui 164 1.64 ad err = sysvbfs_vget(mp, dirent->inode, LK_EXCLUSIVE, a->a_vpp); 165 1.64 ad if (err != 0) { 166 1.16 perry DPRINTF("%s: sysvbfs_vget failed.\n", __func__); 167 1.51 hannken return err; 168 1.1 tsutsui } 169 1.1 tsutsui bnode = (*a->a_vpp)->v_data; 170 1.11 thorpej bnode->update_ctime = true; 171 1.11 thorpej bnode->update_mtime = true; 172 1.11 thorpej bnode->update_atime = true; 173 1.52 hannken VOP_UNLOCK(*a->a_vpp); 174 1.1 tsutsui 175 1.1 tsutsui return err; 176 1.1 tsutsui } 177 1.1 tsutsui 178 1.1 tsutsui int 179 1.1 tsutsui sysvbfs_open(void *arg) 180 1.1 tsutsui { 181 1.1 tsutsui struct vop_open_args /* { 182 1.1 tsutsui struct vnode *a_vp; 183 1.1 tsutsui int a_mode; 184 1.2 elad kauth_cred_t a_cred; 185 1.1 tsutsui } */ *a = arg; 186 1.1 tsutsui struct vnode *v = a->a_vp; 187 1.1 tsutsui struct sysvbfs_node *bnode = v->v_data; 188 1.1 tsutsui struct bfs_inode *inode = bnode->inode; 189 1.1 tsutsui 190 1.16 perry DPRINTF("%s:\n", __func__); 191 1.1 tsutsui KDASSERT(v->v_type == VREG || v->v_type == VDIR); 192 1.1 tsutsui 193 1.11 thorpej bnode->update_atime = true; 194 1.1 tsutsui if ((a->a_mode & FWRITE) && !(a->a_mode & O_APPEND)) { 195 1.1 tsutsui bnode->size = 0; 196 1.1 tsutsui } else { 197 1.1 tsutsui bnode->size = bfs_file_size(inode); 198 1.1 tsutsui } 199 1.1 tsutsui bnode->data_block = inode->start_sector; 200 1.1 tsutsui 201 1.1 tsutsui return 0; 202 1.1 tsutsui } 203 1.1 tsutsui 204 1.1 tsutsui int 205 1.1 tsutsui sysvbfs_close(void *arg) 206 1.1 tsutsui { 207 1.1 tsutsui struct vop_close_args /* { 208 1.1 tsutsui struct vnodeop_desc *a_desc; 209 1.1 tsutsui struct vnode *a_vp; 210 1.1 tsutsui int a_fflag; 211 1.2 elad kauth_cred_t a_cred; 212 1.1 tsutsui } */ *a = arg; 213 1.1 tsutsui struct vnode *v = a->a_vp; 214 1.1 tsutsui struct sysvbfs_node *bnode = v->v_data; 215 1.1 tsutsui struct bfs_fileattr attr; 216 1.1 tsutsui 217 1.16 perry DPRINTF("%s:\n", __func__); 218 1.48 pooka 219 1.48 pooka if (v->v_mount->mnt_flag & MNT_RDONLY) 220 1.48 pooka goto out; 221 1.48 pooka 222 1.1 tsutsui uvm_vnp_setsize(v, bnode->size); 223 1.1 tsutsui 224 1.1 tsutsui memset(&attr, 0xff, sizeof attr); /* Set VNOVAL all */ 225 1.1 tsutsui if (bnode->update_atime) 226 1.5 martin attr.atime = time_second; 227 1.1 tsutsui if (bnode->update_ctime) 228 1.5 martin attr.ctime = time_second; 229 1.1 tsutsui if (bnode->update_mtime) 230 1.5 martin attr.mtime = time_second; 231 1.1 tsutsui bfs_inode_set_attr(bnode->bmp->bfs, bnode->inode, &attr); 232 1.1 tsutsui 233 1.15 pooka VOP_FSYNC(a->a_vp, a->a_cred, FSYNC_WAIT, 0, 0); 234 1.1 tsutsui 235 1.48 pooka out: 236 1.1 tsutsui return 0; 237 1.1 tsutsui } 238 1.1 tsutsui 239 1.23 elad static int 240 1.23 elad sysvbfs_check_possible(struct vnode *vp, struct sysvbfs_node *bnode, 241 1.23 elad mode_t mode) 242 1.23 elad { 243 1.23 elad 244 1.23 elad if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) 245 1.23 elad return EROFS; 246 1.23 elad 247 1.23 elad return 0; 248 1.23 elad } 249 1.23 elad 250 1.23 elad static int 251 1.23 elad sysvbfs_check_permitted(struct vnode *vp, struct sysvbfs_node *bnode, 252 1.66 christos accmode_t accmode, kauth_cred_t cred) 253 1.23 elad { 254 1.23 elad struct bfs_fileattr *attr = &bnode->inode->attr; 255 1.23 elad 256 1.66 christos return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, 257 1.66 christos vp->v_type, attr->mode), vp, NULL, genfs_can_access(vp, cred, 258 1.66 christos attr->uid, attr->gid, attr->mode, NULL, accmode)); 259 1.23 elad } 260 1.23 elad 261 1.1 tsutsui int 262 1.1 tsutsui sysvbfs_access(void *arg) 263 1.1 tsutsui { 264 1.1 tsutsui struct vop_access_args /* { 265 1.1 tsutsui struct vnode *a_vp; 266 1.66 christos accmode_t a_accmode; 267 1.2 elad kauth_cred_t a_cred; 268 1.1 tsutsui } */ *ap = arg; 269 1.1 tsutsui struct vnode *vp = ap->a_vp; 270 1.1 tsutsui struct sysvbfs_node *bnode = vp->v_data; 271 1.24 pgoyette int error; 272 1.1 tsutsui 273 1.16 perry DPRINTF("%s:\n", __func__); 274 1.1 tsutsui 275 1.66 christos error = sysvbfs_check_possible(vp, bnode, ap->a_accmode); 276 1.23 elad if (error) 277 1.23 elad return error; 278 1.23 elad 279 1.66 christos error = sysvbfs_check_permitted(vp, bnode, ap->a_accmode, ap->a_cred); 280 1.23 elad 281 1.23 elad return error; 282 1.1 tsutsui } 283 1.1 tsutsui 284 1.1 tsutsui int 285 1.1 tsutsui sysvbfs_getattr(void *v) 286 1.1 tsutsui { 287 1.1 tsutsui struct vop_getattr_args /* { 288 1.1 tsutsui struct vnode *a_vp; 289 1.1 tsutsui struct vattr *a_vap; 290 1.2 elad kauth_cred_t a_cred; 291 1.1 tsutsui } */ *ap = v; 292 1.1 tsutsui struct vnode *vp = ap->a_vp; 293 1.1 tsutsui struct sysvbfs_node *bnode = vp->v_data; 294 1.1 tsutsui struct bfs_inode *inode = bnode->inode; 295 1.1 tsutsui struct bfs_fileattr *attr = &inode->attr; 296 1.1 tsutsui struct sysvbfs_mount *bmp = bnode->bmp; 297 1.1 tsutsui struct vattr *vap = ap->a_vap; 298 1.1 tsutsui 299 1.16 perry DPRINTF("%s:\n", __func__); 300 1.1 tsutsui 301 1.1 tsutsui vap->va_type = vp->v_type; 302 1.1 tsutsui vap->va_mode = attr->mode; 303 1.1 tsutsui vap->va_nlink = attr->nlink; 304 1.1 tsutsui vap->va_uid = attr->uid; 305 1.1 tsutsui vap->va_gid = attr->gid; 306 1.1 tsutsui vap->va_fsid = bmp->devvp->v_rdev; 307 1.1 tsutsui vap->va_fileid = inode->number; 308 1.1 tsutsui vap->va_size = bfs_file_size(inode); 309 1.1 tsutsui vap->va_blocksize = BFS_BSIZE; 310 1.1 tsutsui vap->va_atime.tv_sec = attr->atime; 311 1.1 tsutsui vap->va_mtime.tv_sec = attr->mtime; 312 1.1 tsutsui vap->va_ctime.tv_sec = attr->ctime; 313 1.1 tsutsui vap->va_birthtime.tv_sec = 0; 314 1.1 tsutsui vap->va_gen = 1; 315 1.1 tsutsui vap->va_flags = 0; 316 1.1 tsutsui vap->va_rdev = 0; /* No device file */ 317 1.1 tsutsui vap->va_bytes = vap->va_size; 318 1.1 tsutsui vap->va_filerev = 0; 319 1.1 tsutsui vap->va_vaflags = 0; 320 1.1 tsutsui 321 1.1 tsutsui return 0; 322 1.1 tsutsui } 323 1.1 tsutsui 324 1.1 tsutsui int 325 1.1 tsutsui sysvbfs_setattr(void *arg) 326 1.1 tsutsui { 327 1.1 tsutsui struct vop_setattr_args /* { 328 1.1 tsutsui struct vnode *a_vp; 329 1.1 tsutsui struct vattr *a_vap; 330 1.2 elad kauth_cred_t a_cred; 331 1.1 tsutsui struct proc *p; 332 1.1 tsutsui } */ *ap = arg; 333 1.1 tsutsui struct vnode *vp = ap->a_vp; 334 1.1 tsutsui struct vattr *vap = ap->a_vap; 335 1.1 tsutsui struct sysvbfs_node *bnode = vp->v_data; 336 1.1 tsutsui struct bfs_inode *inode = bnode->inode; 337 1.1 tsutsui struct bfs_fileattr *attr = &inode->attr; 338 1.1 tsutsui struct bfs *bfs = bnode->bmp->bfs; 339 1.40 njoly kauth_cred_t cred = ap->a_cred; 340 1.40 njoly int error; 341 1.1 tsutsui 342 1.16 perry DPRINTF("%s:\n", __func__); 343 1.1 tsutsui if (vp->v_mount->mnt_flag & MNT_RDONLY) 344 1.1 tsutsui return EROFS; 345 1.1 tsutsui 346 1.1 tsutsui if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 347 1.1 tsutsui (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 348 1.1 tsutsui (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 349 1.1 tsutsui ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) 350 1.1 tsutsui return EINVAL; 351 1.1 tsutsui 352 1.43 njoly if (vap->va_flags != VNOVAL) 353 1.43 njoly return EOPNOTSUPP; 354 1.43 njoly 355 1.46 agc if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { 356 1.40 njoly uid_t uid = 357 1.40 njoly (vap->va_uid != (uid_t)VNOVAL) ? vap->va_uid : attr->uid; 358 1.40 njoly gid_t gid = 359 1.40 njoly (vap->va_gid != (gid_t)VNOVAL) ? vap->va_gid : attr->gid; 360 1.40 njoly error = kauth_authorize_vnode(cred, 361 1.40 njoly KAUTH_VNODE_CHANGE_OWNERSHIP, vp, NULL, 362 1.66 christos genfs_can_chown(vp, cred, attr->uid, attr->gid, uid, gid)); 363 1.40 njoly if (error) 364 1.40 njoly return error; 365 1.40 njoly attr->uid = uid; 366 1.40 njoly attr->gid = gid; 367 1.40 njoly } 368 1.40 njoly 369 1.42 christos if (vap->va_size != VNOVAL) 370 1.42 christos switch (vp->v_type) { 371 1.42 christos case VDIR: 372 1.42 christos return EISDIR; 373 1.42 christos case VCHR: 374 1.42 christos case VBLK: 375 1.42 christos case VFIFO: 376 1.42 christos break; 377 1.42 christos case VREG: 378 1.42 christos if (vp->v_mount->mnt_flag & MNT_RDONLY) 379 1.42 christos return EROFS; 380 1.45 tsutsui sysvbfs_file_setsize(vp, vap->va_size); 381 1.42 christos break; 382 1.42 christos default: 383 1.42 christos return EOPNOTSUPP; 384 1.42 christos } 385 1.42 christos 386 1.40 njoly if (vap->va_mode != (mode_t)VNOVAL) { 387 1.40 njoly mode_t mode = vap->va_mode; 388 1.40 njoly error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, 389 1.66 christos vp, NULL, genfs_can_chmod(vp, cred, attr->uid, 390 1.42 christos attr->gid, mode)); 391 1.40 njoly if (error) 392 1.40 njoly return error; 393 1.40 njoly attr->mode = mode; 394 1.40 njoly } 395 1.40 njoly 396 1.41 elad if ((vap->va_atime.tv_sec != VNOVAL) || 397 1.41 elad (vap->va_mtime.tv_sec != VNOVAL) || 398 1.41 elad (vap->va_ctime.tv_sec != VNOVAL)) { 399 1.41 elad error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, 400 1.66 christos NULL, genfs_can_chtimes(vp, cred, attr->uid, 401 1.66 christos vap->va_vaflags)); 402 1.41 elad if (error) 403 1.41 elad return error; 404 1.41 elad 405 1.41 elad if (vap->va_atime.tv_sec != VNOVAL) 406 1.41 elad attr->atime = vap->va_atime.tv_sec; 407 1.41 elad if (vap->va_mtime.tv_sec != VNOVAL) 408 1.41 elad attr->mtime = vap->va_mtime.tv_sec; 409 1.41 elad if (vap->va_ctime.tv_sec != VNOVAL) 410 1.41 elad attr->ctime = vap->va_ctime.tv_sec; 411 1.41 elad } 412 1.1 tsutsui 413 1.1 tsutsui bfs_inode_set_attr(bfs, inode, attr); 414 1.1 tsutsui 415 1.1 tsutsui return 0; 416 1.1 tsutsui } 417 1.1 tsutsui 418 1.1 tsutsui int 419 1.1 tsutsui sysvbfs_read(void *arg) 420 1.1 tsutsui { 421 1.1 tsutsui struct vop_read_args /* { 422 1.1 tsutsui struct vnode *a_vp; 423 1.1 tsutsui struct uio *a_uio; 424 1.1 tsutsui int a_ioflag; 425 1.2 elad kauth_cred_t a_cred; 426 1.1 tsutsui } */ *a = arg; 427 1.1 tsutsui struct vnode *v = a->a_vp; 428 1.1 tsutsui struct uio *uio = a->a_uio; 429 1.1 tsutsui struct sysvbfs_node *bnode = v->v_data; 430 1.1 tsutsui struct bfs_inode *inode = bnode->inode; 431 1.1 tsutsui vsize_t sz, filesz = bfs_file_size(inode); 432 1.57 riastrad int err, uerr; 433 1.1 tsutsui const int advice = IO_ADV_DECODE(a->a_ioflag); 434 1.1 tsutsui 435 1.16 perry DPRINTF("%s: type=%d\n", __func__, v->v_type); 436 1.39 njoly switch (v->v_type) { 437 1.39 njoly case VREG: 438 1.39 njoly break; 439 1.39 njoly case VDIR: 440 1.39 njoly return EISDIR; 441 1.39 njoly default: 442 1.1 tsutsui return EINVAL; 443 1.39 njoly } 444 1.1 tsutsui 445 1.58 riastrad err = 0; 446 1.1 tsutsui while (uio->uio_resid > 0) { 447 1.1 tsutsui if ((sz = MIN(filesz - uio->uio_offset, uio->uio_resid)) == 0) 448 1.1 tsutsui break; 449 1.1 tsutsui 450 1.21 pooka err = ubc_uiomove(&v->v_uobj, uio, sz, advice, 451 1.65 ad UBC_READ | UBC_PARTIALOK | UBC_VNODE_FLAGS(v)); 452 1.1 tsutsui if (err) 453 1.1 tsutsui break; 454 1.16 perry DPRINTF("%s: read %ldbyte\n", __func__, sz); 455 1.1 tsutsui } 456 1.1 tsutsui 457 1.57 riastrad uerr = sysvbfs_update(v, NULL, NULL, UPDATE_WAIT); 458 1.57 riastrad if (err == 0) 459 1.57 riastrad err = uerr; 460 1.57 riastrad 461 1.57 riastrad return err; 462 1.1 tsutsui } 463 1.1 tsutsui 464 1.1 tsutsui int 465 1.1 tsutsui sysvbfs_write(void *arg) 466 1.1 tsutsui { 467 1.1 tsutsui struct vop_write_args /* { 468 1.1 tsutsui struct vnode *a_vp; 469 1.1 tsutsui struct uio *a_uio; 470 1.1 tsutsui int a_ioflag; 471 1.2 elad kauth_cred_t a_cred; 472 1.1 tsutsui } */ *a = arg; 473 1.1 tsutsui struct vnode *v = a->a_vp; 474 1.1 tsutsui struct uio *uio = a->a_uio; 475 1.21 pooka int advice = IO_ADV_DECODE(a->a_ioflag); 476 1.1 tsutsui struct sysvbfs_node *bnode = v->v_data; 477 1.1 tsutsui vsize_t sz; 478 1.1 tsutsui int err = 0; 479 1.1 tsutsui 480 1.1 tsutsui if (a->a_vp->v_type != VREG) 481 1.1 tsutsui return EISDIR; 482 1.1 tsutsui 483 1.1 tsutsui if (a->a_ioflag & IO_APPEND) 484 1.1 tsutsui uio->uio_offset = bnode->size; 485 1.1 tsutsui 486 1.1 tsutsui if (uio->uio_resid == 0) 487 1.1 tsutsui return 0; 488 1.1 tsutsui 489 1.1 tsutsui if (bnode->size < uio->uio_offset + uio->uio_resid) { 490 1.45 tsutsui sysvbfs_file_setsize(v, uio->uio_offset + uio->uio_resid); 491 1.1 tsutsui } 492 1.1 tsutsui 493 1.1 tsutsui while (uio->uio_resid > 0) { 494 1.1 tsutsui sz = uio->uio_resid; 495 1.21 pooka err = ubc_uiomove(&v->v_uobj, uio, sz, advice, 496 1.65 ad UBC_WRITE | UBC_VNODE_FLAGS(v)); 497 1.1 tsutsui if (err) 498 1.1 tsutsui break; 499 1.16 perry DPRINTF("%s: write %ldbyte\n", __func__, sz); 500 1.1 tsutsui } 501 1.42 christos if (err) 502 1.45 tsutsui sysvbfs_file_setsize(v, bnode->size - uio->uio_resid); 503 1.1 tsutsui 504 1.1 tsutsui return err; 505 1.1 tsutsui } 506 1.1 tsutsui 507 1.1 tsutsui int 508 1.1 tsutsui sysvbfs_remove(void *arg) 509 1.1 tsutsui { 510 1.68 thorpej struct vop_remove_v3_args /* { 511 1.1 tsutsui struct vnodeop_desc *a_desc; 512 1.1 tsutsui struct vnode * a_dvp; 513 1.1 tsutsui struct vnode * a_vp; 514 1.1 tsutsui struct componentname * a_cnp; 515 1.68 thorpej nlink_t ctx_vp_new_nlink; 516 1.1 tsutsui } */ *ap = arg; 517 1.1 tsutsui struct vnode *vp = ap->a_vp; 518 1.1 tsutsui struct vnode *dvp = ap->a_dvp; 519 1.1 tsutsui struct sysvbfs_node *bnode = vp->v_data; 520 1.1 tsutsui struct sysvbfs_mount *bmp = bnode->bmp; 521 1.1 tsutsui struct bfs *bfs = bmp->bfs; 522 1.1 tsutsui int err; 523 1.1 tsutsui 524 1.16 perry DPRINTF("%s: delete %s\n", __func__, ap->a_cnp->cn_nameptr); 525 1.1 tsutsui 526 1.62 riastrad if (vp->v_type == VDIR) { 527 1.62 riastrad vrele(vp); 528 1.1 tsutsui return EPERM; 529 1.62 riastrad } 530 1.1 tsutsui 531 1.50 hannken if ((err = bfs_file_delete(bfs, ap->a_cnp->cn_nameptr, true)) != 0) 532 1.16 perry DPRINTF("%s: bfs_file_delete failed.\n", __func__); 533 1.1 tsutsui 534 1.1 tsutsui if (dvp == vp) 535 1.1 tsutsui vrele(vp); 536 1.1 tsutsui else 537 1.1 tsutsui vput(vp); 538 1.1 tsutsui 539 1.30 pooka if (err == 0) { 540 1.30 pooka bnode->removed = 1; 541 1.30 pooka } 542 1.30 pooka 543 1.1 tsutsui return err; 544 1.1 tsutsui } 545 1.1 tsutsui 546 1.1 tsutsui int 547 1.1 tsutsui sysvbfs_rename(void *arg) 548 1.1 tsutsui { 549 1.1 tsutsui struct vop_rename_args /* { 550 1.1 tsutsui struct vnode *a_fdvp; from parent-directory v-node 551 1.1 tsutsui struct vnode *a_fvp; from file v-node 552 1.1 tsutsui struct componentname *a_fcnp; 553 1.1 tsutsui struct vnode *a_tdvp; to parent-directory 554 1.1 tsutsui struct vnode *a_tvp; to file v-node 555 1.1 tsutsui struct componentname *a_tcnp; 556 1.1 tsutsui } */ *ap = arg; 557 1.1 tsutsui struct vnode *fvp = ap->a_fvp; 558 1.28 pooka struct vnode *fdvp = ap->a_fdvp; 559 1.1 tsutsui struct vnode *tvp = ap->a_tvp; 560 1.28 pooka struct vnode *tdvp = ap->a_tdvp; 561 1.1 tsutsui struct sysvbfs_node *bnode = fvp->v_data; 562 1.1 tsutsui struct bfs *bfs = bnode->bmp->bfs; 563 1.1 tsutsui const char *from_name = ap->a_fcnp->cn_nameptr; 564 1.1 tsutsui const char *to_name = ap->a_tcnp->cn_nameptr; 565 1.1 tsutsui int error; 566 1.1 tsutsui 567 1.16 perry DPRINTF("%s: %s->%s\n", __func__, from_name, to_name); 568 1.28 pooka if ((fvp->v_mount != tdvp->v_mount) || 569 1.1 tsutsui (tvp && (fvp->v_mount != tvp->v_mount))) { 570 1.1 tsutsui error = EXDEV; 571 1.1 tsutsui printf("cross-device link\n"); 572 1.1 tsutsui goto out; 573 1.1 tsutsui } 574 1.1 tsutsui 575 1.1 tsutsui KDASSERT(fvp->v_type == VREG); 576 1.11 thorpej KDASSERT(tvp == NULL ? true : tvp->v_type == VREG); 577 1.30 pooka KASSERT(tdvp == fdvp); 578 1.30 pooka 579 1.30 pooka /* 580 1.30 pooka * Make sure the source hasn't been removed between lookup 581 1.30 pooka * and target directory lock. 582 1.30 pooka */ 583 1.30 pooka if (bnode->removed) { 584 1.30 pooka error = ENOENT; 585 1.30 pooka goto out; 586 1.30 pooka } 587 1.1 tsutsui 588 1.55 hannken /* 589 1.55 hannken * Remove the target if it exists. 590 1.55 hannken */ 591 1.55 hannken if (tvp != NULL) { 592 1.55 hannken error = bfs_file_delete(bfs, to_name, true); 593 1.55 hannken if (error) 594 1.55 hannken goto out; 595 1.55 hannken } 596 1.1 tsutsui error = bfs_file_rename(bfs, from_name, to_name); 597 1.1 tsutsui out: 598 1.28 pooka /* tdvp == tvp probably can't happen with this fs, but safety first */ 599 1.28 pooka if (tdvp == tvp) 600 1.28 pooka vrele(tdvp); 601 1.28 pooka else 602 1.28 pooka vput(tdvp); 603 1.55 hannken if (tvp) 604 1.55 hannken vput(tvp); 605 1.28 pooka 606 1.28 pooka vrele(fdvp); 607 1.28 pooka vrele(fvp); 608 1.1 tsutsui 609 1.1 tsutsui return 0; 610 1.1 tsutsui } 611 1.1 tsutsui 612 1.1 tsutsui int 613 1.1 tsutsui sysvbfs_readdir(void *v) 614 1.1 tsutsui { 615 1.1 tsutsui struct vop_readdir_args /* { 616 1.1 tsutsui struct vnode *a_vp; 617 1.1 tsutsui struct uio *a_uio; 618 1.2 elad kauth_cred_t a_cred; 619 1.1 tsutsui int *a_eofflag; 620 1.1 tsutsui off_t **a_cookies; 621 1.1 tsutsui int *a_ncookies; 622 1.1 tsutsui } */ *ap = v; 623 1.1 tsutsui struct uio *uio = ap->a_uio; 624 1.1 tsutsui struct vnode *vp = ap->a_vp; 625 1.1 tsutsui struct sysvbfs_node *bnode = vp->v_data; 626 1.1 tsutsui struct bfs *bfs = bnode->bmp->bfs; 627 1.14 rumble struct dirent *dp; 628 1.1 tsutsui struct bfs_dirent *file; 629 1.1 tsutsui int i, n, error; 630 1.1 tsutsui 631 1.33 njoly DPRINTF("%s: offset=%" PRId64 " residue=%zu\n", __func__, 632 1.1 tsutsui uio->uio_offset, uio->uio_resid); 633 1.1 tsutsui 634 1.1 tsutsui KDASSERT(vp->v_type == VDIR); 635 1.69 mlelstv 636 1.69 mlelstv if (uio->uio_offset < 0) 637 1.69 mlelstv return EINVAL; 638 1.1 tsutsui 639 1.14 rumble dp = malloc(sizeof(struct dirent), M_BFS, M_WAITOK | M_ZERO); 640 1.14 rumble 641 1.1 tsutsui i = uio->uio_offset / sizeof(struct dirent); 642 1.1 tsutsui n = uio->uio_resid / sizeof(struct dirent); 643 1.1 tsutsui if ((i + n) > bfs->n_dirent) 644 1.1 tsutsui n = bfs->n_dirent - i; 645 1.1 tsutsui 646 1.59 pooka DPRINTF("%s 1: %d %d %d\n", __func__, i, n, bfs->n_dirent); 647 1.59 pooka for (file = &bfs->dirent[i]; n > 0; file++, i++) { 648 1.1 tsutsui if (i == bfs->max_dirent) { 649 1.1 tsutsui DPRINTF("%s: file system inconsistent.\n", 650 1.16 perry __func__); 651 1.1 tsutsui break; 652 1.1 tsutsui } 653 1.59 pooka if (file->inode == 0) 654 1.59 pooka continue; 655 1.59 pooka 656 1.59 pooka /* ok, we have a live one here */ 657 1.59 pooka n--; 658 1.14 rumble memset(dp, 0, sizeof(struct dirent)); 659 1.14 rumble dp->d_fileno = file->inode; 660 1.14 rumble dp->d_type = file->inode == BFS_ROOT_INODE ? DT_DIR : DT_REG; 661 1.14 rumble dp->d_namlen = strlen(file->name); 662 1.14 rumble strncpy(dp->d_name, file->name, BFS_FILENAME_MAXLEN); 663 1.14 rumble dp->d_reclen = sizeof(struct dirent); 664 1.14 rumble if ((error = uiomove(dp, dp->d_reclen, uio)) != 0) { 665 1.16 perry DPRINTF("%s: uiomove failed.\n", __func__); 666 1.14 rumble free(dp, M_BFS); 667 1.1 tsutsui return error; 668 1.1 tsutsui } 669 1.1 tsutsui } 670 1.59 pooka DPRINTF("%s 2: %d %d %d\n", __func__, i, n, bfs->n_dirent); 671 1.14 rumble *ap->a_eofflag = (i == bfs->n_dirent); 672 1.1 tsutsui 673 1.14 rumble free(dp, M_BFS); 674 1.1 tsutsui return 0; 675 1.1 tsutsui } 676 1.1 tsutsui 677 1.1 tsutsui int 678 1.1 tsutsui sysvbfs_inactive(void *arg) 679 1.1 tsutsui { 680 1.61 riastrad struct vop_inactive_v2_args /* { 681 1.1 tsutsui struct vnode *a_vp; 682 1.17 ad bool *a_recycle; 683 1.1 tsutsui } */ *a = arg; 684 1.1 tsutsui struct vnode *v = a->a_vp; 685 1.30 pooka struct sysvbfs_node *bnode = v->v_data; 686 1.1 tsutsui 687 1.16 perry DPRINTF("%s:\n", __func__); 688 1.30 pooka if (bnode->removed) 689 1.30 pooka *a->a_recycle = true; 690 1.30 pooka else 691 1.30 pooka *a->a_recycle = false; 692 1.1 tsutsui 693 1.1 tsutsui return 0; 694 1.1 tsutsui } 695 1.1 tsutsui 696 1.1 tsutsui int 697 1.1 tsutsui sysvbfs_reclaim(void *v) 698 1.1 tsutsui { 699 1.1 tsutsui extern struct pool sysvbfs_node_pool; 700 1.63 riastrad struct vop_reclaim_v2_args /* { 701 1.1 tsutsui struct vnode *a_vp; 702 1.1 tsutsui } */ *ap = v; 703 1.1 tsutsui struct vnode *vp = ap->a_vp; 704 1.1 tsutsui struct sysvbfs_node *bnode = vp->v_data; 705 1.50 hannken struct bfs *bfs = bnode->bmp->bfs; 706 1.1 tsutsui 707 1.63 riastrad VOP_UNLOCK(vp); 708 1.63 riastrad 709 1.16 perry DPRINTF("%s:\n", __func__); 710 1.56 hannken 711 1.50 hannken if (bnode->removed) { 712 1.50 hannken if (bfs_inode_delete(bfs, bnode->inode->number) != 0) 713 1.50 hannken DPRINTF("%s: delete inode failed\n", __func__); 714 1.50 hannken } 715 1.9 ad genfs_node_destroy(vp); 716 1.1 tsutsui pool_put(&sysvbfs_node_pool, bnode); 717 1.1 tsutsui vp->v_data = NULL; 718 1.1 tsutsui 719 1.1 tsutsui return 0; 720 1.1 tsutsui } 721 1.1 tsutsui 722 1.1 tsutsui int 723 1.1 tsutsui sysvbfs_bmap(void *arg) 724 1.1 tsutsui { 725 1.1 tsutsui struct vop_bmap_args /* { 726 1.1 tsutsui struct vnode *a_vp; 727 1.1 tsutsui daddr_t a_bn; 728 1.1 tsutsui struct vnode **a_vpp; 729 1.1 tsutsui daddr_t *a_bnp; 730 1.1 tsutsui int *a_runp; 731 1.1 tsutsui } */ *a = arg; 732 1.1 tsutsui struct vnode *v = a->a_vp; 733 1.1 tsutsui struct sysvbfs_node *bnode = v->v_data; 734 1.1 tsutsui struct sysvbfs_mount *bmp = bnode->bmp; 735 1.1 tsutsui struct bfs_inode *inode = bnode->inode; 736 1.1 tsutsui daddr_t blk; 737 1.1 tsutsui 738 1.16 perry DPRINTF("%s:\n", __func__); 739 1.7 wiz /* BFS algorithm is contiguous allocation */ 740 1.1 tsutsui blk = inode->start_sector + a->a_bn; 741 1.1 tsutsui 742 1.1 tsutsui if (blk * BFS_BSIZE > bmp->bfs->data_end) 743 1.1 tsutsui return ENOSPC; 744 1.1 tsutsui 745 1.1 tsutsui *a->a_vpp = bmp->devvp; 746 1.1 tsutsui *a->a_runp = 0; 747 1.33 njoly DPRINTF("%s: %d + %" PRId64 "\n", __func__, inode->start_sector, 748 1.33 njoly a->a_bn); 749 1.1 tsutsui 750 1.1 tsutsui *a->a_bnp = blk; 751 1.1 tsutsui 752 1.1 tsutsui 753 1.1 tsutsui return 0; 754 1.1 tsutsui } 755 1.1 tsutsui 756 1.1 tsutsui int 757 1.1 tsutsui sysvbfs_strategy(void *arg) 758 1.1 tsutsui { 759 1.1 tsutsui struct vop_strategy_args /* { 760 1.1 tsutsui struct vnode *a_vp; 761 1.1 tsutsui struct buf *a_bp; 762 1.1 tsutsui } */ *a = arg; 763 1.1 tsutsui struct buf *b = a->a_bp; 764 1.1 tsutsui struct vnode *v = a->a_vp; 765 1.1 tsutsui struct sysvbfs_node *bnode = v->v_data; 766 1.1 tsutsui struct sysvbfs_mount *bmp = bnode->bmp; 767 1.1 tsutsui int error; 768 1.1 tsutsui 769 1.16 perry DPRINTF("%s:\n", __func__); 770 1.1 tsutsui KDASSERT(v->v_type == VREG); 771 1.1 tsutsui if (b->b_blkno == b->b_lblkno) { 772 1.1 tsutsui error = VOP_BMAP(v, b->b_lblkno, NULL, &b->b_blkno, NULL); 773 1.1 tsutsui if (error) { 774 1.1 tsutsui b->b_error = error; 775 1.1 tsutsui biodone(b); 776 1.1 tsutsui return error; 777 1.1 tsutsui } 778 1.1 tsutsui if ((long)b->b_blkno == -1) 779 1.1 tsutsui clrbuf(b); 780 1.1 tsutsui } 781 1.1 tsutsui if ((long)b->b_blkno == -1) { 782 1.1 tsutsui biodone(b); 783 1.1 tsutsui return 0; 784 1.1 tsutsui } 785 1.1 tsutsui 786 1.1 tsutsui return VOP_STRATEGY(bmp->devvp, b); 787 1.1 tsutsui } 788 1.1 tsutsui 789 1.1 tsutsui int 790 1.1 tsutsui sysvbfs_print(void *v) 791 1.1 tsutsui { 792 1.1 tsutsui struct vop_print_args /* { 793 1.1 tsutsui struct vnode *a_vp; 794 1.1 tsutsui } */ *ap = v; 795 1.1 tsutsui struct sysvbfs_node *bnode = ap->a_vp->v_data; 796 1.1 tsutsui 797 1.16 perry DPRINTF("%s:\n", __func__); 798 1.1 tsutsui bfs_dump(bnode->bmp->bfs); 799 1.1 tsutsui 800 1.1 tsutsui return 0; 801 1.1 tsutsui } 802 1.1 tsutsui 803 1.1 tsutsui int 804 1.1 tsutsui sysvbfs_advlock(void *v) 805 1.1 tsutsui { 806 1.1 tsutsui struct vop_advlock_args /* { 807 1.1 tsutsui struct vnode *a_vp; 808 1.1 tsutsui void *a_id; 809 1.1 tsutsui int a_op; 810 1.1 tsutsui struct flock *a_fl; 811 1.1 tsutsui int a_flags; 812 1.1 tsutsui } */ *ap = v; 813 1.1 tsutsui struct sysvbfs_node *bnode = ap->a_vp->v_data; 814 1.1 tsutsui 815 1.16 perry DPRINTF("%s: op=%d\n", __func__, ap->a_op); 816 1.1 tsutsui 817 1.1 tsutsui return lf_advlock(ap, &bnode->lockf, bfs_file_size(bnode->inode)); 818 1.1 tsutsui } 819 1.1 tsutsui 820 1.1 tsutsui int 821 1.1 tsutsui sysvbfs_pathconf(void *v) 822 1.1 tsutsui { 823 1.1 tsutsui struct vop_pathconf_args /* { 824 1.1 tsutsui struct vnode *a_vp; 825 1.1 tsutsui int a_name; 826 1.1 tsutsui register_t *a_retval; 827 1.1 tsutsui } */ *ap = v; 828 1.1 tsutsui 829 1.16 perry DPRINTF("%s:\n", __func__); 830 1.1 tsutsui 831 1.1 tsutsui switch (ap->a_name) { 832 1.1 tsutsui case _PC_LINK_MAX: 833 1.1 tsutsui *ap->a_retval = 1; 834 1.67 christos return 0; 835 1.1 tsutsui case _PC_NAME_MAX: 836 1.1 tsutsui *ap->a_retval = BFS_FILENAME_MAXLEN; 837 1.67 christos return 0; 838 1.1 tsutsui case _PC_PATH_MAX: 839 1.1 tsutsui *ap->a_retval = BFS_FILENAME_MAXLEN; 840 1.67 christos return 0; 841 1.1 tsutsui case _PC_CHOWN_RESTRICTED: 842 1.1 tsutsui *ap->a_retval = 1; 843 1.67 christos return 0; 844 1.1 tsutsui case _PC_NO_TRUNC: 845 1.1 tsutsui *ap->a_retval = 0; 846 1.67 christos return 0; 847 1.1 tsutsui case _PC_SYNC_IO: 848 1.1 tsutsui *ap->a_retval = 1; 849 1.67 christos return 0; 850 1.1 tsutsui case _PC_FILESIZEBITS: 851 1.1 tsutsui *ap->a_retval = 32; 852 1.67 christos return 0; 853 1.1 tsutsui default: 854 1.67 christos return genfs_pathconf(ap); 855 1.1 tsutsui } 856 1.1 tsutsui } 857 1.1 tsutsui 858 1.1 tsutsui int 859 1.1 tsutsui sysvbfs_fsync(void *v) 860 1.1 tsutsui { 861 1.1 tsutsui struct vop_fsync_args /* { 862 1.1 tsutsui struct vnode *a_vp; 863 1.2 elad kauth_cred_t a_cred; 864 1.1 tsutsui int a_flags; 865 1.1 tsutsui off_t offlo; 866 1.1 tsutsui off_t offhi; 867 1.1 tsutsui } */ *ap = v; 868 1.1 tsutsui struct vnode *vp = ap->a_vp; 869 1.1 tsutsui int error, wait; 870 1.1 tsutsui 871 1.1 tsutsui if (ap->a_flags & FSYNC_CACHE) { 872 1.1 tsutsui return EOPNOTSUPP; 873 1.1 tsutsui } 874 1.1 tsutsui 875 1.1 tsutsui wait = (ap->a_flags & FSYNC_WAIT) != 0; 876 1.44 chs error = vflushbuf(vp, ap->a_flags); 877 1.37 hannken if (error == 0 && (ap->a_flags & FSYNC_DATAONLY) == 0) 878 1.1 tsutsui error = sysvbfs_update(vp, NULL, NULL, wait ? UPDATE_WAIT : 0); 879 1.1 tsutsui 880 1.1 tsutsui return error; 881 1.1 tsutsui } 882 1.1 tsutsui 883 1.1 tsutsui int 884 1.1 tsutsui sysvbfs_update(struct vnode *vp, const struct timespec *acc, 885 1.1 tsutsui const struct timespec *mod, int flags) 886 1.1 tsutsui { 887 1.1 tsutsui struct sysvbfs_node *bnode = vp->v_data; 888 1.1 tsutsui struct bfs_fileattr attr; 889 1.1 tsutsui 890 1.48 pooka if (vp->v_mount->mnt_flag & MNT_RDONLY) 891 1.48 pooka return 0; 892 1.48 pooka 893 1.16 perry DPRINTF("%s:\n", __func__); 894 1.1 tsutsui memset(&attr, 0xff, sizeof attr); /* Set VNOVAL all */ 895 1.1 tsutsui if (bnode->update_atime) { 896 1.5 martin attr.atime = acc ? acc->tv_sec : time_second; 897 1.11 thorpej bnode->update_atime = false; 898 1.1 tsutsui } 899 1.1 tsutsui if (bnode->update_ctime) { 900 1.5 martin attr.ctime = time_second; 901 1.11 thorpej bnode->update_ctime = false; 902 1.1 tsutsui } 903 1.1 tsutsui if (bnode->update_mtime) { 904 1.5 martin attr.mtime = mod ? mod->tv_sec : time_second; 905 1.11 thorpej bnode->update_mtime = false; 906 1.1 tsutsui } 907 1.1 tsutsui bfs_inode_set_attr(bnode->bmp->bfs, bnode->inode, &attr); 908 1.1 tsutsui 909 1.1 tsutsui return 0; 910 1.1 tsutsui } 911 1.45 tsutsui 912 1.45 tsutsui static void 913 1.45 tsutsui sysvbfs_file_setsize(struct vnode *v, size_t size) 914 1.45 tsutsui { 915 1.45 tsutsui struct sysvbfs_node *bnode = v->v_data; 916 1.45 tsutsui struct bfs_inode *inode = bnode->inode; 917 1.45 tsutsui 918 1.45 tsutsui bnode->size = size; 919 1.45 tsutsui uvm_vnp_setsize(v, bnode->size); 920 1.45 tsutsui inode->end_sector = bnode->data_block + 921 1.45 tsutsui (ROUND_SECTOR(bnode->size) >> DEV_BSHIFT) - 1; 922 1.45 tsutsui inode->eof_offset_byte = bnode->data_block * DEV_BSIZE + 923 1.45 tsutsui bnode->size - 1; 924 1.45 tsutsui bnode->update_mtime = true; 925 1.45 tsutsui } 926