1 /* $NetBSD: subr.c,v 1.23 2008/08/12 19:44:39 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.23 2008/08/12 19:44:39 pooka Exp $"); 31 #endif /* !lint */ 32 33 #include <sys/types.h> 34 #include <sys/dirent.h> 35 #include <sys/time.h> 36 37 #include <assert.h> 38 #include <errno.h> 39 #include <stdlib.h> 40 #include <stdio.h> 41 #include <stddef.h> 42 #include <string.h> 43 #include <unistd.h> 44 45 #include "puffs.h" 46 #include "puffs_priv.h" 47 48 49 int 50 puffs_gendotdent(struct dirent **dent, ino_t id, int dotdot, size_t *reslen) 51 { 52 const char *name; 53 54 assert(dotdot == 0 || dotdot == 1); 55 name = dotdot == 0 ? "." : ".."; 56 57 return puffs_nextdent(dent, name, id, DT_DIR, reslen); 58 } 59 60 int 61 puffs_nextdent(struct dirent **dent, const char *name, ino_t id, uint8_t dtype, 62 size_t *reslen) 63 { 64 struct dirent *d = *dent; 65 unsigned int len, reclen; 66 int o; 67 char *cp; 68 69 /* check if we have enough room for our dent-aligned dirent */ 70 if (_DIRENT_RECLEN(d, strlen(name)) > *reslen) 71 return 0; 72 73 d->d_ino = id; 74 75 /* Compute the length of the name */ 76 cp = memchr(name, '\0', NAME_MAX); 77 if (cp == NULL) 78 len = NAME_MAX; 79 else 80 len = cp - (name); 81 82 /* Compute record length */ 83 reclen = offsetof(struct dirent, d_name) + len + 1; 84 o = (reclen % sizeof(long)); 85 if (o != 0) 86 reclen += sizeof(long) - o; 87 88 /* FIXME: Set d_off? 89 * dep->d_off = 90 */ 91 d->d_reclen = (unsigned short) reclen; 92 (void)memcpy(d->d_name, name, (size_t)len); 93 d->d_name[len] = '\0'; 94 95 *reslen -= d->d_reclen; 96 *dent = _DIRENT_NEXT(d); 97 98 return 1; 99 } 100 101 /*ARGSUSED*/ 102 int 103 puffs_fsnop_unmount(struct puffs_usermount *dontuse1, int dontuse2) 104 { 105 106 /* would you like to see puffs rule again, my friend? */ 107 return 0; 108 } 109 110 /*ARGSUSED*/ 111 int 112 puffs_fsnop_sync(struct puffs_usermount *dontuse1, int dontuse2, 113 const struct puffs_cred *dontuse3) 114 { 115 116 return 0; 117 } 118 119 /*ARGSUSED*/ 120 int 121 puffs_fsnop_statvfs(struct puffs_usermount *dontuse1, struct statvfs *sbp) 122 { 123 124 /* FIXME: implement me 125 sbp->f_bsize = sbp->f_frsize = sbp->f_iosize = 512; 126 127 sbp->f_bfree=sbp->f_bavail=sbp->f_bresvd=sbp->f_blocks = (fsblkcnt_t)0; 128 sbp->f_ffree=sbp->f_favail=sbp->f_fresvd=sbp->f_files = (fsfilcnt_t)0; 129 */ 130 return 0; 131 } 132 133 /*ARGSUSED3*/ 134 int 135 puffs_genfs_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc, 136 struct vattr *va, const struct puffs_cred *pcr) 137 { 138 struct puffs_node *pn = PU_CMAP(pu, opc); 139 140 memcpy(va, &pn->pn_va, sizeof(struct vattr)); 141 return 0; 142 } 143 144 /* 145 * Just put the node, don't do anything else. Don't use this if 146 * your fs needs more cleanup. 147 */ 148 /*ARGSUSED2*/ 149 int 150 puffs_genfs_node_reclaim(struct puffs_usermount *pu, puffs_cookie_t opc) 151 { 152 153 puffs_pn_put(PU_CMAP(pu, opc)); 154 155 return 0; 156 } 157 158 /* 159 * Just a wrapper to make calling the above nicer without having to pass 160 * NULLs from application code 161 */ 162 void 163 puffs_zerostatvfs(struct statvfs *sbp) 164 { 165 166 puffs_fsnop_statvfs(NULL, sbp); 167 } 168 169 /* 170 * Set vattr values for those applicable (i.e. not PUFFS_VNOVAL). 171 */ 172 void 173 puffs_setvattr(struct vattr *vap, const struct vattr *sva) 174 { 175 176 #define SETIFVAL(a, t) if (sva->a != (t)PUFFS_VNOVAL) vap->a = sva->a 177 if (sva->va_type != VNON) 178 vap->va_type = sva->va_type; 179 SETIFVAL(va_mode, mode_t); 180 SETIFVAL(va_nlink, nlink_t); 181 SETIFVAL(va_uid, uid_t); 182 SETIFVAL(va_gid, gid_t); 183 SETIFVAL(va_fsid, long); 184 SETIFVAL(va_size, u_quad_t); 185 SETIFVAL(va_fileid, ino_t); 186 SETIFVAL(va_blocksize, long); 187 SETIFVAL(va_atime.tv_sec, time_t); 188 SETIFVAL(va_ctime.tv_sec, time_t); 189 SETIFVAL(va_mtime.tv_sec, time_t); 190 SETIFVAL(va_birthtime.tv_sec, time_t); 191 SETIFVAL(va_atime.tv_nsec, long); 192 SETIFVAL(va_ctime.tv_nsec, long); 193 SETIFVAL(va_mtime.tv_nsec, long); 194 SETIFVAL(va_birthtime.tv_nsec, long); 195 SETIFVAL(va_gen, u_long); 196 SETIFVAL(va_flags, u_long); 197 SETIFVAL(va_rdev, dev_t); 198 SETIFVAL(va_bytes, u_quad_t); 199 #undef SETIFVAL 200 /* ignore va->va_vaflags */ 201 } 202 203 void 204 puffs_vattr_null(struct vattr *vap) 205 { 206 207 vap->va_type = VNON; 208 209 /* 210 * Assign individually so that it is safe even if size and 211 * sign of each member are varied. 212 */ 213 vap->va_mode = (mode_t)PUFFS_VNOVAL; 214 vap->va_nlink = (nlink_t)PUFFS_VNOVAL; 215 vap->va_uid = (uid_t)PUFFS_VNOVAL; 216 vap->va_gid = (gid_t)PUFFS_VNOVAL; 217 vap->va_fsid = PUFFS_VNOVAL; 218 vap->va_fileid = (ino_t)PUFFS_VNOVAL; 219 vap->va_size = (u_quad_t)PUFFS_VNOVAL; 220 vap->va_blocksize = sysconf(_SC_PAGESIZE); 221 vap->va_atime.tv_sec = 222 vap->va_mtime.tv_sec = 223 vap->va_ctime.tv_sec = 224 vap->va_birthtime.tv_sec = PUFFS_VNOVAL; 225 vap->va_atime.tv_nsec = 226 vap->va_mtime.tv_nsec = 227 vap->va_ctime.tv_nsec = 228 vap->va_birthtime.tv_nsec = PUFFS_VNOVAL; 229 vap->va_rdev = (dev_t)PUFFS_VNOVAL; 230 vap->va_bytes = (u_quad_t)PUFFS_VNOVAL; 231 232 vap->va_flags = 0; 233 vap->va_gen = 0; 234 vap->va_vaflags = 0; 235 } 236 237 static int vdmap[] = { 238 DT_UNKNOWN, /* VNON */ 239 DT_REG, /* VREG */ 240 DT_DIR, /* VDIR */ 241 DT_BLK, /* VBLK */ 242 DT_CHR, /* VCHR */ 243 DT_LNK, /* VLNK */ 244 DT_SOCK, /* VSUCK*/ 245 DT_FIFO, /* VFIFO*/ 246 DT_UNKNOWN /* VBAD */ 247 }; 248 /* XXX: DT_WHT ? */ 249 int 250 puffs_vtype2dt(enum vtype vt) 251 { 252 253 if ((int)vt >= VNON && vt < (sizeof(vdmap)/sizeof(vdmap[0]))) 254 return vdmap[vt]; 255 256 return DT_UNKNOWN; 257 } 258 259 enum vtype 260 puffs_mode2vt(mode_t mode) 261 { 262 263 switch (mode & S_IFMT) { 264 case S_IFIFO: 265 return VFIFO; 266 case S_IFCHR: 267 return VCHR; 268 case S_IFDIR: 269 return VDIR; 270 case S_IFBLK: 271 return VBLK; 272 case S_IFREG: 273 return VREG; 274 case S_IFLNK: 275 return VLNK; 276 case S_IFSOCK: 277 return VSOCK; 278 default: 279 return VBAD; /* XXX: not really true, but ... */ 280 } 281 } 282 283 void 284 puffs_stat2vattr(struct vattr *va, const struct stat *sb) 285 { 286 287 va->va_type = puffs_mode2vt(sb->st_mode); 288 va->va_mode = sb->st_mode; 289 va->va_nlink = sb->st_nlink; 290 va->va_uid = sb->st_uid; 291 va->va_gid = sb->st_gid; 292 va->va_fsid = sb->st_dev; 293 va->va_fileid = sb->st_ino; 294 va->va_size = sb->st_size; 295 va->va_atime.tv_nsec = va->va_mtime.tv_nsec = va->va_ctime.tv_nsec = 0; 296 va->va_atime.tv_sec = sb->st_atime; 297 va->va_ctime.tv_sec = sb->st_ctime; 298 va->va_mtime.tv_sec = sb->st_mtime; 299 va->va_blocksize = sb->st_blksize; 300 va->va_birthtime = sb->st_birthtimespec; 301 va->va_gen = sb->st_gen; 302 va->va_flags = sb->st_flags; 303 va->va_rdev = sb->st_rdev; 304 va->va_bytes = sb->st_blocks * sb->st_blksize; 305 va->va_filerev = 0; 306 va->va_vaflags = 0; 307 } 308 309 mode_t 310 puffs_addvtype2mode(mode_t mode, enum vtype type) 311 { 312 313 switch (type) { 314 case VCHR: 315 mode |= S_IFCHR; 316 break; 317 case VBLK: 318 mode |= S_IFBLK; 319 break; 320 default: 321 break; 322 } 323 324 return mode; 325 } 326