1 1.20 manu /* $NetBSD: subr.c,v 1.20 2014/08/10 03:22:33 manu Exp $ */ 2 1.1 manu 3 1.1 manu /*- 4 1.11 manu * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved. 5 1.1 manu * 6 1.1 manu * Redistribution and use in source and binary forms, with or without 7 1.1 manu * modification, are permitted provided that the following conditions 8 1.1 manu * are met: 9 1.1 manu * 1. Redistributions of source code must retain the above copyright 10 1.1 manu * notice, this list of conditions and the following disclaimer. 11 1.1 manu * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 manu * notice, this list of conditions and the following disclaimer in the 13 1.1 manu * documentation and/or other materials provided with the distribution. 14 1.1 manu * 15 1.1 manu * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 1.1 manu * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 1.1 manu * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 1.1 manu * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 1.1 manu * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 1.1 manu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 1.1 manu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 1.1 manu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 1.1 manu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 1.1 manu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 1.1 manu * POSSIBILITY OF SUCH DAMAGE. 26 1.1 manu */ 27 1.1 manu 28 1.1 manu #include <stdio.h> 29 1.1 manu #include <stdlib.h> 30 1.1 manu #include <err.h> 31 1.1 manu #include <errno.h> 32 1.1 manu #include <sysexits.h> 33 1.1 manu #include <syslog.h> 34 1.1 manu #include <puffs.h> 35 1.1 manu #include <paths.h> 36 1.19 manu #include <sys/hash.h> 37 1.12 manu #include <sys/extattr.h> 38 1.1 manu 39 1.1 manu #include "perfuse_priv.h" 40 1.1 manu 41 1.12 manu struct perfuse_ns_map { 42 1.12 manu const char *pnm_ns; 43 1.12 manu const size_t pnm_nslen; 44 1.12 manu const int pnm_native_ns; 45 1.12 manu }; 46 1.12 manu 47 1.12 manu #define PERFUSE_NS_MAP(ns, native_ns) \ 48 1.12 manu { ns ".", sizeof(ns), native_ns } 49 1.12 manu 50 1.19 manu static __inline struct perfuse_node_hashlist *perfuse_nidhash(struct 51 1.19 manu perfuse_state *, uint64_t); 52 1.8 manu 53 1.1 manu struct puffs_node * 54 1.17 matt perfuse_new_pn(struct puffs_usermount *pu, const char *name, 55 1.17 matt struct puffs_node *parent) 56 1.1 manu { 57 1.19 manu struct perfuse_state *ps = puffs_getspecific(pu); 58 1.1 manu struct puffs_node *pn; 59 1.1 manu struct perfuse_node_data *pnd; 60 1.1 manu 61 1.1 manu if ((pnd = malloc(sizeof(*pnd))) == NULL) 62 1.13 christos DERR(EX_OSERR, "%s: malloc failed", __func__); 63 1.1 manu 64 1.1 manu if ((pn = puffs_pn_new(pu, pnd)) == NULL) 65 1.13 christos DERR(EX_SOFTWARE, "%s: puffs_pn_new failed", __func__); 66 1.1 manu 67 1.1 manu (void)memset(pnd, 0, sizeof(*pnd)); 68 1.4 manu pnd->pnd_rfh = FUSE_UNKNOWN_FH; 69 1.4 manu pnd->pnd_wfh = FUSE_UNKNOWN_FH; 70 1.14 manu pnd->pnd_nodeid = PERFUSE_UNKNOWN_NODEID; 71 1.19 manu if (parent != NULL) { 72 1.19 manu pnd->pnd_parent_nodeid = PERFUSE_NODE_DATA(parent)->pnd_nodeid; 73 1.19 manu } else { 74 1.19 manu pnd->pnd_parent_nodeid = FUSE_ROOT_ID; 75 1.19 manu } 76 1.19 manu pnd->pnd_fuse_nlookup = 0; 77 1.19 manu pnd->pnd_puffs_nlookup = 0; 78 1.5 manu pnd->pnd_pn = (puffs_cookie_t)pn; 79 1.19 manu if (strcmp(name, "..") != 0) 80 1.19 manu (void)strlcpy(pnd->pnd_name, name, MAXPATHLEN); 81 1.19 manu else 82 1.19 manu pnd->pnd_name[0] = 0; /* anonymous for now */ 83 1.1 manu TAILQ_INIT(&pnd->pnd_pcq); 84 1.1 manu 85 1.19 manu puffs_pn_setpriv(pn, pnd); 86 1.5 manu 87 1.19 manu ps->ps_nodecount++; 88 1.1 manu 89 1.1 manu return pn; 90 1.1 manu } 91 1.1 manu 92 1.1 manu void 93 1.19 manu perfuse_destroy_pn(struct puffs_usermount *pu, struct puffs_node *pn) 94 1.1 manu { 95 1.19 manu struct perfuse_state *ps = puffs_getspecific(pu); 96 1.1 manu struct perfuse_node_data *pnd; 97 1.1 manu 98 1.18 manu if ((pnd = puffs_pn_getpriv(pn)) != NULL) { 99 1.19 manu if (pnd->pnd_all_fd != NULL) 100 1.19 manu free(pnd->pnd_all_fd); 101 1.1 manu 102 1.1 manu if (pnd->pnd_dirent != NULL) 103 1.1 manu free(pnd->pnd_dirent); 104 1.19 manu 105 1.1 manu #ifdef PERFUSE_DEBUG 106 1.4 manu if (pnd->pnd_flags & PND_OPEN) 107 1.4 manu DERRX(EX_SOFTWARE, "%s: file open", __func__); 108 1.1 manu 109 1.1 manu if (!TAILQ_EMPTY(&pnd->pnd_pcq)) 110 1.1 manu DERRX(EX_SOFTWARE, "%s: non empty pnd_pcq", __func__); 111 1.19 manu 112 1.19 manu pnd->pnd_flags |= PND_INVALID; 113 1.1 manu #endif /* PERFUSE_DEBUG */ 114 1.1 manu 115 1.1 manu free(pnd); 116 1.1 manu } 117 1.1 manu 118 1.7 manu puffs_pn_put(pn); 119 1.1 manu 120 1.19 manu ps->ps_nodecount--; 121 1.19 manu 122 1.1 manu return; 123 1.1 manu } 124 1.1 manu 125 1.1 manu void 126 1.17 matt perfuse_new_fh(puffs_cookie_t opc, uint64_t fh, int mode) 127 1.1 manu { 128 1.1 manu struct perfuse_node_data *pnd; 129 1.1 manu 130 1.1 manu pnd = PERFUSE_NODE_DATA(opc); 131 1.1 manu 132 1.4 manu if (mode & FWRITE) { 133 1.4 manu if (pnd->pnd_flags & PND_WFH) 134 1.4 manu DERRX(EX_SOFTWARE, "%s: opc = %p, write fh already set", 135 1.4 manu __func__, (void *)opc); 136 1.4 manu pnd->pnd_wfh = fh; 137 1.4 manu pnd->pnd_flags |= PND_WFH; 138 1.4 manu } 139 1.4 manu 140 1.4 manu if (mode & FREAD) { 141 1.4 manu if (pnd->pnd_flags & PND_RFH) 142 1.4 manu DERRX(EX_SOFTWARE, "%s: opc = %p, read fh already set", 143 1.4 manu __func__, (void *)opc); 144 1.4 manu pnd->pnd_rfh = fh; 145 1.4 manu pnd->pnd_flags |= PND_RFH; 146 1.4 manu } 147 1.1 manu 148 1.1 manu return; 149 1.1 manu } 150 1.1 manu 151 1.1 manu void 152 1.17 matt perfuse_destroy_fh(puffs_cookie_t opc, uint64_t fh) 153 1.1 manu { 154 1.1 manu struct perfuse_node_data *pnd; 155 1.1 manu 156 1.1 manu pnd = PERFUSE_NODE_DATA(opc); 157 1.1 manu 158 1.4 manu if (fh == pnd->pnd_rfh) { 159 1.4 manu if (!(pnd->pnd_flags & PND_RFH) && (fh != FUSE_UNKNOWN_FH)) 160 1.4 manu DERRX(EX_SOFTWARE, 161 1.4 manu "%s: opc = %p, unset rfh = %"PRIx64"", 162 1.4 manu __func__, (void *)opc, fh); 163 1.4 manu pnd->pnd_rfh = FUSE_UNKNOWN_FH; 164 1.4 manu pnd->pnd_flags &= ~PND_RFH; 165 1.1 manu } 166 1.1 manu 167 1.4 manu if (fh == pnd->pnd_wfh) { 168 1.4 manu if (!(pnd->pnd_flags & PND_WFH) && (fh != FUSE_UNKNOWN_FH)) 169 1.4 manu DERRX(EX_SOFTWARE, 170 1.4 manu "%s: opc = %p, unset wfh = %"PRIx64"", 171 1.4 manu __func__, (void *)opc, fh); 172 1.4 manu pnd->pnd_wfh = FUSE_UNKNOWN_FH; 173 1.4 manu pnd->pnd_flags &= ~PND_WFH; 174 1.4 manu } 175 1.2 manu 176 1.1 manu return; 177 1.1 manu } 178 1.1 manu 179 1.1 manu uint64_t 180 1.17 matt perfuse_get_fh(puffs_cookie_t opc, int mode) 181 1.1 manu { 182 1.1 manu struct perfuse_node_data *pnd; 183 1.1 manu 184 1.1 manu pnd = PERFUSE_NODE_DATA(opc); 185 1.1 manu 186 1.6 manu if (mode & FWRITE) { 187 1.4 manu if (pnd->pnd_flags & PND_WFH) 188 1.4 manu return pnd->pnd_wfh; 189 1.6 manu } 190 1.4 manu 191 1.4 manu if (mode & FREAD) { 192 1.4 manu if (pnd->pnd_flags & PND_RFH) 193 1.4 manu return pnd->pnd_rfh; 194 1.4 manu 195 1.4 manu if (pnd->pnd_flags & PND_WFH) 196 1.4 manu return pnd->pnd_wfh; 197 1.6 manu 198 1.4 manu } 199 1.1 manu 200 1.4 manu return FUSE_UNKNOWN_FH; 201 1.1 manu } 202 1.1 manu 203 1.19 manu /* ARGSUSED0 */ 204 1.8 manu char * 205 1.19 manu perfuse_node_path(struct perfuse_state *ps, puffs_cookie_t opc) 206 1.8 manu { 207 1.8 manu static char buf[MAXPATHLEN + 1]; 208 1.8 manu 209 1.19 manu #if 0 210 1.19 manu if (node_path(ps, opc, buf, sizeof(buf)) == 0) 211 1.8 manu sprintf(buf, "/"); 212 1.19 manu #endif 213 1.19 manu sprintf(buf, "%s", PERFUSE_NODE_DATA(opc)->pnd_name); 214 1.8 manu 215 1.8 manu return buf; 216 1.8 manu } 217 1.12 manu 218 1.20 manu int 219 1.20 manu perfuse_ns_match(const int attrnamespace, const char *attrname) 220 1.20 manu { 221 1.20 manu const char *system_ns[] = { "system.", "trusted.", "security", NULL }; 222 1.20 manu int i; 223 1.20 manu 224 1.20 manu for (i = 0; system_ns[i]; i++) { 225 1.20 manu if (strncmp(attrname, system_ns[i], strlen(system_ns[i])) == 0) 226 1.20 manu return (attrnamespace == EXTATTR_NAMESPACE_SYSTEM); 227 1.20 manu } 228 1.20 manu 229 1.20 manu return (attrnamespace == EXTATTR_NAMESPACE_USER); 230 1.20 manu } 231 1.20 manu 232 1.12 manu const char * 233 1.17 matt perfuse_native_ns(const int attrnamespace, const char *attrname, 234 1.17 matt char *fuse_attrname) 235 1.12 manu { 236 1.12 manu const struct perfuse_ns_map *pnm; 237 1.12 manu const struct perfuse_ns_map perfuse_ns_map[] = { 238 1.12 manu PERFUSE_NS_MAP("trusted", EXTATTR_NAMESPACE_SYSTEM), 239 1.12 manu PERFUSE_NS_MAP("security", EXTATTR_NAMESPACE_SYSTEM), 240 1.12 manu PERFUSE_NS_MAP("system", EXTATTR_NAMESPACE_SYSTEM), 241 1.12 manu PERFUSE_NS_MAP("user", EXTATTR_NAMESPACE_USER), 242 1.12 manu { NULL, 0, EXTATTR_NAMESPACE_USER }, 243 1.12 manu }; 244 1.12 manu 245 1.12 manu /* 246 1.12 manu * If attribute has a reserved Linux namespace (e.g.: trusted.foo) 247 1.12 manu * and that namespace matches the requested native namespace 248 1.12 manu * we have nothing to do. 249 1.12 manu * Otherwise we have either: 250 1.12 manu * (system|trusted|security).* with user namespace: prepend user. 251 1.12 manu * anything else with system napespace: prepend system. 252 1.12 manu */ 253 1.12 manu for (pnm = perfuse_ns_map; pnm->pnm_ns; pnm++) { 254 1.12 manu if (strncmp(attrname, pnm->pnm_ns, pnm->pnm_nslen) != 0) 255 1.12 manu continue; 256 1.12 manu 257 1.12 manu if (attrnamespace == pnm->pnm_native_ns) 258 1.12 manu return attrname; 259 1.12 manu 260 1.12 manu /* (system|trusted|security).* with user namespace */ 261 1.12 manu if (attrnamespace == EXTATTR_NAMESPACE_USER) { 262 1.12 manu (void)snprintf(fuse_attrname, LINUX_XATTR_NAME_MAX, 263 1.12 manu "user.%s", attrname); 264 1.12 manu return (const char *)fuse_attrname; 265 1.12 manu } 266 1.12 manu } 267 1.12 manu 268 1.12 manu /* anything else with system napespace */ 269 1.12 manu if (attrnamespace == EXTATTR_NAMESPACE_SYSTEM) { 270 1.12 manu (void)snprintf(fuse_attrname, LINUX_XATTR_NAME_MAX, 271 1.12 manu "system.%s", attrname); 272 1.12 manu return (const char *)fuse_attrname; 273 1.12 manu } 274 1.12 manu 275 1.12 manu return (const char *)attrname; 276 1.12 manu } 277 1.19 manu 278 1.19 manu static __inline struct perfuse_node_hashlist * 279 1.19 manu perfuse_nidhash(struct perfuse_state *ps, uint64_t nodeid) 280 1.19 manu { 281 1.19 manu uint32_t hash; 282 1.19 manu 283 1.19 manu hash = hash32_buf(&nodeid, sizeof(nodeid), HASH32_BUF_INIT); 284 1.19 manu 285 1.19 manu return &ps->ps_nidhash[hash % ps->ps_nnidhash]; 286 1.19 manu } 287 1.19 manu 288 1.19 manu struct perfuse_node_data * 289 1.19 manu perfuse_node_bynodeid(struct perfuse_state *ps, uint64_t nodeid) 290 1.19 manu { 291 1.19 manu struct perfuse_node_hashlist *plist; 292 1.19 manu struct perfuse_node_data *pnd; 293 1.19 manu 294 1.19 manu plist = perfuse_nidhash(ps, nodeid); 295 1.19 manu 296 1.19 manu LIST_FOREACH(pnd, plist, pnd_nident) 297 1.19 manu if (pnd->pnd_nodeid == nodeid) 298 1.19 manu break; 299 1.19 manu 300 1.19 manu return pnd; 301 1.19 manu } 302 1.19 manu 303 1.19 manu void 304 1.19 manu perfuse_node_cache(struct perfuse_state *ps, puffs_cookie_t opc) 305 1.19 manu { 306 1.19 manu struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc); 307 1.19 manu struct perfuse_node_hashlist *nidlist; 308 1.19 manu 309 1.19 manu if (pnd->pnd_flags & PND_REMOVED) 310 1.19 manu DERRX(EX_SOFTWARE, "%s: \"%s\" already removed", 311 1.19 manu __func__, pnd->pnd_name); 312 1.19 manu 313 1.19 manu nidlist = perfuse_nidhash(ps, pnd->pnd_nodeid); 314 1.19 manu LIST_INSERT_HEAD(nidlist, pnd, pnd_nident); 315 1.19 manu 316 1.19 manu return; 317 1.19 manu } 318 1.19 manu 319 1.19 manu void 320 1.19 manu perfuse_cache_flush(puffs_cookie_t opc) 321 1.19 manu { 322 1.19 manu struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc); 323 1.19 manu 324 1.19 manu if (pnd->pnd_flags & PND_REMOVED) 325 1.19 manu DERRX(EX_SOFTWARE, "%s: \"%s\" already removed", 326 1.19 manu __func__, pnd->pnd_name); 327 1.19 manu 328 1.19 manu LIST_REMOVE(pnd, pnd_nident); 329 1.19 manu 330 1.19 manu return; 331 1.19 manu } 332