1 /* $NetBSD: subr.c,v 1.11 2011/04/25 04:54:53 manu Exp $ */ 2 3 /*- 4 * Copyright (c) 2010-2011 Emmanuel Dreyfus. 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <err.h> 31 #include <errno.h> 32 #include <sysexits.h> 33 #include <syslog.h> 34 #include <puffs.h> 35 #include <paths.h> 36 37 #include "perfuse_priv.h" 38 39 static size_t node_path(puffs_cookie_t, char *, size_t); 40 41 struct puffs_node * 42 perfuse_new_pn(pu, name, parent) 43 struct puffs_usermount *pu; 44 const char *name; 45 struct puffs_node *parent; 46 { 47 struct puffs_node *pn; 48 struct perfuse_node_data *pnd; 49 50 if ((pnd = malloc(sizeof(*pnd))) == NULL) 51 DERR(EX_OSERR, "malloc failed"); 52 53 if ((pn = puffs_pn_new(pu, pnd)) == NULL) 54 DERR(EX_SOFTWARE, "puffs_pn_new failed"); 55 56 (void)memset(pnd, 0, sizeof(*pnd)); 57 pnd->pnd_rfh = FUSE_UNKNOWN_FH; 58 pnd->pnd_wfh = FUSE_UNKNOWN_FH; 59 pnd->pnd_ino = PERFUSE_UNKNOWN_INO; 60 pnd->pnd_nlookup = 1; 61 pnd->pnd_parent = parent; 62 pnd->pnd_pn = (puffs_cookie_t)pn; 63 (void)strlcpy(pnd->pnd_name, name, MAXPATHLEN); 64 TAILQ_INIT(&pnd->pnd_pcq); 65 TAILQ_INIT(&pnd->pnd_children); 66 67 if (parent != NULL) { 68 struct perfuse_node_data *parent_pnd; 69 70 parent_pnd = PERFUSE_NODE_DATA(parent); 71 TAILQ_INSERT_TAIL(&parent_pnd->pnd_children, pnd, pnd_next); 72 73 parent_pnd->pnd_childcount++; 74 } 75 76 return pn; 77 } 78 79 void 80 perfuse_destroy_pn(pn) 81 struct puffs_node *pn; 82 { 83 struct perfuse_node_data *pnd; 84 85 pnd = PERFUSE_NODE_DATA(pn); 86 87 if (pnd->pnd_parent != NULL) { 88 struct perfuse_node_data *parent_pnd; 89 90 parent_pnd = PERFUSE_NODE_DATA(pnd->pnd_parent); 91 TAILQ_REMOVE(&parent_pnd->pnd_children, pnd, pnd_next); 92 } 93 94 if ((pnd = puffs_pn_getpriv(pn)) != NULL) { 95 if (pnd->pnd_parent != NULL) 96 PERFUSE_NODE_DATA(pnd->pnd_parent)->pnd_childcount--; 97 98 if (pnd->pnd_dirent != NULL) 99 free(pnd->pnd_dirent); 100 101 if (pnd->pnd_all_fd != NULL) 102 free(pnd->pnd_all_fd); 103 #ifdef PERFUSE_DEBUG 104 if (pnd->pnd_flags & PND_OPEN) 105 DERRX(EX_SOFTWARE, "%s: file open", __func__); 106 107 if (!TAILQ_EMPTY(&pnd->pnd_pcq)) 108 DERRX(EX_SOFTWARE, "%s: non empty pnd_pcq", __func__); 109 #endif /* PERFUSE_DEBUG */ 110 111 free(pnd); 112 } 113 114 puffs_pn_put(pn); 115 116 return; 117 } 118 119 120 void 121 perfuse_new_fh(opc, fh, mode) 122 puffs_cookie_t opc; 123 uint64_t fh; 124 int mode; 125 { 126 struct perfuse_node_data *pnd; 127 128 pnd = PERFUSE_NODE_DATA(opc); 129 130 if (mode & FWRITE) { 131 if (pnd->pnd_flags & PND_WFH) 132 DERRX(EX_SOFTWARE, "%s: opc = %p, write fh already set", 133 __func__, (void *)opc); 134 pnd->pnd_wfh = fh; 135 pnd->pnd_flags |= PND_WFH; 136 } 137 138 if (mode & FREAD) { 139 if (pnd->pnd_flags & PND_RFH) 140 DERRX(EX_SOFTWARE, "%s: opc = %p, read fh already set", 141 __func__, (void *)opc); 142 pnd->pnd_rfh = fh; 143 pnd->pnd_flags |= PND_RFH; 144 } 145 146 return; 147 } 148 149 void 150 perfuse_destroy_fh(opc, fh) 151 puffs_cookie_t opc; 152 uint64_t fh; 153 { 154 struct perfuse_node_data *pnd; 155 156 pnd = PERFUSE_NODE_DATA(opc); 157 158 if (fh == pnd->pnd_rfh) { 159 if (!(pnd->pnd_flags & PND_RFH) && (fh != FUSE_UNKNOWN_FH)) 160 DERRX(EX_SOFTWARE, 161 "%s: opc = %p, unset rfh = %"PRIx64"", 162 __func__, (void *)opc, fh); 163 pnd->pnd_rfh = FUSE_UNKNOWN_FH; 164 pnd->pnd_flags &= ~PND_RFH; 165 } 166 167 if (fh == pnd->pnd_wfh) { 168 if (!(pnd->pnd_flags & PND_WFH) && (fh != FUSE_UNKNOWN_FH)) 169 DERRX(EX_SOFTWARE, 170 "%s: opc = %p, unset wfh = %"PRIx64"", 171 __func__, (void *)opc, fh); 172 pnd->pnd_wfh = FUSE_UNKNOWN_FH; 173 pnd->pnd_flags &= ~PND_WFH; 174 } 175 176 return; 177 } 178 179 uint64_t 180 perfuse_get_fh(opc, mode) 181 puffs_cookie_t opc; 182 int mode; 183 { 184 struct perfuse_node_data *pnd; 185 186 pnd = PERFUSE_NODE_DATA(opc); 187 188 if (mode & FWRITE) { 189 if (pnd->pnd_flags & PND_WFH) 190 return pnd->pnd_wfh; 191 } 192 193 if (mode & FREAD) { 194 if (pnd->pnd_flags & PND_RFH) 195 return pnd->pnd_rfh; 196 197 if (pnd->pnd_flags & PND_WFH) 198 return pnd->pnd_wfh; 199 200 } 201 202 return FUSE_UNKNOWN_FH; 203 } 204 205 static size_t 206 node_path(opc, buf, buflen) 207 puffs_cookie_t opc; 208 char *buf; 209 size_t buflen; 210 { 211 struct perfuse_node_data *pnd; 212 size_t written; 213 214 pnd = PERFUSE_NODE_DATA(opc); 215 if (pnd->pnd_parent == opc) 216 return 0; 217 218 written = node_path(pnd->pnd_parent, buf, buflen); 219 buf += written; 220 buflen -= written; 221 222 return written + snprintf(buf, buflen, "/%s", pnd->pnd_name); 223 } 224 225 char * 226 perfuse_node_path(opc) 227 puffs_cookie_t opc; 228 { 229 static char buf[MAXPATHLEN + 1]; 230 231 if (node_path(opc, buf, sizeof(buf)) == 0) 232 sprintf(buf, "/"); 233 234 return buf; 235 } 236