1272343Sngie/* $NetBSD: dtfs_vfsops.c,v 1.3 2012/11/04 23:37:02 christos Exp $ */ 2272343Sngie 3272343Sngie/* 4272343Sngie * Copyright (c) 2006 Antti Kantee. All Rights Reserved. 5272343Sngie * 6272343Sngie * Redistribution and use in source and binary forms, with or without 7272343Sngie * modification, are permitted provided that the following conditions 8272343Sngie * are met: 9272343Sngie * 1. Redistributions of source code must retain the above copyright 10272343Sngie * notice, this list of conditions and the following disclaimer. 11272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 12272343Sngie * notice, this list of conditions and the following disclaimer in the 13272343Sngie * documentation and/or other materials provided with the distribution. 14272343Sngie * 15272343Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16272343Sngie * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17272343Sngie * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18272343Sngie * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21272343Sngie * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25272343Sngie * SUCH DAMAGE. 26272343Sngie */ 27272343Sngie 28272343Sngie#include <sys/types.h> 29272343Sngie#include <sys/resource.h> 30272343Sngie 31272343Sngie#include <stdio.h> 32272343Sngie#include <assert.h> 33272343Sngie#include <err.h> 34272343Sngie#include <errno.h> 35272343Sngie#include <puffs.h> 36272343Sngie#include <string.h> 37272343Sngie#include <stdlib.h> 38272343Sngie#include <unistd.h> 39272343Sngie#include <util.h> 40272343Sngie 41272343Sngie#include "dtfs.h" 42272343Sngie 43272343Sngiestatic int 44272343Sngiertstr(struct puffs_usermount *pu, const char *str, enum vtype vt) 45272343Sngie{ 46272343Sngie struct puffs_node *pn = puffs_getroot(pu); 47272343Sngie struct vattr *va = &pn->pn_va; 48272343Sngie struct dtfs_file *df = DTFS_PTOF(pn); 49272343Sngie char ltarg[256+1]; 50272343Sngie 51272343Sngie if (sscanf(str, "%*s %256s", ltarg) != 1) 52272343Sngie return 1; 53272343Sngie 54272343Sngie dtfs_baseattrs(va, vt, 2); 55272343Sngie df->df_linktarget = estrdup(ltarg); 56272343Sngie 57272343Sngie va->va_nlink = 1; 58272343Sngie va->va_size = strlen(df->df_linktarget); 59272343Sngie 60272343Sngie puffs_setrootinfo(pu, vt, 0, 0); 61272343Sngie 62272343Sngie return 0; 63272343Sngie} 64272343Sngie 65272343Sngiestatic int 66272343Sngiertdev(struct puffs_usermount *pu, const char *str, enum vtype vt) 67272343Sngie{ 68272343Sngie struct puffs_node *pn = puffs_getroot(pu); 69272343Sngie struct vattr *va = &pn->pn_va; 70272343Sngie int major, minor; 71272343Sngie 72272343Sngie if (sscanf(str, "%*s %d %d", &major, &minor) != 2) 73272343Sngie return 1; 74272343Sngie 75272343Sngie dtfs_baseattrs(va, vt, 2); 76272343Sngie va->va_nlink = 1; 77272343Sngie va->va_rdev = makedev(major, minor); 78272343Sngie 79272343Sngie if (vt == VBLK) 80272343Sngie va->va_mode |= S_IFBLK; 81272343Sngie else 82272343Sngie va->va_mode |= S_IFCHR; 83272343Sngie 84272343Sngie puffs_setrootinfo(pu, vt, 0, va->va_rdev); 85272343Sngie 86272343Sngie return 0; 87272343Sngie} 88272343Sngie 89272343Sngiestatic int 90272343Sngiertnorm(struct puffs_usermount *pu, const char *str, enum vtype vt) 91272343Sngie{ 92272343Sngie struct puffs_node *pn = puffs_getroot(pu); 93272343Sngie struct vattr *va = &pn->pn_va; 94272343Sngie 95272343Sngie dtfs_baseattrs(va, vt, 2); 96272343Sngie if (vt == VDIR) 97272343Sngie va->va_nlink = 2; 98272343Sngie else 99272343Sngie va->va_nlink = 1; 100272343Sngie 101272343Sngie puffs_setrootinfo(pu, vt, 0, 0); 102272343Sngie 103272343Sngie return 0; 104272343Sngie} 105272343Sngie 106272343Sngiestruct rtype { 107272343Sngie char *tstr; 108272343Sngie enum vtype vt; 109272343Sngie int (*pfunc)(struct puffs_usermount *, const char *, enum vtype); 110272343Sngie} rtypes[] = { 111272343Sngie { "reg", VREG, rtnorm }, 112272343Sngie { "dir", VDIR, rtnorm }, 113272343Sngie { "blk", VBLK, rtdev }, 114272343Sngie { "chr", VCHR, rtdev }, 115272343Sngie { "lnk", VLNK, rtstr }, 116272343Sngie { "sock", VSOCK, rtnorm }, 117272343Sngie { "fifo", VFIFO, rtnorm } 118272343Sngie}; 119272343Sngie#define NTYPES (sizeof(rtypes) / sizeof(rtypes[0])) 120272343Sngie 121272343Sngieint 122272343Sngiedtfs_domount(struct puffs_usermount *pu, const char *typestr) 123272343Sngie{ 124272343Sngie struct dtfs_mount *dtm; 125272343Sngie struct dtfs_file *dff; 126272343Sngie struct puffs_node *pn; 127272343Sngie int i; 128272343Sngie 129272343Sngie /* create mount-local thingie */ 130272343Sngie dtm = puffs_getspecific(pu); 131272343Sngie dtm->dtm_nextfileid = 3; 132272343Sngie dtm->dtm_nfiles = 1; 133272343Sngie dtm->dtm_fsizes = 0; 134272343Sngie LIST_INIT(&dtm->dtm_pollent); 135272343Sngie 136272343Sngie /* 137272343Sngie * create root directory, do it "by hand" to avoid special-casing 138272343Sngie * dtfs_genfile() 139272343Sngie */ 140272343Sngie dff = dtfs_newdir(); 141272343Sngie dff->df_dotdot = NULL; 142272343Sngie pn = puffs_pn_new(pu, dff); 143272343Sngie if (!pn) 144272343Sngie errx(1, "puffs_newpnode"); 145272343Sngie puffs_setroot(pu, pn); 146272343Sngie 147272343Sngie if (!typestr) { 148272343Sngie rtnorm(pu, NULL, VDIR); 149272343Sngie } else { 150272343Sngie for (i = 0; i < NTYPES; i++) { 151272343Sngie if (strncmp(rtypes[i].tstr, typestr, 152272343Sngie strlen(rtypes[i].tstr)) == 0) { 153272343Sngie if (rtypes[i].pfunc(pu, typestr, 154272343Sngie rtypes[i].vt) != 0) { 155272343Sngie fprintf(stderr, "failed to parse " 156272343Sngie "\"%s\"\n", typestr); 157272343Sngie return 1; 158272343Sngie } 159272343Sngie break; 160272343Sngie } 161272343Sngie } 162272343Sngie if (i == NTYPES) { 163272343Sngie fprintf(stderr, "no maching type for %s\n", typestr); 164272343Sngie return 1; 165272343Sngie } 166272343Sngie } 167272343Sngie 168272343Sngie return 0; 169272343Sngie} 170272343Sngie 171272343Sngie/* 172272343Sngie * statvfs() should fill in the following members of struct statvfs: 173272343Sngie * 174272343Sngie * unsigned long f_bsize; file system block size 175272343Sngie * unsigned long f_frsize; fundamental file system block size 176272343Sngie * unsigned long f_iosize; optimal file system block size 177272343Sngie * fsblkcnt_t f_blocks; number of blocks in file system, 178272343Sngie * (in units of f_frsize) 179272343Sngie * 180272343Sngie * fsblkcnt_t f_bfree; free blocks avail in file system 181272343Sngie * fsblkcnt_t f_bavail; free blocks avail to non-root 182272343Sngie * fsblkcnt_t f_bresvd; blocks reserved for root 183272343Sngie * 184272343Sngie * fsfilcnt_t f_files; total file nodes in file system 185272343Sngie * fsfilcnt_t f_ffree; free file nodes in file system 186272343Sngie * fsfilcnt_t f_favail; free file nodes avail to non-root 187272343Sngie * fsfilcnt_t f_fresvd; file nodes reserved for root 188272343Sngie * 189272343Sngie * 190272343Sngie * The rest are filled in by the kernel. 191272343Sngie */ 192272343Sngie#define ROUND(a,b) (((a) + ((b)-1)) & ~((b)-1)) 193272343Sngie#define NFILES 1024*1024 194272343Sngieint 195272343Sngiedtfs_fs_statvfs(struct puffs_usermount *pu, struct statvfs *sbp) 196272343Sngie{ 197272343Sngie struct rlimit rlim; 198272343Sngie struct dtfs_mount *dtm; 199272343Sngie off_t btot, bfree; 200272343Sngie int pgsize; 201272343Sngie 202272343Sngie dtm = puffs_getspecific(pu); 203272343Sngie pgsize = getpagesize(); 204272343Sngie memset(sbp, 0, sizeof(struct statvfs)); 205272343Sngie 206272343Sngie /* 207272343Sngie * Use datasize rlimit as an _approximation_ for free size. 208272343Sngie * This, of course, is not accurate due to overhead and not 209272343Sngie * accounting for metadata. 210272343Sngie */ 211272343Sngie if (getrlimit(RLIMIT_DATA, &rlim) == 0) 212272343Sngie btot = rlim.rlim_cur; 213272343Sngie else 214272343Sngie btot = 16*1024*1024; 215272343Sngie bfree = btot - dtm->dtm_fsizes; 216272343Sngie 217272343Sngie sbp->f_blocks = ROUND(btot, pgsize) / pgsize; 218272343Sngie sbp->f_files = NFILES; 219272343Sngie 220272343Sngie sbp->f_bsize = sbp->f_frsize = sbp->f_iosize = pgsize; 221272343Sngie sbp->f_bfree = sbp->f_bavail = ROUND(bfree, pgsize) / pgsize; 222272343Sngie sbp->f_ffree = sbp->f_favail = NFILES - dtm->dtm_nfiles; 223272343Sngie 224272343Sngie sbp->f_bresvd = sbp->f_fresvd = 0; 225272343Sngie 226272343Sngie return 0; 227272343Sngie} 228272343Sngie#undef ROUND 229272343Sngie 230272343Sngiestatic void * 231272343Sngieaddrcmp(struct puffs_usermount *pu, struct puffs_node *pn, void *arg) 232272343Sngie{ 233272343Sngie 234272343Sngie if (pn == arg) 235272343Sngie return pn; 236272343Sngie 237272343Sngie return NULL; 238272343Sngie} 239272343Sngie 240272343Sngieint 241272343Sngiedtfs_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize, 242272343Sngie struct puffs_newinfo *pni) 243272343Sngie{ 244272343Sngie struct dtfs_fid *dfid; 245272343Sngie struct puffs_node *pn; 246272343Sngie 247272343Sngie assert(fidsize == sizeof(struct dtfs_fid)); 248272343Sngie dfid = fid; 249272343Sngie 250272343Sngie pn = puffs_pn_nodewalk(pu, addrcmp, dfid->dfid_addr); 251272343Sngie if (pn == NULL) 252272343Sngie return ESTALE; 253272343Sngie 254272343Sngie if (pn->pn_va.va_fileid != dfid->dfid_fileid 255272343Sngie || pn->pn_va.va_gen != dfid->dfid_gen) 256272343Sngie return ESTALE; 257272343Sngie 258272343Sngie puffs_newinfo_setcookie(pni, pn); 259272343Sngie puffs_newinfo_setvtype(pni, pn->pn_va.va_type); 260272343Sngie puffs_newinfo_setsize(pni, pn->pn_va.va_size); 261272343Sngie puffs_newinfo_setrdev(pni, pn->pn_va.va_rdev); 262272343Sngie 263272343Sngie return 0; 264272343Sngie} 265272343Sngie 266272343Sngieint 267272343Sngiedtfs_fs_nodetofh(struct puffs_usermount *pu, void *cookie, 268272343Sngie void *fid, size_t *fidsize) 269272343Sngie{ 270272343Sngie struct puffs_node *pn = cookie; 271272343Sngie struct dtfs_fid *dfid; 272272343Sngie extern int dynamicfh; 273272343Sngie 274272343Sngie if (dynamicfh == 0) { 275272343Sngie assert(*fidsize >= sizeof(struct dtfs_fid)); 276272343Sngie } else { 277272343Sngie if (*fidsize < sizeof(struct dtfs_fid)) { 278272343Sngie *fidsize = sizeof(struct dtfs_fid); 279272343Sngie return E2BIG; 280272343Sngie } 281272343Sngie *fidsize = sizeof(struct dtfs_fid); 282272343Sngie } 283272343Sngie 284272343Sngie dfid = fid; 285272343Sngie 286272343Sngie dfid->dfid_addr = pn; 287272343Sngie dfid->dfid_fileid = pn->pn_va.va_fileid; 288272343Sngie dfid->dfid_gen = pn->pn_va.va_gen; 289272343Sngie 290272343Sngie return 0; 291272343Sngie} 292272343Sngie 293272343Sngieint 294272343Sngiedtfs_fs_unmount(struct puffs_usermount *pu, int flags) 295272343Sngie{ 296272343Sngie 297272343Sngie return 0; 298272343Sngie} 299