1 1.10 christos /* $NetBSD: dtfs_vnops.c,v 1.10 2013/10/19 17:45:00 christos Exp $ */ 2 1.1 pooka 3 1.1 pooka /* 4 1.1 pooka * Copyright (c) 2006 Antti Kantee. All Rights Reserved. 5 1.1 pooka * 6 1.1 pooka * Redistribution and use in source and binary forms, with or without 7 1.1 pooka * modification, are permitted provided that the following conditions 8 1.1 pooka * are met: 9 1.1 pooka * 1. Redistributions of source code must retain the above copyright 10 1.1 pooka * notice, this list of conditions and the following disclaimer. 11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 pooka * notice, this list of conditions and the following disclaimer in the 13 1.1 pooka * documentation and/or other materials provided with the distribution. 14 1.1 pooka * 15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 pooka * SUCH DAMAGE. 26 1.1 pooka */ 27 1.1 pooka 28 1.1 pooka #include <sys/types.h> 29 1.1 pooka #include <sys/poll.h> 30 1.1 pooka 31 1.1 pooka #include <assert.h> 32 1.1 pooka #include <errno.h> 33 1.1 pooka #include <puffs.h> 34 1.1 pooka #include <stdio.h> 35 1.1 pooka #include <stdlib.h> 36 1.1 pooka #include <string.h> 37 1.1 pooka #include <unistd.h> 38 1.1 pooka #include <util.h> 39 1.1 pooka 40 1.1 pooka #include "dtfs.h" 41 1.1 pooka 42 1.1 pooka int 43 1.1 pooka dtfs_node_lookup(struct puffs_usermount *pu, void *opc, 44 1.1 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn) 45 1.1 pooka { 46 1.1 pooka struct puffs_node *pn_dir = opc; 47 1.1 pooka struct dtfs_file *df = DTFS_CTOF(opc); 48 1.1 pooka struct dtfs_dirent *dfd; 49 1.1 pooka extern int straightflush; 50 1.1 pooka int rv; 51 1.1 pooka 52 1.1 pooka /* parent dir? */ 53 1.1 pooka if (PCNISDOTDOT(pcn)) { 54 1.8 pooka if (df->df_dotdot == NULL) 55 1.8 pooka return ENOENT; 56 1.8 pooka 57 1.1 pooka assert(df->df_dotdot->pn_va.va_type == VDIR); 58 1.1 pooka puffs_newinfo_setcookie(pni, df->df_dotdot); 59 1.1 pooka puffs_newinfo_setvtype(pni, df->df_dotdot->pn_va.va_type); 60 1.1 pooka 61 1.1 pooka return 0; 62 1.1 pooka } 63 1.1 pooka 64 1.1 pooka dfd = dtfs_dirgetbyname(df, pcn->pcn_name, pcn->pcn_namelen); 65 1.1 pooka if (dfd) { 66 1.9 njoly if ((pcn->pcn_flags & NAMEI_ISLASTCN) && 67 1.9 njoly (pcn->pcn_nameiop == NAMEI_DELETE)) { 68 1.9 njoly rv = puffs_access(VDIR, pn_dir->pn_va.va_mode, 69 1.9 njoly pn_dir->pn_va.va_uid, pn_dir->pn_va.va_gid, 70 1.9 njoly PUFFS_VWRITE, pcn->pcn_cred); 71 1.9 njoly if (rv) 72 1.9 njoly return rv; 73 1.9 njoly } 74 1.1 pooka puffs_newinfo_setcookie(pni, dfd->dfd_node); 75 1.1 pooka puffs_newinfo_setvtype(pni, dfd->dfd_node->pn_va.va_type); 76 1.1 pooka puffs_newinfo_setsize(pni, dfd->dfd_node->pn_va.va_size); 77 1.1 pooka puffs_newinfo_setrdev(pni, dfd->dfd_node->pn_va.va_rdev); 78 1.1 pooka 79 1.1 pooka if (straightflush) 80 1.1 pooka puffs_flush_pagecache_node(pu, dfd->dfd_node); 81 1.1 pooka 82 1.1 pooka return 0; 83 1.1 pooka } 84 1.1 pooka 85 1.1 pooka if ((pcn->pcn_flags & NAMEI_ISLASTCN) 86 1.1 pooka && (pcn->pcn_nameiop == NAMEI_CREATE || 87 1.9 njoly pcn->pcn_nameiop == NAMEI_RENAME)) { 88 1.1 pooka rv = puffs_access(VDIR, pn_dir->pn_va.va_mode, 89 1.1 pooka pn_dir->pn_va.va_uid, pn_dir->pn_va.va_gid, 90 1.1 pooka PUFFS_VWRITE, pcn->pcn_cred); 91 1.1 pooka if (rv) 92 1.1 pooka return rv; 93 1.1 pooka } 94 1.1 pooka 95 1.1 pooka return ENOENT; 96 1.1 pooka } 97 1.1 pooka 98 1.1 pooka int 99 1.1 pooka dtfs_node_access(struct puffs_usermount *pu, void *opc, int acc_mode, 100 1.1 pooka const struct puffs_cred *pcr) 101 1.1 pooka { 102 1.1 pooka struct puffs_node *pn = opc; 103 1.1 pooka 104 1.1 pooka return puffs_access(pn->pn_va.va_type, pn->pn_va.va_mode, 105 1.1 pooka pn->pn_va.va_uid, pn->pn_va.va_gid, acc_mode, pcr); 106 1.1 pooka } 107 1.1 pooka 108 1.1 pooka int 109 1.1 pooka dtfs_node_setattr(struct puffs_usermount *pu, void *opc, 110 1.1 pooka const struct vattr *va, const struct puffs_cred *pcr) 111 1.1 pooka { 112 1.1 pooka struct puffs_node *pn = opc; 113 1.1 pooka int rv; 114 1.1 pooka 115 1.1 pooka /* check permissions */ 116 1.1 pooka if (va->va_flags != PUFFS_VNOVAL) 117 1.1 pooka return EOPNOTSUPP; 118 1.1 pooka 119 1.1 pooka if (va->va_uid != PUFFS_VNOVAL || va->va_gid != PUFFS_VNOVAL) { 120 1.1 pooka rv = puffs_access_chown(pn->pn_va.va_uid, pn->pn_va.va_gid, 121 1.1 pooka va->va_uid, va->va_gid, pcr); 122 1.1 pooka if (rv) 123 1.1 pooka return rv; 124 1.1 pooka } 125 1.1 pooka 126 1.1 pooka if (va->va_mode != PUFFS_VNOVAL) { 127 1.1 pooka rv = puffs_access_chmod(pn->pn_va.va_uid, pn->pn_va.va_gid, 128 1.1 pooka pn->pn_va.va_type, va->va_mode, pcr); 129 1.1 pooka if (rv) 130 1.1 pooka return rv; 131 1.1 pooka } 132 1.1 pooka 133 1.1 pooka if ((va->va_atime.tv_sec != PUFFS_VNOVAL 134 1.1 pooka && va->va_atime.tv_nsec != PUFFS_VNOVAL) 135 1.1 pooka || (va->va_mtime.tv_sec != PUFFS_VNOVAL 136 1.1 pooka && va->va_mtime.tv_nsec != PUFFS_VNOVAL)) { 137 1.1 pooka rv = puffs_access_times(pn->pn_va.va_uid, pn->pn_va.va_gid, 138 1.1 pooka pn->pn_va.va_mode, va->va_vaflags & VA_UTIMES_NULL, pcr); 139 1.1 pooka if (rv) 140 1.1 pooka return rv; 141 1.1 pooka } 142 1.1 pooka 143 1.1 pooka if (va->va_size != PUFFS_VNOVAL) { 144 1.1 pooka switch (pn->pn_va.va_type) { 145 1.1 pooka case VREG: 146 1.1 pooka dtfs_setsize(pn, va->va_size); 147 1.1 pooka pn->pn_va.va_bytes = va->va_size; 148 1.1 pooka break; 149 1.1 pooka case VBLK: 150 1.1 pooka case VCHR: 151 1.1 pooka case VFIFO: 152 1.1 pooka break; 153 1.1 pooka case VDIR: 154 1.1 pooka return EISDIR; 155 1.1 pooka default: 156 1.1 pooka return EOPNOTSUPP; 157 1.1 pooka } 158 1.1 pooka } 159 1.1 pooka 160 1.1 pooka puffs_setvattr(&pn->pn_va, va); 161 1.1 pooka 162 1.1 pooka return 0; 163 1.1 pooka } 164 1.1 pooka 165 1.1 pooka /* create a new node in the parent directory specified by opc */ 166 1.1 pooka int 167 1.1 pooka dtfs_node_create(struct puffs_usermount *pu, void *opc, 168 1.1 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn, 169 1.1 pooka const struct vattr *va) 170 1.1 pooka { 171 1.1 pooka struct puffs_node *pn_parent = opc; 172 1.1 pooka struct puffs_node *pn_new; 173 1.1 pooka 174 1.1 pooka if (!(va->va_type == VREG || va->va_type == VSOCK)) 175 1.1 pooka return ENODEV; 176 1.1 pooka 177 1.1 pooka pn_new = dtfs_genfile(pn_parent, pcn, va->va_type); 178 1.1 pooka puffs_setvattr(&pn_new->pn_va, va); 179 1.1 pooka 180 1.1 pooka puffs_newinfo_setcookie(pni, pn_new); 181 1.1 pooka 182 1.1 pooka return 0; 183 1.1 pooka } 184 1.1 pooka 185 1.1 pooka int 186 1.1 pooka dtfs_node_remove(struct puffs_usermount *pu, void *opc, void *targ, 187 1.1 pooka const struct puffs_cn *pcn) 188 1.1 pooka { 189 1.1 pooka struct puffs_node *pn_parent = opc; 190 1.1 pooka struct puffs_node *pn = targ; 191 1.1 pooka 192 1.1 pooka if (pn->pn_va.va_type == VDIR) 193 1.1 pooka return EPERM; 194 1.1 pooka 195 1.1 pooka dtfs_nukenode(targ, pn_parent, pcn->pcn_name, pcn->pcn_namelen); 196 1.1 pooka 197 1.1 pooka if (pn->pn_va.va_nlink == 0) 198 1.1 pooka puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); 199 1.1 pooka 200 1.1 pooka return 0; 201 1.1 pooka } 202 1.1 pooka 203 1.1 pooka int 204 1.1 pooka dtfs_node_mkdir(struct puffs_usermount *pu, void *opc, 205 1.1 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn, 206 1.1 pooka const struct vattr *va) 207 1.1 pooka { 208 1.1 pooka struct puffs_node *pn_parent = opc; 209 1.1 pooka struct puffs_node *pn_new; 210 1.1 pooka 211 1.1 pooka pn_new = dtfs_genfile(pn_parent, pcn, VDIR); 212 1.1 pooka puffs_setvattr(&pn_new->pn_va, va); 213 1.1 pooka 214 1.1 pooka puffs_newinfo_setcookie(pni, pn_new); 215 1.1 pooka 216 1.1 pooka return 0; 217 1.1 pooka } 218 1.1 pooka 219 1.1 pooka int 220 1.1 pooka dtfs_node_rmdir(struct puffs_usermount *pu, void *opc, void *targ, 221 1.1 pooka const struct puffs_cn *pcn) 222 1.1 pooka { 223 1.1 pooka struct puffs_node *pn_parent = opc; 224 1.1 pooka struct dtfs_file *df = DTFS_CTOF(targ); 225 1.1 pooka 226 1.1 pooka if (!LIST_EMPTY(&df->df_dirents)) 227 1.1 pooka return ENOTEMPTY; 228 1.1 pooka 229 1.1 pooka dtfs_nukenode(targ, pn_parent, pcn->pcn_name, pcn->pcn_namelen); 230 1.1 pooka puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); 231 1.1 pooka 232 1.1 pooka return 0; 233 1.1 pooka } 234 1.1 pooka 235 1.1 pooka int 236 1.1 pooka dtfs_node_readdir(struct puffs_usermount *pu, void *opc, 237 1.1 pooka struct dirent *dent, off_t *readoff, size_t *reslen, 238 1.1 pooka const struct puffs_cred *pcr, 239 1.1 pooka int *eofflag, off_t *cookies, size_t *ncookies) 240 1.1 pooka { 241 1.1 pooka struct puffs_node *pn = opc; 242 1.1 pooka struct puffs_node *pn_nth; 243 1.1 pooka struct dtfs_dirent *dfd_nth; 244 1.1 pooka 245 1.1 pooka if (pn->pn_va.va_type != VDIR) 246 1.1 pooka return ENOTDIR; 247 1.1 pooka 248 1.1 pooka dtfs_updatetimes(pn, 1, 0, 0); 249 1.1 pooka 250 1.1 pooka *ncookies = 0; 251 1.1 pooka again: 252 1.1 pooka if (*readoff == DENT_DOT || *readoff == DENT_DOTDOT) { 253 1.1 pooka puffs_gendotdent(&dent, pn->pn_va.va_fileid, *readoff, reslen); 254 1.1 pooka (*readoff)++; 255 1.1 pooka PUFFS_STORE_DCOOKIE(cookies, ncookies, *readoff); 256 1.1 pooka goto again; 257 1.1 pooka } 258 1.1 pooka 259 1.1 pooka for (;;) { 260 1.1 pooka dfd_nth = dtfs_dirgetnth(pn->pn_data, DENT_ADJ(*readoff)); 261 1.1 pooka if (!dfd_nth) { 262 1.1 pooka *eofflag = 1; 263 1.1 pooka break; 264 1.1 pooka } 265 1.1 pooka pn_nth = dfd_nth->dfd_node; 266 1.1 pooka 267 1.1 pooka if (!puffs_nextdent(&dent, dfd_nth->dfd_name, 268 1.1 pooka pn_nth->pn_va.va_fileid, 269 1.1 pooka puffs_vtype2dt(pn_nth->pn_va.va_type), 270 1.1 pooka reslen)) 271 1.1 pooka break; 272 1.1 pooka 273 1.1 pooka (*readoff)++; 274 1.1 pooka PUFFS_STORE_DCOOKIE(cookies, ncookies, *readoff); 275 1.1 pooka } 276 1.1 pooka 277 1.1 pooka return 0; 278 1.1 pooka } 279 1.1 pooka 280 1.1 pooka int 281 1.1 pooka dtfs_node_poll(struct puffs_usermount *pu, void *opc, int *events) 282 1.1 pooka { 283 1.1 pooka struct dtfs_mount *dtm = puffs_getspecific(pu); 284 1.1 pooka struct dtfs_poll dp; 285 1.1 pooka struct itimerval it; 286 1.1 pooka 287 1.1 pooka memset(&it, 0, sizeof(struct itimerval)); 288 1.1 pooka it.it_value.tv_sec = 4; 289 1.1 pooka if (setitimer(ITIMER_REAL, &it, NULL) == -1) 290 1.1 pooka return errno; 291 1.1 pooka 292 1.1 pooka dp.dp_pcc = puffs_cc_getcc(pu); 293 1.1 pooka LIST_INSERT_HEAD(&dtm->dtm_pollent, &dp, dp_entries); 294 1.1 pooka puffs_cc_yield(dp.dp_pcc); 295 1.1 pooka 296 1.1 pooka *events = *events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM); 297 1.1 pooka return 0; 298 1.1 pooka } 299 1.1 pooka 300 1.1 pooka int 301 1.1 pooka dtfs_node_mmap(struct puffs_usermount *pu, void *opc, vm_prot_t prot, 302 1.1 pooka const struct puffs_cred *pcr) 303 1.1 pooka { 304 1.1 pooka struct dtfs_mount *dtm = puffs_getspecific(pu); 305 1.1 pooka 306 1.1 pooka if ((dtm->dtm_allowprot & prot) != prot) 307 1.1 pooka return EACCES; 308 1.1 pooka 309 1.1 pooka return 0; 310 1.1 pooka } 311 1.1 pooka 312 1.1 pooka int 313 1.1 pooka dtfs_node_rename(struct puffs_usermount *pu, void *opc, void *src, 314 1.1 pooka const struct puffs_cn *pcn_src, void *targ_dir, void *targ, 315 1.1 pooka const struct puffs_cn *pcn_targ) 316 1.1 pooka { 317 1.1 pooka struct dtfs_dirent *dfd_src; 318 1.3 pooka struct dtfs_file *df_targ; 319 1.1 pooka struct puffs_node *pn_sdir = opc; 320 1.2 pooka struct puffs_node *pn_sfile = src; 321 1.1 pooka struct puffs_node *pn_tdir = targ_dir; 322 1.1 pooka struct puffs_node *pn_tfile = targ; 323 1.1 pooka 324 1.2 pooka /* check that we don't do the old amigados trick */ 325 1.2 pooka if (pn_sfile->pn_va.va_type == VDIR) { 326 1.2 pooka if (dtfs_isunder(pn_tdir, pn_sfile)) 327 1.2 pooka return EINVAL; 328 1.5 pooka 329 1.5 pooka if ((pcn_src->pcn_namelen == 1 && pcn_src->pcn_name[0]=='.') || 330 1.5 pooka opc == src || 331 1.5 pooka PCNISDOTDOT(pcn_src) || 332 1.5 pooka PCNISDOTDOT(pcn_targ)) { 333 1.5 pooka return EINVAL; 334 1.5 pooka } 335 1.2 pooka } 336 1.2 pooka 337 1.1 pooka dfd_src = dtfs_dirgetbyname(DTFS_PTOF(pn_sdir), 338 1.1 pooka pcn_src->pcn_name, pcn_src->pcn_namelen); 339 1.1 pooka 340 1.6 pooka /* does it still exist, or did someone race us here? */ 341 1.6 pooka if (dfd_src == NULL) { 342 1.6 pooka return ENOENT; 343 1.6 pooka } 344 1.6 pooka 345 1.1 pooka /* if there's a target file, nuke it for atomic replacement */ 346 1.1 pooka if (pn_tfile) { 347 1.1 pooka if (pn_tfile->pn_va.va_type == VDIR) { 348 1.3 pooka df_targ = DTFS_CTOF(pn_tfile); 349 1.3 pooka if (!LIST_EMPTY(&df_targ->df_dirents)) 350 1.3 pooka return ENOTEMPTY; 351 1.1 pooka } 352 1.4 pooka dtfs_nukenode(pn_tfile, pn_tdir, 353 1.1 pooka pcn_targ->pcn_name, pcn_targ->pcn_namelen); 354 1.1 pooka } 355 1.1 pooka 356 1.1 pooka /* out with the old */ 357 1.1 pooka dtfs_removedent(pn_sdir, dfd_src); 358 1.1 pooka /* and in with the new */ 359 1.1 pooka dtfs_adddent(pn_tdir, dfd_src); 360 1.1 pooka 361 1.1 pooka /* update name */ 362 1.1 pooka free(dfd_src->dfd_name); 363 1.1 pooka dfd_src->dfd_name = estrndup(pcn_targ->pcn_name,pcn_targ->pcn_namelen); 364 1.1 pooka dfd_src->dfd_namelen = strlen(dfd_src->dfd_name); 365 1.1 pooka 366 1.1 pooka dtfs_updatetimes(src, 0, 1, 0); 367 1.1 pooka 368 1.1 pooka return 0; 369 1.1 pooka } 370 1.1 pooka 371 1.1 pooka int 372 1.1 pooka dtfs_node_link(struct puffs_usermount *pu, void *opc, void *targ, 373 1.1 pooka const struct puffs_cn *pcn) 374 1.1 pooka { 375 1.1 pooka struct puffs_node *pn_dir = opc; 376 1.1 pooka struct dtfs_dirent *dfd; 377 1.1 pooka 378 1.1 pooka dfd = emalloc(sizeof(struct dtfs_dirent)); 379 1.1 pooka dfd->dfd_node = targ; 380 1.1 pooka dfd->dfd_name = estrndup(pcn->pcn_name, pcn->pcn_namelen); 381 1.1 pooka dfd->dfd_namelen = strlen(dfd->dfd_name); 382 1.1 pooka dtfs_adddent(pn_dir, dfd); 383 1.1 pooka 384 1.1 pooka dtfs_updatetimes(targ, 0, 1, 0); 385 1.1 pooka 386 1.1 pooka return 0; 387 1.1 pooka } 388 1.1 pooka 389 1.1 pooka int 390 1.1 pooka dtfs_node_symlink(struct puffs_usermount *pu, void *opc, 391 1.1 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn_src, 392 1.1 pooka const struct vattr *va, const char *link_target) 393 1.1 pooka { 394 1.1 pooka struct puffs_node *pn_parent = opc; 395 1.1 pooka struct puffs_node *pn_new; 396 1.1 pooka struct dtfs_file *df_new; 397 1.1 pooka 398 1.1 pooka if (va->va_type != VLNK) 399 1.1 pooka return ENODEV; 400 1.1 pooka 401 1.1 pooka pn_new = dtfs_genfile(pn_parent, pcn_src, VLNK); 402 1.1 pooka puffs_setvattr(&pn_new->pn_va, va); 403 1.1 pooka df_new = DTFS_PTOF(pn_new); 404 1.1 pooka df_new->df_linktarget = estrdup(link_target); 405 1.1 pooka pn_new->pn_va.va_size = strlen(df_new->df_linktarget); 406 1.1 pooka 407 1.1 pooka puffs_newinfo_setcookie(pni, pn_new); 408 1.1 pooka 409 1.1 pooka return 0; 410 1.1 pooka } 411 1.1 pooka 412 1.1 pooka int 413 1.1 pooka dtfs_node_readlink(struct puffs_usermount *pu, void *opc, 414 1.1 pooka const struct puffs_cred *cred, char *linkname, size_t *linklen) 415 1.1 pooka { 416 1.1 pooka struct dtfs_file *df = DTFS_CTOF(opc); 417 1.1 pooka struct puffs_node *pn = opc; 418 1.1 pooka 419 1.1 pooka assert(pn->pn_va.va_type == VLNK); 420 1.1 pooka strlcpy(linkname, df->df_linktarget, *linklen); 421 1.1 pooka *linklen = strlen(linkname); 422 1.1 pooka 423 1.1 pooka return 0; 424 1.1 pooka } 425 1.1 pooka 426 1.1 pooka int 427 1.1 pooka dtfs_node_mknod(struct puffs_usermount *pu, void *opc, 428 1.1 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn, 429 1.1 pooka const struct vattr *va) 430 1.1 pooka { 431 1.1 pooka struct puffs_node *pn_parent = opc; 432 1.1 pooka struct puffs_node *pn_new; 433 1.1 pooka 434 1.1 pooka if (!(va->va_type == VBLK || va->va_type == VCHR 435 1.1 pooka || va->va_type == VFIFO)) 436 1.1 pooka return EINVAL; 437 1.1 pooka 438 1.1 pooka pn_new = dtfs_genfile(pn_parent, pcn, va->va_type); 439 1.1 pooka puffs_setvattr(&pn_new->pn_va, va); 440 1.1 pooka 441 1.1 pooka puffs_newinfo_setcookie(pni, pn_new); 442 1.1 pooka 443 1.1 pooka return 0; 444 1.1 pooka } 445 1.1 pooka 446 1.1 pooka #define BLOCKOFF(a,b) ((a) & ((b)-1)) 447 1.1 pooka #define BLOCKLEFT(a,b) ((b) - BLOCKOFF(a,b)) 448 1.1 pooka 449 1.1 pooka /* 450 1.1 pooka * Read operation, used both for VOP_READ and VOP_GETPAGES 451 1.1 pooka */ 452 1.1 pooka int 453 1.1 pooka dtfs_node_read(struct puffs_usermount *pu, void *opc, uint8_t *buf, 454 1.1 pooka off_t offset, size_t *resid, const struct puffs_cred *pcr, int ioflag) 455 1.1 pooka { 456 1.1 pooka struct puffs_node *pn = opc; 457 1.1 pooka struct dtfs_file *df = DTFS_CTOF(opc); 458 1.1 pooka quad_t xfer, origxfer; 459 1.1 pooka uint8_t *src, *dest; 460 1.1 pooka size_t copylen; 461 1.1 pooka 462 1.1 pooka if (pn->pn_va.va_type != VREG) 463 1.1 pooka return EISDIR; 464 1.1 pooka 465 1.1 pooka xfer = MIN(*resid, df->df_datalen - offset); 466 1.1 pooka if (xfer < 0) 467 1.1 pooka return EINVAL; 468 1.1 pooka 469 1.1 pooka dest = buf; 470 1.1 pooka origxfer = xfer; 471 1.1 pooka while (xfer > 0) { 472 1.1 pooka copylen = MIN(xfer, BLOCKLEFT(offset, DTFS_BLOCKSIZE)); 473 1.1 pooka src = df->df_blocks[BLOCKNUM(offset, DTFS_BLOCKSHIFT)] 474 1.1 pooka + BLOCKOFF(offset, DTFS_BLOCKSIZE); 475 1.1 pooka memcpy(dest, src, copylen); 476 1.1 pooka offset += copylen; 477 1.1 pooka dest += copylen; 478 1.1 pooka xfer -= copylen; 479 1.1 pooka } 480 1.1 pooka *resid -= origxfer; 481 1.1 pooka 482 1.1 pooka dtfs_updatetimes(pn, 1, 0, 0); 483 1.1 pooka 484 1.1 pooka return 0; 485 1.1 pooka } 486 1.1 pooka 487 1.1 pooka /* 488 1.1 pooka * write operation on the wing 489 1.1 pooka */ 490 1.1 pooka int 491 1.1 pooka dtfs_node_write(struct puffs_usermount *pu, void *opc, uint8_t *buf, 492 1.1 pooka off_t offset, size_t *resid, const struct puffs_cred *pcr, int ioflag) 493 1.1 pooka { 494 1.1 pooka struct puffs_node *pn = opc; 495 1.1 pooka struct dtfs_file *df = DTFS_CTOF(opc); 496 1.1 pooka uint8_t *src, *dest; 497 1.1 pooka size_t copylen; 498 1.1 pooka 499 1.1 pooka if (pn->pn_va.va_type != VREG) 500 1.1 pooka return EISDIR; 501 1.1 pooka 502 1.1 pooka if (ioflag & PUFFS_IO_APPEND) 503 1.1 pooka offset = pn->pn_va.va_size; 504 1.1 pooka 505 1.1 pooka if (*resid + offset > pn->pn_va.va_size) 506 1.1 pooka dtfs_setsize(pn, *resid + offset); 507 1.1 pooka 508 1.1 pooka src = buf; 509 1.1 pooka while (*resid > 0) { 510 1.1 pooka int i; 511 1.1 pooka copylen = MIN(*resid, BLOCKLEFT(offset, DTFS_BLOCKSIZE)); 512 1.1 pooka i = BLOCKNUM(offset, DTFS_BLOCKSHIFT); 513 1.1 pooka dest = df->df_blocks[i] 514 1.1 pooka + BLOCKOFF(offset, DTFS_BLOCKSIZE); 515 1.1 pooka memcpy(dest, src, copylen); 516 1.1 pooka offset += copylen; 517 1.1 pooka dest += copylen; 518 1.1 pooka *resid -= copylen; 519 1.1 pooka } 520 1.1 pooka 521 1.1 pooka dtfs_updatetimes(pn, 0, 1, 1); 522 1.1 pooka 523 1.1 pooka return 0; 524 1.1 pooka } 525 1.1 pooka 526 1.1 pooka int 527 1.7 pooka dtfs_node_pathconf(struct puffs_usermount *pu, puffs_cookie_t opc, 528 1.7 pooka int name, register_t *retval) 529 1.7 pooka { 530 1.7 pooka 531 1.7 pooka switch (name) { 532 1.7 pooka case _PC_LINK_MAX: 533 1.7 pooka *retval = LINK_MAX; 534 1.7 pooka return 0; 535 1.7 pooka case _PC_NAME_MAX: 536 1.7 pooka *retval = NAME_MAX; 537 1.7 pooka return 0; 538 1.7 pooka case _PC_PATH_MAX: 539 1.7 pooka *retval = PATH_MAX; 540 1.7 pooka return 0; 541 1.7 pooka case _PC_PIPE_BUF: 542 1.7 pooka *retval = PIPE_BUF; 543 1.7 pooka return 0; 544 1.7 pooka case _PC_CHOWN_RESTRICTED: 545 1.7 pooka *retval = 1; 546 1.7 pooka return 0; 547 1.7 pooka case _PC_NO_TRUNC: 548 1.7 pooka *retval = 1; 549 1.7 pooka return 0; 550 1.7 pooka case _PC_SYNC_IO: 551 1.7 pooka *retval = 1; 552 1.7 pooka return 0; 553 1.7 pooka case _PC_FILESIZEBITS: 554 1.7 pooka *retval = 43; /* this one goes to 11 */ 555 1.7 pooka return 0; 556 1.7 pooka case _PC_SYMLINK_MAX: 557 1.7 pooka *retval = MAXPATHLEN; 558 1.7 pooka return 0; 559 1.7 pooka case _PC_2_SYMLINKS: 560 1.7 pooka *retval = 1; 561 1.7 pooka return 0; 562 1.7 pooka default: 563 1.7 pooka return EINVAL; 564 1.7 pooka } 565 1.7 pooka } 566 1.7 pooka 567 1.7 pooka int 568 1.1 pooka dtfs_node_inactive(struct puffs_usermount *pu, puffs_cookie_t opc) 569 1.1 pooka { 570 1.1 pooka struct puffs_node *pn = opc; 571 1.1 pooka 572 1.1 pooka if (pn->pn_va.va_nlink == 0) 573 1.1 pooka puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N1); 574 1.1 pooka return 0; 575 1.1 pooka } 576 1.1 pooka 577 1.1 pooka int 578 1.1 pooka dtfs_node_reclaim(struct puffs_usermount *pu, void *opc) 579 1.1 pooka { 580 1.1 pooka struct puffs_node *pn = opc; 581 1.1 pooka 582 1.1 pooka if (pn->pn_va.va_nlink == 0) 583 1.1 pooka dtfs_freenode(pn); 584 1.1 pooka 585 1.1 pooka return 0; 586 1.1 pooka } 587