103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland/*
203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * Copyright (C) 2010 The Android Open Source Project
303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland *
403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * Licensed under the Apache License, Version 2.0 (the "License");
503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * you may not use this file except in compliance with the License.
603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * You may obtain a copy of the License at
703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland *
803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland *      http://www.apache.org/licenses/LICENSE-2.0
903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland *
1003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * Unless required by applicable law or agreed to in writing, software
1103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * distributed under the License is distributed on an "AS IS" BASIS,
1203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * See the License for the specific language governing permissions and
1403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * limitations under the License.
1503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland */
1603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
1703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include <stdio.h>
1803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include <stdlib.h>
1903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include <string.h>
2003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include <unistd.h>
2103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include <errno.h>
2203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include <fcntl.h>
2303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include <sys/mount.h>
2403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include <sys/stat.h>
254553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood#include <sys/statfs.h>
2603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include <sys/uio.h>
2703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include <dirent.h>
287729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown#include <limits.h>
291bedb73f9fc239b69d958cbabc50c7ba382bacbcMike Lockwood#include <ctype.h>
306249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown#include <pthread.h>
3103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
32b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland#include <private/android_filesystem_config.h>
33b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland
3403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include "fuse.h"
3503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
3603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland/* README
3703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland *
3803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * What is this?
3903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland *
4003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * sdcard is a program that uses FUSE to emulate FAT-on-sdcard style
4103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * directory permissions (all files are given fixed owner, group, and
4203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * permissions at creation, owner, group, and permissions are not
4303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * changeable, symlinks and hardlinks are not createable, etc.
4403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland *
45e169bd05ec70f68c0db5e61c93b71e1746eb6c56Jeff Sharkey * See usage() for command line options.
4603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland *
47e169bd05ec70f68c0db5e61c93b71e1746eb6c56Jeff Sharkey * It must be run as root, but will drop to requested UID/GID as soon as it
48e169bd05ec70f68c0db5e61c93b71e1746eb6c56Jeff Sharkey * mounts a filesystem.  It will refuse to run if requested UID/GID are zero.
4903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland *
5003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * Things I believe to be true:
5103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland *
5203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * - ops that return a fuse_entry (LOOKUP, MKNOD, MKDIR, LINK, SYMLINK,
5303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * CREAT) must bump that node's refcount
5403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * - don't forget that FORGET can forget multiple references (req->nlookup)
5503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * - if an op that returns a fuse_entry fails writing the reply to the
5603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * kernel, you must rollback the refcount to reflect the reference the
5703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * kernel did not actually acquire
5803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland */
5903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
6003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#define FUSE_TRACE 0
6103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
6203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#if FUSE_TRACE
6303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#define TRACE(x...) fprintf(stderr,x)
6403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#else
6503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#define TRACE(x...) do {} while (0)
6603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#endif
6703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
6803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#define ERROR(x...) fprintf(stderr,x)
6903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
7003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#define FUSE_UNKNOWN_INO 0xffffffff
7103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
72847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown/* Maximum number of bytes to write in one request. */
73847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown#define MAX_WRITE (256 * 1024)
74847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown
75847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown/* Maximum number of bytes to read in one request. */
76847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown#define MAX_READ (128 * 1024)
77847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown
78847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown/* Largest possible request.
79847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown * The request size is bounded by the maximum size of a FUSE_WRITE request because it has
80847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown * the largest possible data payload. */
81847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown#define MAX_REQUEST_SIZE (sizeof(struct fuse_in_header) + sizeof(struct fuse_write_in) + MAX_WRITE)
82847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown
836249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown/* Default number of threads. */
846249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown#define DEFAULT_NUM_THREADS 2
856249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
866249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown/* Pseudo-error constant used to indicate that no fuse status is needed
876249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown * or that a reply has already been written. */
886249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown#define NO_STATUS 1
896249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
9003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct handle {
9103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    int fd;
9203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland};
9303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
9403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct dirhandle {
9503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    DIR *d;
9603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland};
9703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
9803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct node {
996249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    __u32 refcount;
10003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    __u64 nid;
10103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    __u64 gen;
10203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
10311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham    struct node *next;          /* per-dir sibling list */
10411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham    struct node *child;         /* first contained file by this dir */
10511ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham    struct node *parent;        /* containing directory */
10603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
1076249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    size_t namelen;
10811ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham    char *name;
109575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood    /* If non-null, this is the real name of the file in the underlying storage.
110575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood     * This may differ from the field "name" only by case.
111575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood     * strlen(actual_name) will always equal strlen(name), so it is safe to use
112575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood     * namelen for both fields.
113575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood     */
114575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood    char *actual_name;
11503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland};
11603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
1177729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown/* Global data structure shared by all fuse handlers. */
11803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct fuse {
1196249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    pthread_mutex_t lock;
12003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
1216249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    __u64 next_generation;
12203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    int fd;
12303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    struct node root;
1247729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown    char rootpath[PATH_MAX];
12503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland};
12603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
1277729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown/* Private data used by a single fuse handler. */
1287729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brownstruct fuse_handler {
1296249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    struct fuse* fuse;
1306249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    int token;
1316249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
1327729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown    /* To save memory, we never use the contents of the request buffer and the read
1337729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown     * buffer at the same time.  This allows us to share the underlying storage. */
1347729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown    union {
1357729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown        __u8 request_buffer[MAX_REQUEST_SIZE];
1367729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown        __u8 read_buffer[MAX_READ];
1377729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown    };
1387729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown};
13903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
1406249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic inline void *id_to_ptr(__u64 nid)
1416249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown{
1426249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    return (void *) (uintptr_t) nid;
1436249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown}
144b94d320b1e7e2a3493147f6763cd2825b111a4d8Mike Lockwood
1456249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic inline __u64 ptr_to_id(void *ptr)
1466249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown{
1476249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    return (__u64) (uintptr_t) ptr;
1486249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown}
1496249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
1506249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic void acquire_node_locked(struct node* node)
1516249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown{
1526249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    node->refcount++;
1536249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    TRACE("ACQUIRE %p (%s) rc=%d\n", node, node->name, node->refcount);
1546249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown}
1556249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
1566249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic void remove_node_from_parent_locked(struct node* node);
1576249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
1586249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic void release_node_locked(struct node* node)
1596249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown{
1606249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    TRACE("RELEASE %p (%s) rc=%d\n", node, node->name, node->refcount);
1616249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (node->refcount > 0) {
1626249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        node->refcount--;
1636249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        if (!node->refcount) {
1646249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            TRACE("DESTROY %p (%s)\n", node, node->name);
1656249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            remove_node_from_parent_locked(node);
1666249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
1676249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown                /* TODO: remove debugging - poison memory */
1686249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            memset(node->name, 0xef, node->namelen);
1696249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            free(node->name);
1706249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            free(node->actual_name);
1716249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            memset(node, 0xfc, sizeof(*node));
1726249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            free(node);
1736249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        }
1746249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    } else {
1756249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        ERROR("Zero refcnt %p\n", node);
1766249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    }
1776249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown}
1786249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
1796249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic void add_node_to_parent_locked(struct node *node, struct node *parent) {
1806249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    node->parent = parent;
1816249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    node->next = parent->child;
1826249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    parent->child = node;
1836249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    acquire_node_locked(parent);
1846249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown}
1856249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
1866249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic void remove_node_from_parent_locked(struct node* node)
1876249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown{
1886249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (node->parent) {
1896249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        if (node->parent->child == node) {
1906249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            node->parent->child = node->parent->child->next;
1916249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        } else {
1926249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            struct node *node2;
1936249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            node2 = node->parent->child;
1946249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            while (node2->next != node)
1956249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown                node2 = node2->next;
1966249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            node2->next = node->next;
1976249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        }
1986249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        release_node_locked(node->parent);
1996249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        node->parent = NULL;
2006249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        node->next = NULL;
2016249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    }
2026249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown}
2036249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
2046249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown/* Gets the absolute path to a node into the provided buffer.
2056249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown *
2066249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown * Populates 'buf' with the path and returns the length of the path on success,
2076249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown * or returns -1 if the path is too long for the provided buffer.
208f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham */
2096249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic ssize_t get_node_path_locked(struct node* node, char* buf, size_t bufsize)
21003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
2116249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    size_t namelen = node->namelen;
2126249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (bufsize < namelen + 1) {
2136249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        return -1;
2146249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    }
2156249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
2166249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    ssize_t pathlen = 0;
2176249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (node->parent) {
2186249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        pathlen = get_node_path_locked(node->parent, buf, bufsize - namelen - 2);
2196249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        if (pathlen < 0) {
2206249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            return -1;
221575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood        }
2226249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        buf[pathlen++] = '/';
22303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    }
22403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
2256249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    const char* name = node->actual_name ? node->actual_name : node->name;
2266249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    memcpy(buf + pathlen, name, namelen + 1); /* include trailing \0 */
2276249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    return pathlen + namelen;
2286249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown}
2296249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
2306249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown/* Finds the absolute path of a file within a given directory.
2316249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown * Performs a case-insensitive search for the file and sets the buffer to the path
2326249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown * of the first matching file.  If 'search' is zero or if no match is found, sets
2336249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown * the buffer to the path that the file would have, assuming the name were case-sensitive.
2346249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown *
2356249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown * Populates 'buf' with the path and returns the actual name (within 'buf') on success,
2366249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown * or returns NULL if the path is too long for the provided buffer.
2376249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown */
2386249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic char* find_file_within(const char* path, const char* name,
2396249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        char* buf, size_t bufsize, int search)
2406249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown{
2416249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    size_t pathlen = strlen(path);
2426249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    size_t namelen = strlen(name);
2436249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    size_t childlen = pathlen + namelen + 1;
2446249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    char* actual;
2456249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
2466249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (bufsize <= childlen) {
2476249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        return NULL;
2486249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    }
2496249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
2506249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    memcpy(buf, path, pathlen);
2516249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    buf[pathlen] = '/';
2526249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    actual = buf + pathlen + 1;
2536249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    memcpy(actual, name, namelen + 1);
2546249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
2556249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (search && access(buf, F_OK)) {
256575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood        struct dirent* entry;
2576249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        DIR* dir = opendir(path);
258575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood        if (!dir) {
259575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood            ERROR("opendir %s failed: %s", path, strerror(errno));
2606249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            return actual;
261575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood        }
262575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood        while ((entry = readdir(dir))) {
2636249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            if (!strcasecmp(entry->d_name, name)) {
2646249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown                /* we have a match - replace the name, don't need to copy the null again */
2656249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown                memcpy(actual, entry->d_name, namelen);
266575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood                break;
267575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood            }
268575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood        }
269575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood        closedir(dir);
270575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood    }
2716249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    return actual;
272575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood}
273575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood
2746249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic void attr_from_stat(struct fuse_attr *attr, const struct stat *s, __u64 nid)
275575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood{
2766249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    attr->ino = nid;
27703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    attr->size = s->st_size;
27803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    attr->blocks = s->st_blocks;
2794553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood    attr->atime = s->st_atime;
2804553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood    attr->mtime = s->st_mtime;
2814553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood    attr->ctime = s->st_ctime;
2824553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood    attr->atimensec = s->st_atime_nsec;
2834553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood    attr->mtimensec = s->st_mtime_nsec;
2844553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood    attr->ctimensec = s->st_ctime_nsec;
28503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    attr->mode = s->st_mode;
28603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    attr->nlink = s->st_nlink;
28703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
288b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland        /* force permissions to something reasonable:
289b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland         * world readable
290b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland         * writable by the sdcard group
291b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland         */
292b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland    if (attr->mode & 0100) {
293b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland        attr->mode = (attr->mode & (~0777)) | 0775;
294b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland    } else {
295b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland        attr->mode = (attr->mode & (~0777)) | 0664;
296b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland    }
297b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland
298b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland        /* all files owned by root.sdcard */
299b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland    attr->uid = 0;
300b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland    attr->gid = AID_SDCARD_RW;
30103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}
30203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
3036249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstruct node *create_node_locked(struct fuse* fuse,
3046249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        struct node *parent, const char *name, const char* actual_name)
30503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
30603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    struct node *node;
3076249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    size_t namelen = strlen(name);
30803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
30911ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham    node = calloc(1, sizeof(struct node));
3106249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (!node) {
3116249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        return NULL;
31203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    }
31311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham    node->name = malloc(namelen + 1);
3146249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (!node->name) {
31511ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham        free(node);
3166249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        return NULL;
31711ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham    }
31803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    memcpy(node->name, name, namelen + 1);
3196249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (strcmp(name, actual_name)) {
3206249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        node->actual_name = malloc(namelen + 1);
3216249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        if (!node->actual_name) {
3226249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            free(node->name);
3236249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            free(node);
3246249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            return NULL;
3256249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        }
3266249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        memcpy(node->actual_name, actual_name, namelen + 1);
3276249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    }
32803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    node->namelen = namelen;
3296249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    node->nid = ptr_to_id(node);
3306249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    node->gen = fuse->next_generation++;
3316249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    acquire_node_locked(node);
3326249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    add_node_to_parent_locked(node, parent);
33303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    return node;
33403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}
33503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
3366249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic int rename_node_locked(struct node *node, const char *name,
3376249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        const char* actual_name)
33811ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham{
3396249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    size_t namelen = strlen(name);
3406249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    int need_actual_name = strcmp(name, actual_name);
3416249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown
3426249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    /* make the storage bigger without actually changing the name
3436249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown     * in case an error occurs part way */
3446249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (namelen > node->namelen) {
3456249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        char* new_name = realloc(node->name, namelen + 1);
3466249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        if (!new_name) {
3476249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            return -ENOMEM;
3486249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        }
3496249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        node->name = new_name;
3506249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        if (need_actual_name && node->actual_name) {
3516249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            char* new_actual_name = realloc(node->actual_name, namelen + 1);
3526249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            if (!new_actual_name) {
3536249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown                return -ENOMEM;
3546249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            }
3556249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            node->actual_name = new_actual_name;
3566249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        }
3576249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    }
35803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
3596249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    /* update the name, taking care to allocate storage before overwriting the old name */
3606249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (need_actual_name) {
3616249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        if (!node->actual_name) {
3626249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            node->actual_name = malloc(namelen + 1);
3636249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            if (!node->actual_name) {
3646249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown                return -ENOMEM;
3656249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown            }
3666249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        }
3676249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        memcpy(node->actual_name, actual_name, namelen + 1);
3686249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    } else {
3696249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        free(node->actual_name);
3706249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        node->actual_name = NULL;
3716249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    }
3726249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    memcpy(node->name, name, namelen + 1);
3736249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    node->namelen = namelen;
3746249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    return 0;
37503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}
37603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
3776249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic struct node *lookup_node_by_id_locked(struct fuse *fuse, __u64 nid)
37803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
3796249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (nid == FUSE_ROOT_ID) {
38003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland        return &fuse->root;
38103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    } else {
38203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland        return id_to_ptr(nid);
38303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    }
38403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}
38503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
3866249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic struct node* lookup_node_and_path_by_id_locked(struct fuse* fuse, __u64 nid,
3876249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        char* buf, size_t bufsize)
38803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
3896249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    struct node* node = lookup_node_by_id_locked(fuse, nid);
3906249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (node && get_node_path_locked(node, buf, bufsize) < 0) {
3916249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        node = NULL;
39203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    }
3936249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    return node;
39403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}
39503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
3966249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic struct node *lookup_child_by_name_locked(struct node *node, const char *name)
39703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
39803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    for (node = node->child; node; node = node->next) {
3996249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        /* use exact string comparison, nodes that differ by case
4006249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown         * must be considered distinct even if they refer to the same
4016249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown         * underlying file as otherwise operations such as "mv x x"
4026249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown         * will not work because the source and target nodes are the same. */
4036249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        if (!strcmp(name, node->name)) {
40411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham            return node;
40511ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham        }
40611ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham    }
40711ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham    return 0;
40811ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham}
40911ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham
4106249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic struct node* acquire_or_create_child_locked(
4116249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        struct fuse* fuse, struct node* parent,
4126249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        const char* name, const char* actual_name)
41303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
4146249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    struct node* child = lookup_child_by_name_locked(parent, name);
4156249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (child) {
4166249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        acquire_node_locked(child);
4176249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    } else {
4186249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        child = create_node_locked(fuse, parent, name, actual_name);
41903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    }
4206249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    return child;
42103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}
42203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
423e169bd05ec70f68c0db5e61c93b71e1746eb6c56Jeff Sharkeystatic void fuse_init(struct fuse *fuse, int fd, const char *source_path)
42403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
4256249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    pthread_mutex_init(&fuse->lock, NULL);
42603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
4276249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    fuse->fd = fd;
4286249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    fuse->next_generation = 0;
42903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
4306249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    memset(&fuse->root, 0, sizeof(fuse->root));
4316249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    fuse->root.nid = FUSE_ROOT_ID; /* 1 */
4326249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    fuse->root.refcount = 2;
433e169bd05ec70f68c0db5e61c93b71e1746eb6c56Jeff Sharkey    fuse->root.namelen = strlen(source_path);
434e169bd05ec70f68c0db5e61c93b71e1746eb6c56Jeff Sharkey    fuse->root.name = strdup(source_path);
43503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}
43603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
4376249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic void fuse_status(struct fuse *fuse, __u64 unique, int err)
43803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
43903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    struct fuse_out_header hdr;
44003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    hdr.len = sizeof(hdr);
44103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    hdr.error = err;
44203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    hdr.unique = unique;
44303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    write(fuse->fd, &hdr, sizeof(hdr));
44403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}
44503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
4466249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic void fuse_reply(struct fuse *fuse, __u64 unique, void *data, int len)
44703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
44803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    struct fuse_out_header hdr;
44903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    struct iovec vec[2];
45003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    int res;
45103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
45203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    hdr.len = len + sizeof(hdr);
45303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    hdr.error = 0;
45403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    hdr.unique = unique;
45503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
45603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    vec[0].iov_base = &hdr;
45703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    vec[0].iov_len = sizeof(hdr);
45803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    vec[1].iov_base = data;
45903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    vec[1].iov_len = len;
46003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
46103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    res = writev(fuse->fd, vec, 2);
46203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    if (res < 0) {
46303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland        ERROR("*** REPLY FAILED *** %d\n", errno);
46403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    }
46503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}
46603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
4676249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic int fuse_reply_entry(struct fuse* fuse, __u64 unique,
4686249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        struct node* parent, const char* name, const char* actual_name,
4696249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        const char* path)
47003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
471fc1e1a0ab48a88dc7e9a93f65da5e6458de622afJeff Brown    struct node* node;
4726249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    struct fuse_entry_out out;
4736249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    struct stat s;
47403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
4756249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (lstat(path, &s) < 0) {
4766249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        return -errno;
47703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    }
478fc1e1a0ab48a88dc7e9a93f65da5e6458de622afJeff Brown
4796249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    pthread_mutex_lock(&fuse->lock);
4806249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    node = acquire_or_create_child_locked(fuse, parent, name, actual_name);
4816249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    if (!node) {
4826249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        pthread_mutex_unlock(&fuse->lock);
4836249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        return -ENOMEM;
4846249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    }
4856249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    memset(&out, 0, sizeof(out));
4866249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    attr_from_stat(&out.attr, &s, node->nid);
4876249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    out.attr_valid = 10;
4886249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    out.entry_valid = 10;
48903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    out.nodeid = node->nid;
49003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    out.generation = node->gen;
4916249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    pthread_mutex_unlock(&fuse->lock);
49203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland    fuse_reply(fuse, unique, &out, sizeof(out));
4936249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown    return NO_STATUS;
49403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}
49503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland
4966249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brownstatic int fuse_reply_attr(struct fuse* fuse, __u64 unique, __u64 nid,
4976249b9009f44f2127670eda4d5aa6d5fd3e26e02Jeff Brown        const char* path)
49803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{
499