1 /* $NetBSD: subr.c,v 1.9 2006/11/21 23:11:09 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the company nor the name of the author may be used to 15 * endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 #if !defined(lint) 33 __RCSID("$NetBSD: subr.c,v 1.9 2006/11/21 23:11:09 pooka Exp $"); 34 #endif /* !lint */ 35 36 #include <sys/types.h> 37 #include <sys/time.h> 38 #include <sys/vnode.h> 39 #include <sys/dirent.h> 40 41 #include <assert.h> 42 #include <puffs.h> 43 #include <stdlib.h> 44 #include <stdio.h> 45 #include <string.h> 46 47 /* 48 * Well, you're probably wondering why this isn't optimized. 49 * The reason is simple: my available time is not optimized for 50 * size ... so please be patient ;) 51 */ 52 struct puffs_node * 53 puffs_newpnode(struct puffs_usermount *puser, void *privdata, enum vtype type) 54 { 55 struct puffs_node *pn; 56 57 pn = calloc(1, sizeof(struct puffs_node)); 58 if (pn == NULL) 59 return NULL; 60 61 pn->pn_mnt = puser; 62 pn->pn_data = privdata; 63 pn->pn_type = type; 64 65 /* technically not needed */ 66 memset(&pn->pn_va, 0, sizeof(struct vattr)); 67 pn->pn_va.va_type = type; 68 69 LIST_INSERT_HEAD(&puser->pu_pnodelst, pn, pn_entries); 70 71 return pn; 72 } 73 74 void 75 puffs_putpnode(struct puffs_node *pn) 76 { 77 78 if (pn == NULL) 79 return; 80 81 LIST_REMOVE(pn, pn_entries); 82 free(pn); 83 } 84 85 int 86 puffs_gendotdent(struct dirent **dent, ino_t id, int dotdot, size_t *reslen) 87 { 88 const char *name; 89 90 assert(dotdot == 0 || dotdot == 1); 91 name = dotdot == 0 ? "." : ".."; 92 93 return puffs_nextdent(dent, name, id, DT_DIR, reslen); 94 } 95 96 int 97 puffs_nextdent(struct dirent **dent, const char *name, ino_t id, uint8_t dtype, 98 size_t *reslen) 99 { 100 struct dirent *d = *dent; 101 102 /* check if we have enough room for our dent-aligned dirent */ 103 if (_DIRENT_RECLEN(d, strlen(name)) > *reslen) 104 return 0; 105 106 d->d_fileno = id; 107 d->d_type = dtype; 108 d->d_namlen = (uint16_t)strlen(name); 109 (void)memcpy(&d->d_name, name, (size_t)d->d_namlen); 110 d->d_name[d->d_namlen] = '\0'; 111 d->d_reclen = (uint16_t)_DIRENT_SIZE(d); 112 113 *reslen -= d->d_reclen; 114 *dent = _DIRENT_NEXT(d); 115 116 return 1; 117 } 118 119 /*ARGSUSED*/ 120 int 121 puffs_vfsnop_unmount(struct puffs_usermount *pu, int flags, pid_t pid) 122 { 123 124 /* would you like to see puffs rule again, my friend? */ 125 return 0; 126 } 127 128 /*ARGSUSED*/ 129 int 130 puffs_vfsnop_sync(struct puffs_usermount *pu, int waitfor, 131 const struct puffs_cred *cred, pid_t pid) 132 { 133 134 return 0; 135 } 136 137 /*ARGSUSED*/ 138 int 139 puffs_vfsnop_statvfs(struct puffs_usermount *pu, struct statvfs *sbp, pid_t pid) 140 { 141 142 sbp->f_bsize = sbp->f_frsize = sbp->f_iosize = 512; 143 144 sbp->f_bfree=sbp->f_bavail=sbp->f_bresvd=sbp->f_blocks = (fsblkcnt_t)0; 145 sbp->f_ffree=sbp->f_favail=sbp->f_fresvd=sbp->f_files = (fsfilcnt_t)0; 146 sbp->f_fsidx = pu->pu_fsidx; 147 148 return 0; 149 } 150 151 /* 152 * Set vattr values for those applicable (i.e. not PUFFS_VNOVAL). 153 */ 154 void 155 puffs_setvattr(struct vattr *vap, const struct vattr *sva) 156 { 157 158 #define SETIFVAL(a, t) if (sva->a != (t)PUFFS_VNOVAL) vap->a = sva->a 159 if (sva->va_type != VNON) 160 vap->va_type = sva->va_type; 161 SETIFVAL(va_mode, mode_t); 162 SETIFVAL(va_nlink, nlink_t); 163 SETIFVAL(va_uid, uid_t); 164 SETIFVAL(va_gid, gid_t); 165 SETIFVAL(va_fsid, long); 166 SETIFVAL(va_size, u_quad_t); 167 SETIFVAL(va_blocksize, long); 168 SETIFVAL(va_atime.tv_sec, time_t); 169 SETIFVAL(va_ctime.tv_sec, time_t); 170 SETIFVAL(va_mtime.tv_sec, time_t); 171 SETIFVAL(va_birthtime.tv_sec, time_t); 172 SETIFVAL(va_atime.tv_nsec, long); 173 SETIFVAL(va_ctime.tv_nsec, long); 174 SETIFVAL(va_mtime.tv_nsec, long); 175 SETIFVAL(va_birthtime.tv_nsec, long); 176 SETIFVAL(va_gen, u_long); 177 SETIFVAL(va_flags, u_long); 178 SETIFVAL(va_rdev, dev_t); 179 SETIFVAL(va_bytes, u_quad_t); 180 #undef SETIFVAL 181 /* ignore va->va_vaflags */ 182 } 183 184 185 static int vdmap[] = { 186 DT_UNKNOWN, /* VNON */ 187 DT_REG, /* VREG */ 188 DT_DIR, /* VDIR */ 189 DT_BLK, /* VBLK */ 190 DT_CHR, /* VCHR */ 191 DT_LNK, /* VLNK */ 192 DT_SOCK, /* VSUCK*/ 193 DT_FIFO, /* VFIFO*/ 194 DT_UNKNOWN /* VBAD */ 195 }; 196 /* XXX: DT_WHT ? */ 197 int 198 puffs_vtype2dt(enum vtype vt) 199 { 200 201 if ((int)vt >= VNON && vt < (sizeof(vdmap)/sizeof(vdmap[0]))) 202 return vdmap[vt]; 203 204 return DT_UNKNOWN; 205 } 206 207 enum vtype 208 puffs_mode2vt(mode_t mode) 209 { 210 211 switch (mode & S_IFMT) { 212 case S_IFIFO: 213 return VFIFO; 214 case S_IFCHR: 215 return VCHR; 216 case S_IFDIR: 217 return VDIR; 218 case S_IFBLK: 219 return VBLK; 220 case S_IFREG: 221 return VREG; 222 case S_IFLNK: 223 return VLNK; 224 case S_IFSOCK: 225 return VSOCK; 226 default: 227 return VBAD; /* XXX: not really true, but ... */ 228 } 229 } 230