1*1f45a5acShelg /* $OpenBSD: fuse_subr.c,v 1.12 2018/05/21 11:47:46 helg Exp $ */
275af46c2Stedu /*
375af46c2Stedu * Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com>
475af46c2Stedu *
575af46c2Stedu * Permission to use, copy, modify, and distribute this software for any
675af46c2Stedu * purpose with or without fee is hereby granted, provided that the above
775af46c2Stedu * copyright notice and this permission notice appear in all copies.
875af46c2Stedu *
975af46c2Stedu * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1075af46c2Stedu * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1175af46c2Stedu * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1275af46c2Stedu * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1375af46c2Stedu * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1475af46c2Stedu * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1575af46c2Stedu * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1675af46c2Stedu */
1775af46c2Stedu
1875af46c2Stedu #include <errno.h>
1975af46c2Stedu #include <stdlib.h>
2075af46c2Stedu #include <string.h>
2175af46c2Stedu #include <unistd.h>
2275af46c2Stedu
2375af46c2Stedu #include "fuse_private.h"
2475af46c2Stedu #include "debug.h"
2575af46c2Stedu
2675af46c2Stedu struct fuse_vnode *
alloc_vn(struct fuse * f,const char * path,ino_t ino,ino_t pino)275e69e0b6Snatano alloc_vn(struct fuse *f, const char *path, ino_t ino, ino_t pino)
2875af46c2Stedu {
2975af46c2Stedu struct fuse_vnode *vn;
3075af46c2Stedu
3175af46c2Stedu if ((vn = malloc(sizeof(*vn))) == NULL) {
32ddbf7910Ssyl DPERROR(__func__);
3375af46c2Stedu return (NULL);
3475af46c2Stedu }
3575af46c2Stedu
3675af46c2Stedu vn->ino = ino;
375e69e0b6Snatano vn->ref = 1;
38ddbf7910Ssyl if (strlcpy(vn->path, path, sizeof(vn->path)) >= sizeof(vn->path)) {
39ddbf7910Ssyl DPRINTF("%s: strlcpy name too long\n", __func__);
40ddbf7910Ssyl free(vn);
41ddbf7910Ssyl return (NULL);
42ddbf7910Ssyl }
43ddbf7910Ssyl
445e69e0b6Snatano if (pino == (ino_t)0)
455e69e0b6Snatano vn->parent = NULL;
465e69e0b6Snatano else {
475e69e0b6Snatano if ((vn->parent = tree_get(&f->vnode_tree, pino)) == NULL) {
485e69e0b6Snatano DPRINTF("%s: parent vnode %llu not in the vnode tree\n",
495e69e0b6Snatano __func__, pino);
505e69e0b6Snatano free(vn);
515e69e0b6Snatano errno = ENOENT;
525e69e0b6Snatano return (NULL);
535e69e0b6Snatano }
545e69e0b6Snatano ref_vn(vn->parent);
555e69e0b6Snatano }
565e69e0b6Snatano
5775af46c2Stedu if (ino == (ino_t)-1) {
5875af46c2Stedu f->max_ino++;
5975af46c2Stedu vn->ino = f->max_ino;
60*1f45a5acShelg DPRINTF("New Inode: %llu\t", (unsigned long long)vn->ino);
6175af46c2Stedu }
6275af46c2Stedu
6375af46c2Stedu return (vn);
6475af46c2Stedu }
6575af46c2Stedu
665e69e0b6Snatano void
ref_vn(struct fuse_vnode * vn)675e69e0b6Snatano ref_vn(struct fuse_vnode *vn)
685e69e0b6Snatano {
695e69e0b6Snatano vn->ref++;
705e69e0b6Snatano }
715e69e0b6Snatano
725e69e0b6Snatano void
unref_vn(struct fuse * f,struct fuse_vnode * vn)735e69e0b6Snatano unref_vn(struct fuse *f, struct fuse_vnode *vn)
745e69e0b6Snatano {
755e69e0b6Snatano if (--vn->ref == 0) {
765e69e0b6Snatano tree_pop(&f->vnode_tree, vn->ino);
775e69e0b6Snatano remove_vnode_from_name_tree(f, vn);
785e69e0b6Snatano if (vn->parent != NULL)
795e69e0b6Snatano unref_vn(f, vn->parent);
805e69e0b6Snatano free(vn);
815e69e0b6Snatano }
825e69e0b6Snatano }
835e69e0b6Snatano
8475af46c2Stedu int
set_vn(struct fuse * f,struct fuse_vnode * v)8575af46c2Stedu set_vn(struct fuse *f, struct fuse_vnode *v)
8675af46c2Stedu {
8775af46c2Stedu struct fuse_vn_head *vn_head;
8875af46c2Stedu struct fuse_vnode *vn;
8975af46c2Stedu
9075af46c2Stedu if (tree_set(&f->vnode_tree, v->ino, v) == NULL)
9175af46c2Stedu return (0);
9275af46c2Stedu
9375af46c2Stedu if (!dict_check(&f->name_tree, v->path)) {
9475af46c2Stedu vn_head = malloc(sizeof(*vn_head));
9575af46c2Stedu if (vn_head == NULL)
9675af46c2Stedu return (0);
9775af46c2Stedu SIMPLEQ_INIT(vn_head);
9875af46c2Stedu } else {
9975af46c2Stedu vn_head = dict_get(&f->name_tree, v->path);
10075af46c2Stedu if (vn_head == NULL)
10175af46c2Stedu return (0);
10275af46c2Stedu }
10375af46c2Stedu
10475af46c2Stedu SIMPLEQ_FOREACH(vn, vn_head, node) {
10575af46c2Stedu if (v->parent == vn->parent && v->ino == vn->ino)
10675af46c2Stedu return (1);
10775af46c2Stedu }
10875af46c2Stedu
10975af46c2Stedu SIMPLEQ_INSERT_TAIL(vn_head, v, node);
11075af46c2Stedu dict_set(&f->name_tree, v->path, vn_head);
11175af46c2Stedu
11275af46c2Stedu return (1);
11375af46c2Stedu }
11475af46c2Stedu
1150e0c4c5cSsyl void
remove_vnode_from_name_tree(struct fuse * f,struct fuse_vnode * vn)1160e0c4c5cSsyl remove_vnode_from_name_tree(struct fuse *f, struct fuse_vnode *vn)
1170e0c4c5cSsyl {
1180e0c4c5cSsyl struct fuse_vn_head *vn_head;
1190e0c4c5cSsyl struct fuse_vnode *v;
1200e0c4c5cSsyl struct fuse_vnode *lastv;
1210e0c4c5cSsyl
1220e0c4c5cSsyl vn_head = dict_get(&f->name_tree, vn->path);
1230e0c4c5cSsyl if (vn_head == NULL)
1240e0c4c5cSsyl return;
1250e0c4c5cSsyl
1260e0c4c5cSsyl lastv = NULL;
1270e0c4c5cSsyl SIMPLEQ_FOREACH(v, vn_head, node) {
1280e0c4c5cSsyl if (v->parent == vn->parent)
1290e0c4c5cSsyl break;
1300e0c4c5cSsyl
1310e0c4c5cSsyl lastv = v;
1320e0c4c5cSsyl }
1330e0c4c5cSsyl if (v == NULL)
1340e0c4c5cSsyl return;
1350e0c4c5cSsyl
1360e0c4c5cSsyl /* if we found the vnode remove it */
1370e0c4c5cSsyl if (v == SIMPLEQ_FIRST(vn_head))
1380e0c4c5cSsyl SIMPLEQ_REMOVE_HEAD(vn_head, node);
1390e0c4c5cSsyl else
1400e0c4c5cSsyl SIMPLEQ_REMOVE_AFTER(vn_head, lastv, node);
1410e0c4c5cSsyl
1420e0c4c5cSsyl /* if the queue is empty we need to remove it from the dict */
1430e0c4c5cSsyl if (SIMPLEQ_EMPTY(vn_head)) {
1440e0c4c5cSsyl vn_head = dict_pop(&f->name_tree, vn->path);
1450e0c4c5cSsyl free(vn_head);
1460e0c4c5cSsyl }
1470e0c4c5cSsyl }
1480e0c4c5cSsyl
14975af46c2Stedu struct fuse_vnode *
get_vn_by_name_and_parent(struct fuse * f,uint8_t * xpath,ino_t pino)1505e69e0b6Snatano get_vn_by_name_and_parent(struct fuse *f, uint8_t *xpath, ino_t pino)
15175af46c2Stedu {
15275af46c2Stedu struct fuse_vn_head *vn_head;
15375af46c2Stedu struct fuse_vnode *v = NULL;
154dedc9797Ssyl const char *path = (const char *)xpath;
15575af46c2Stedu
15675af46c2Stedu vn_head = dict_get(&f->name_tree, path);
15775af46c2Stedu
15875af46c2Stedu if (vn_head == NULL)
15977cffba6Ssyl goto fail;
16075af46c2Stedu
16175af46c2Stedu SIMPLEQ_FOREACH(v, vn_head, node)
1625e69e0b6Snatano if (v->parent && v->parent->ino == pino)
16375af46c2Stedu return (v);
16475af46c2Stedu
16577cffba6Ssyl fail:
16677cffba6Ssyl errno = ENOENT;
16775af46c2Stedu return (NULL);
16875af46c2Stedu }
16975af46c2Stedu
17075af46c2Stedu char *
build_realname(struct fuse * f,ino_t ino)17175af46c2Stedu build_realname(struct fuse *f, ino_t ino)
17275af46c2Stedu {
17375af46c2Stedu struct fuse_vnode *vn;
174cec0f43fSokan char *name;
17575af46c2Stedu char *tmp = NULL;
176c39b94d2Sreyk int firstshot = 0, ret;
17775af46c2Stedu
178cec0f43fSokan name = strdup("/");
179cec0f43fSokan if (name == NULL)
180cec0f43fSokan return (NULL);
181cec0f43fSokan
18275af46c2Stedu vn = tree_get(&f->vnode_tree, ino);
18375af46c2Stedu if (!vn || !name) {
18475af46c2Stedu free(name);
18575af46c2Stedu return (NULL);
18675af46c2Stedu }
18775af46c2Stedu
1885e69e0b6Snatano while (vn->parent != NULL) {
18975af46c2Stedu if (firstshot++)
190c39b94d2Sreyk ret = asprintf(&tmp, "/%s%s", vn->path, name);
19175af46c2Stedu else
192c39b94d2Sreyk ret = asprintf(&tmp, "/%s", vn->path);
19375af46c2Stedu
194c39b94d2Sreyk if (ret == -1) {
19575af46c2Stedu free(name);
19675af46c2Stedu return (NULL);
19775af46c2Stedu }
19875af46c2Stedu
19975af46c2Stedu free(name);
20075af46c2Stedu name = tmp;
20175af46c2Stedu tmp = NULL;
2025e69e0b6Snatano vn = vn->parent;
20375af46c2Stedu }
20475af46c2Stedu
20575af46c2Stedu if (ino == (ino_t)0)
206*1f45a5acShelg DPRINTF("%s: NULL ino\t", __func__);
20775af46c2Stedu
208*1f45a5acShelg DPRINTF("%s", name);
20975af46c2Stedu return (name);
21075af46c2Stedu }
211