1 /* $NetBSD: subr.c,v 1.27 2011/02/17 17:55:36 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 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 #if !defined(lint) 30 __RCSID("$NetBSD: subr.c,v 1.27 2011/02/17 17:55:36 pooka Exp $"); 31 #endif /* !lint */ 32 33 #include <sys/types.h> 34 #include <sys/time.h> 35 #include <sys/vnode.h> 36 #include <sys/dirent.h> 37 38 #include <assert.h> 39 #include <errno.h> 40 #include <puffs.h> 41 #include <stdlib.h> 42 #include <stdio.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #include "puffs_priv.h" 47 48 int 49 puffs_gendotdent(struct dirent **dent, ino_t id, int dotdot, size_t *reslen) 50 { 51 const char *name; 52 53 assert(dotdot == 0 || dotdot == 1); 54 name = dotdot == 0 ? "." : ".."; 55 56 return puffs_nextdent(dent, name, id, DT_DIR, reslen); 57 } 58 59 int 60 puffs_nextdent(struct dirent **dent, const char *name, ino_t id, uint8_t dtype, 61 size_t *reslen) 62 { 63 struct dirent *d = *dent; 64 65 /* check if we have enough room for our dent-aligned dirent */ 66 if (_DIRENT_RECLEN(d, strlen(name)) > *reslen) 67 return 0; 68 69 d->d_fileno = id; 70 d->d_type = dtype; 71 d->d_namlen = (uint16_t)strlen(name); 72 (void)memcpy(&d->d_name, name, (size_t)d->d_namlen); 73 d->d_name[d->d_namlen] = '\0'; 74 d->d_reclen = (uint16_t)_DIRENT_SIZE(d); 75 76 *reslen -= d->d_reclen; 77 *dent = _DIRENT_NEXT(d); 78 79 return 1; 80 } 81 82 /*ARGSUSED*/ 83 int 84 puffs_fsnop_unmount(struct puffs_usermount *dontuse1, int dontuse2) 85 { 86 87 /* would you like to see puffs rule again, my friend? */ 88 return 0; 89 } 90 91 /*ARGSUSED*/ 92 int 93 puffs_fsnop_sync(struct puffs_usermount *dontuse1, int dontuse2, 94 const struct puffs_cred *dontuse3) 95 { 96 97 return 0; 98 } 99 100 /*ARGSUSED*/ 101 int 102 puffs_fsnop_statvfs(struct puffs_usermount *dontuse1, struct statvfs *sbp) 103 { 104 105 sbp->f_bsize = sbp->f_frsize = sbp->f_iosize = DEV_BSIZE; 106 107 sbp->f_bfree=sbp->f_bavail=sbp->f_bresvd=sbp->f_blocks = (fsblkcnt_t)0; 108 sbp->f_ffree=sbp->f_favail=sbp->f_fresvd=sbp->f_files = (fsfilcnt_t)0; 109 110 sbp->f_namemax = MAXNAMLEN; 111 112 return 0; 113 } 114 115 /*ARGSUSED3*/ 116 int 117 puffs_genfs_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc, 118 struct vattr *va, const struct puffs_cred *pcr) 119 { 120 struct puffs_node *pn = PU_CMAP(pu, opc); 121 122 memcpy(va, &pn->pn_va, sizeof(struct vattr)); 123 return 0; 124 } 125 126 /* 127 * Just put the node, don't do anything else. Don't use this if 128 * your fs needs more cleanup. 129 */ 130 /*ARGSUSED2*/ 131 int 132 puffs_genfs_node_reclaim(struct puffs_usermount *pu, puffs_cookie_t opc) 133 { 134 135 puffs_pn_put(PU_CMAP(pu, opc)); 136 137 return 0; 138 } 139 140 /* 141 * Just a wrapper to make calling the above nicer without having to pass 142 * NULLs from application code 143 */ 144 void 145 puffs_zerostatvfs(struct statvfs *sbp) 146 { 147 148 puffs_fsnop_statvfs(NULL, sbp); 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, dev_t); 166 SETIFVAL(va_size, u_quad_t); 167 SETIFVAL(va_fileid, ino_t); 168 SETIFVAL(va_blocksize, long); 169 SETIFVAL(va_atime.tv_sec, time_t); 170 SETIFVAL(va_ctime.tv_sec, time_t); 171 SETIFVAL(va_mtime.tv_sec, time_t); 172 SETIFVAL(va_birthtime.tv_sec, time_t); 173 SETIFVAL(va_atime.tv_nsec, long); 174 SETIFVAL(va_ctime.tv_nsec, long); 175 SETIFVAL(va_mtime.tv_nsec, long); 176 SETIFVAL(va_birthtime.tv_nsec, long); 177 SETIFVAL(va_gen, u_long); 178 SETIFVAL(va_flags, u_long); 179 SETIFVAL(va_rdev, dev_t); 180 SETIFVAL(va_bytes, u_quad_t); 181 #undef SETIFVAL 182 /* ignore va->va_vaflags */ 183 } 184 185 void 186 puffs_vattr_null(struct vattr *vap) 187 { 188 189 vap->va_type = VNON; 190 191 /* 192 * Assign individually so that it is safe even if size and 193 * sign of each member are varied. 194 */ 195 vap->va_mode = (mode_t)PUFFS_VNOVAL; 196 vap->va_nlink = (nlink_t)PUFFS_VNOVAL; 197 vap->va_uid = (uid_t)PUFFS_VNOVAL; 198 vap->va_gid = (gid_t)PUFFS_VNOVAL; 199 vap->va_fsid = (dev_t)PUFFS_VNOVAL; 200 vap->va_fileid = (ino_t)PUFFS_VNOVAL; 201 vap->va_size = (u_quad_t)PUFFS_VNOVAL; 202 vap->va_blocksize = sysconf(_SC_PAGESIZE); 203 vap->va_atime.tv_sec = 204 vap->va_mtime.tv_sec = 205 vap->va_ctime.tv_sec = 206 vap->va_birthtime.tv_sec = PUFFS_VNOVAL; 207 vap->va_atime.tv_nsec = 208 vap->va_mtime.tv_nsec = 209 vap->va_ctime.tv_nsec = 210 vap->va_birthtime.tv_nsec = PUFFS_VNOVAL; 211 vap->va_rdev = (dev_t)PUFFS_VNOVAL; 212 vap->va_bytes = (u_quad_t)PUFFS_VNOVAL; 213 214 vap->va_flags = 0; 215 vap->va_gen = 0; 216 vap->va_vaflags = 0; 217 } 218 219 static int vdmap[] = { 220 DT_UNKNOWN, /* VNON */ 221 DT_REG, /* VREG */ 222 DT_DIR, /* VDIR */ 223 DT_BLK, /* VBLK */ 224 DT_CHR, /* VCHR */ 225 DT_LNK, /* VLNK */ 226 DT_SOCK, /* VSUCK*/ 227 DT_FIFO, /* VFIFO*/ 228 DT_UNKNOWN /* VBAD */ 229 }; 230 /* XXX: DT_WHT ? */ 231 int 232 puffs_vtype2dt(enum vtype vt) 233 { 234 235 if ((int)vt >= VNON && vt < (sizeof(vdmap)/sizeof(vdmap[0]))) 236 return vdmap[vt]; 237 238 return DT_UNKNOWN; 239 } 240 241 enum vtype 242 puffs_mode2vt(mode_t mode) 243 { 244 245 switch (mode & S_IFMT) { 246 case S_IFIFO: 247 return VFIFO; 248 case S_IFCHR: 249 return VCHR; 250 case S_IFDIR: 251 return VDIR; 252 case S_IFBLK: 253 return VBLK; 254 case S_IFREG: 255 return VREG; 256 case S_IFLNK: 257 return VLNK; 258 case S_IFSOCK: 259 return VSOCK; 260 default: 261 return VBAD; /* XXX: not really true, but ... */ 262 } 263 } 264 265 void 266 puffs_stat2vattr(struct vattr *va, const struct stat *sb) 267 { 268 269 va->va_type = puffs_mode2vt(sb->st_mode); 270 va->va_mode = sb->st_mode; 271 va->va_nlink = sb->st_nlink; 272 va->va_uid = sb->st_uid; 273 va->va_gid = sb->st_gid; 274 va->va_fsid = sb->st_dev; 275 va->va_fileid = sb->st_ino; 276 va->va_size = sb->st_size; 277 va->va_blocksize = sb->st_blksize; 278 va->va_atime = sb->st_atimespec; 279 va->va_ctime = sb->st_ctimespec; 280 va->va_mtime = sb->st_mtimespec; 281 va->va_birthtime = sb->st_birthtimespec; 282 va->va_gen = sb->st_gen; 283 va->va_flags = sb->st_flags; 284 va->va_rdev = sb->st_rdev; 285 va->va_bytes = sb->st_blocks << DEV_BSHIFT; 286 va->va_filerev = 0; 287 va->va_vaflags = 0; 288 } 289 290 mode_t 291 puffs_addvtype2mode(mode_t mode, enum vtype type) 292 { 293 294 switch (type) { 295 case VCHR: 296 mode |= S_IFCHR; 297 break; 298 case VBLK: 299 mode |= S_IFBLK; 300 break; 301 case VSOCK: 302 mode |= S_IFSOCK; 303 break; 304 case VFIFO: 305 mode |= S_IFIFO; 306 break; 307 case VREG: 308 mode |= S_IFREG; 309 break; 310 case VLNK: 311 mode |= S_IFLNK; 312 break; 313 case VDIR: 314 mode |= S_IFDIR; 315 break; 316 default: 317 break; 318 } 319 320 return mode; 321 } 322