1 /* $NetBSD: subr.c,v 1.10 2010/10/11 05:37:58 manu Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 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(pu, pn) 81 struct puffs_usermount *pu; 82 struct puffs_node *pn; 83 { 84 struct perfuse_node_data *pnd; 85 86 pnd = PERFUSE_NODE_DATA(pn); 87 88 if (pnd->pnd_parent != NULL) { 89 struct perfuse_node_data *parent_pnd; 90 91 parent_pnd = PERFUSE_NODE_DATA(pnd->pnd_parent); 92 TAILQ_REMOVE(&parent_pnd->pnd_children, pnd, pnd_next); 93 } 94 95 if ((pnd = puffs_pn_getpriv(pn)) != NULL) { 96 if (pnd->pnd_parent != NULL) 97 PERFUSE_NODE_DATA(pnd->pnd_parent)->pnd_childcount--; 98 99 if (pnd->pnd_dirent != NULL) 100 free(pnd->pnd_dirent); 101 102 if (pnd->pnd_all_fd != NULL) 103 free(pnd->pnd_all_fd); 104 #ifdef PERFUSE_DEBUG 105 if (pnd->pnd_flags & PND_OPEN) 106 DERRX(EX_SOFTWARE, "%s: file open", __func__); 107 108 if (!TAILQ_EMPTY(&pnd->pnd_pcq)) 109 DERRX(EX_SOFTWARE, "%s: non empty pnd_pcq", __func__); 110 #endif /* PERFUSE_DEBUG */ 111 112 free(pnd); 113 } 114 115 puffs_pn_put(pn); 116 117 return; 118 } 119 120 121 void 122 perfuse_new_fh(opc, fh, mode) 123 puffs_cookie_t opc; 124 uint64_t fh; 125 int mode; 126 { 127 struct perfuse_node_data *pnd; 128 129 pnd = PERFUSE_NODE_DATA(opc); 130 131 if (mode & FWRITE) { 132 if (pnd->pnd_flags & PND_WFH) 133 DERRX(EX_SOFTWARE, "%s: opc = %p, write fh already set", 134 __func__, (void *)opc); 135 pnd->pnd_wfh = fh; 136 pnd->pnd_flags |= PND_WFH; 137 } 138 139 if (mode & FREAD) { 140 if (pnd->pnd_flags & PND_RFH) 141 DERRX(EX_SOFTWARE, "%s: opc = %p, read fh already set", 142 __func__, (void *)opc); 143 pnd->pnd_rfh = fh; 144 pnd->pnd_flags |= PND_RFH; 145 } 146 147 return; 148 } 149 150 void 151 perfuse_destroy_fh(opc, fh) 152 puffs_cookie_t opc; 153 uint64_t fh; 154 { 155 struct perfuse_node_data *pnd; 156 157 pnd = PERFUSE_NODE_DATA(opc); 158 159 if (fh == pnd->pnd_rfh) { 160 if (!(pnd->pnd_flags & PND_RFH) && (fh != FUSE_UNKNOWN_FH)) 161 DERRX(EX_SOFTWARE, 162 "%s: opc = %p, unset rfh = %"PRIx64"", 163 __func__, (void *)opc, fh); 164 pnd->pnd_rfh = FUSE_UNKNOWN_FH; 165 pnd->pnd_flags &= ~PND_RFH; 166 } 167 168 if (fh == pnd->pnd_wfh) { 169 if (!(pnd->pnd_flags & PND_WFH) && (fh != FUSE_UNKNOWN_FH)) 170 DERRX(EX_SOFTWARE, 171 "%s: opc = %p, unset wfh = %"PRIx64"", 172 __func__, (void *)opc, fh); 173 pnd->pnd_wfh = FUSE_UNKNOWN_FH; 174 pnd->pnd_flags &= ~PND_WFH; 175 } 176 177 return; 178 } 179 180 uint64_t 181 perfuse_get_fh(opc, mode) 182 puffs_cookie_t opc; 183 int mode; 184 { 185 struct perfuse_node_data *pnd; 186 187 pnd = PERFUSE_NODE_DATA(opc); 188 189 if (mode & FWRITE) { 190 if (pnd->pnd_flags & PND_WFH) 191 return pnd->pnd_wfh; 192 } 193 194 if (mode & FREAD) { 195 if (pnd->pnd_flags & PND_RFH) 196 return pnd->pnd_rfh; 197 198 if (pnd->pnd_flags & PND_WFH) 199 return pnd->pnd_wfh; 200 201 } 202 203 return FUSE_UNKNOWN_FH; 204 } 205 206 static size_t 207 node_path(opc, buf, buflen) 208 puffs_cookie_t opc; 209 char *buf; 210 size_t buflen; 211 { 212 struct perfuse_node_data *pnd; 213 size_t written; 214 215 pnd = PERFUSE_NODE_DATA(opc); 216 if (pnd->pnd_parent == opc) 217 return 0; 218 219 written = node_path(pnd->pnd_parent, buf, buflen); 220 buf += written; 221 buflen -= written; 222 223 return written + snprintf(buf, buflen, "/%s", pnd->pnd_name); 224 } 225 226 char * 227 perfuse_node_path(opc) 228 puffs_cookie_t opc; 229 { 230 static char buf[MAXPATHLEN + 1]; 231 232 if (node_path(opc, buf, sizeof(buf)) == 0) 233 sprintf(buf, "/"); 234 235 return buf; 236 } 237