sdcard.c revision 7729d2450faeb1a02c72b29f48efc208de1cb444
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> 3003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 31b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland#include <private/android_filesystem_config.h> 32b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland 3303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#include "fuse.h" 3403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 3503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland/* README 3603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * 3703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * What is this? 3803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * 3903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * sdcard is a program that uses FUSE to emulate FAT-on-sdcard style 4003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * directory permissions (all files are given fixed owner, group, and 4103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * permissions at creation, owner, group, and permissions are not 4203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * changeable, symlinks and hardlinks are not createable, etc. 4303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * 4403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * usage: sdcard <path> <uid> <gid> 4503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * 4603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * It must be run as root, but will change to uid/gid as soon as it 47cfa9f650266621fee963fe18084a39602aa8fcc6Jeff Sharkey * mounts a filesystem on /storage/sdcard. It will refuse to run if uid or 4803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * gid are zero. 4903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * 5003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * 5103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * Things I believe to be true: 5203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * 5303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * - ops that return a fuse_entry (LOOKUP, MKNOD, MKDIR, LINK, SYMLINK, 5403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * CREAT) must bump that node's refcount 5503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * - don't forget that FORGET can forget multiple references (req->nlookup) 5603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * - if an op that returns a fuse_entry fails writing the reply to the 5703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * kernel, you must rollback the refcount to reflect the reference the 5803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * kernel did not actually acquire 5903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland * 6003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland */ 6103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 6203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#define FUSE_TRACE 0 6303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 6403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#if FUSE_TRACE 6503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#define TRACE(x...) fprintf(stderr,x) 6603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#else 6703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#define TRACE(x...) do {} while (0) 6803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#endif 6903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 7003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#define ERROR(x...) fprintf(stderr,x) 7103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 7203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland#define FUSE_UNKNOWN_INO 0xffffffff 7303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 74cfa9f650266621fee963fe18084a39602aa8fcc6Jeff Sharkey#define MOUNT_POINT "/storage/sdcard0" 754553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood 76847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown/* Maximum number of bytes to write in one request. */ 77847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown#define MAX_WRITE (256 * 1024) 78847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 79847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown/* Maximum number of bytes to read in one request. */ 80847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown#define MAX_READ (128 * 1024) 81847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 82847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown/* Largest possible request. 83847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown * The request size is bounded by the maximum size of a FUSE_WRITE request because it has 84847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown * the largest possible data payload. */ 85847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown#define MAX_REQUEST_SIZE (sizeof(struct fuse_in_header) + sizeof(struct fuse_write_in) + MAX_WRITE) 86847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 8703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct handle { 8803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct node *node; 8903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int fd; 9003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}; 9103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 9203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct dirhandle { 9303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct node *node; 9403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland DIR *d; 9503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}; 9603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 9703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct node { 9803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland __u64 nid; 9903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland __u64 gen; 10003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 10111ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham struct node *next; /* per-dir sibling list */ 10211ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham struct node *child; /* first contained file by this dir */ 10311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham struct node *all; /* global node list */ 10411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham struct node *parent; /* containing directory */ 10503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 10603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland __u32 refcount; 10703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland __u32 namelen; 10803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 10911ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham char *name; 110575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood /* If non-null, this is the real name of the file in the underlying storage. 111575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood * This may differ from the field "name" only by case. 112575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood * strlen(actual_name) will always equal strlen(name), so it is safe to use 113575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood * namelen for both fields. 114575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood */ 115575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood char *actual_name; 11603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}; 11703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 1187729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown/* Global data structure shared by all fuse handlers. */ 11903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct fuse { 12003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland __u64 next_generation; 12103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland __u64 next_node_id; 12203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 12303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int fd; 12403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 12503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct node *all; 12603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 12703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct node root; 1287729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char rootpath[PATH_MAX]; 12903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland}; 13003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 1317729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown/* Private data used by a single fuse handler. */ 1327729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brownstruct fuse_handler { 1337729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown /* To save memory, we never use the contents of the request buffer and the read 1347729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown * buffer at the same time. This allows us to share the underlying storage. */ 1357729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown union { 1367729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown __u8 request_buffer[MAX_REQUEST_SIZE]; 1377729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown __u8 read_buffer[MAX_READ]; 1387729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown }; 1397729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown}; 14003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 141575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood#define NO_CASE_SENSITIVE_MATCH 0 142575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood#define CASE_SENSITIVE_MATCH 1 143b94d320b1e7e2a3493147f6763cd2825b111a4d8Mike Lockwood 144f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham/* 145f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham * Get the real-life absolute path to a node. 146f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham * node: start at this node 147f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham * buf: storage for returned string 148f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham * name: append this string to path if set 149f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham */ 150575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwoodchar *do_node_get_path(struct node *node, char *buf, const char *name, int match_case_insensitive) 15103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 152575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood struct node *in_node = node; 153575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood const char *in_name = name; 1547729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *out = buf + PATH_MAX - 1; 15503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int len; 15603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out[0] = 0; 15703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 15803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (name) { 15903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland len = strlen(name); 16003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland goto start; 16103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 16203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 16303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland while (node) { 164575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood name = (node->actual_name ? node->actual_name : node->name); 16503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland len = node->namelen; 16603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node = node->parent; 16703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland start: 16803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if ((len + 1) > (out - buf)) 16903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return 0; 17003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out -= len; 17103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland memcpy(out, name, len); 172575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood /* avoid double slash at beginning of path */ 173575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood if (out[0] != '/') { 174575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood out --; 175575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood out[0] = '/'; 176575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } 17703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 17803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 179575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood /* If we are searching for a file within node (rather than computing node's path) 180575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood * and fail, then we need to look for a case insensitive match. 181575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood */ 182575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood if (in_name && match_case_insensitive && access(out, F_OK) != 0) { 1837729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 184575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood DIR* dir; 185575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood struct dirent* entry; 186575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood path = do_node_get_path(in_node, buffer, NULL, NO_CASE_SENSITIVE_MATCH); 187575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood dir = opendir(path); 188575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood if (!dir) { 189575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood ERROR("opendir %s failed: %s", path, strerror(errno)); 190575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood return out; 191575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } 192575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood 193575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood while ((entry = readdir(dir))) { 194575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood if (!strcasecmp(entry->d_name, in_name)) { 195575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood /* we have a match - replace the name */ 196575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood len = strlen(in_name); 1977729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown memcpy(buf + PATH_MAX - len - 1, entry->d_name, len); 198575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood break; 199575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } 200575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } 201575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood closedir(dir); 202575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } 203575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood 204575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood return out; 205575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood} 206575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood 207575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwoodchar *node_get_path(struct node *node, char *buf, const char *name) 208575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood{ 209575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood /* We look for case insensitive matches by default */ 210575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood return do_node_get_path(node, buf, name, CASE_SENSITIVE_MATCH); 21103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 21203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 21303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandvoid attr_from_stat(struct fuse_attr *attr, struct stat *s) 21403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 21503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland attr->ino = s->st_ino; 21603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland attr->size = s->st_size; 21703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland attr->blocks = s->st_blocks; 2184553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood attr->atime = s->st_atime; 2194553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood attr->mtime = s->st_mtime; 2204553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood attr->ctime = s->st_ctime; 2214553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood attr->atimensec = s->st_atime_nsec; 2224553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood attr->mtimensec = s->st_mtime_nsec; 2234553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood attr->ctimensec = s->st_ctime_nsec; 22403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland attr->mode = s->st_mode; 22503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland attr->nlink = s->st_nlink; 22603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 227b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland /* force permissions to something reasonable: 228b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland * world readable 229b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland * writable by the sdcard group 230b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland */ 231b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland if (attr->mode & 0100) { 232b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland attr->mode = (attr->mode & (~0777)) | 0775; 233b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland } else { 234b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland attr->mode = (attr->mode & (~0777)) | 0664; 235b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland } 236b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland 237b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland /* all files owned by root.sdcard */ 238b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland attr->uid = 0; 239b14a2c6e34b197870433386fb809d34b58b30fc0Brian Swetland attr->gid = AID_SDCARD_RW; 24003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 24103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 24203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandint node_get_attr(struct node *node, struct fuse_attr *attr) 24303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 24403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 24503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct stat s; 2467729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 24703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 24803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland path = node_get_path(node, buffer, 0); 24903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland res = lstat(path, &s); 25003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (res < 0) { 25103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland ERROR("lstat('%s') errno %d\n", path, errno); 25203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return -1; 25303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 25403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 25503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland attr_from_stat(attr, &s); 25603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland attr->ino = node->nid; 25703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 25803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return 0; 25903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 26003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 26111ccdb3be67b22f677065715ace68aabf371acc7Paul Easthamstatic void add_node_to_parent(struct node *node, struct node *parent) { 26211ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham node->parent = parent; 26311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham node->next = parent->child; 26411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham parent->child = node; 26577085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham parent->refcount++; 26611ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham} 26711ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham 268575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood/* Check to see if our parent directory already has a file with a name 269575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood * that differs only by case. If we find one, store it in the actual_name 270575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood * field so node_get_path will map it to this file in the underlying storage. 271575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood */ 272575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwoodstatic void node_find_actual_name(struct node *node) 273575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood{ 2747729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 275575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood const char *node_name = node->name; 276575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood DIR* dir; 277575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood struct dirent* entry; 278575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood 279575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood if (!node->parent) return; 280575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood 281575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood path = node_get_path(node->parent, buffer, 0); 282575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood dir = opendir(path); 283575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood if (!dir) { 284575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood ERROR("opendir %s failed: %s", path, strerror(errno)); 285575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood return; 286575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } 287575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood 288575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood while ((entry = readdir(dir))) { 289575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood const char *test_name = entry->d_name; 290575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood if (strcmp(test_name, node_name) && !strcasecmp(test_name, node_name)) { 291575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood /* we have a match - differs but only by case */ 292575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood node->actual_name = strdup(test_name); 293575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood if (!node->actual_name) { 294575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood ERROR("strdup failed - out of memory\n"); 295575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood exit(1); 296575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } 297575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood break; 298575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } 299575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } 300575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood closedir(dir); 301575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood} 302575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood 30303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct node *node_create(struct node *parent, const char *name, __u64 nid, __u64 gen) 30403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 30503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct node *node; 30603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int namelen = strlen(name); 30703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 30811ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham node = calloc(1, sizeof(struct node)); 30903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (node == 0) { 31003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return 0; 31103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 31211ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham node->name = malloc(namelen + 1); 31311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham if (node->name == 0) { 31411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham free(node); 31511ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham return 0; 31611ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham } 31703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 31803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node->nid = nid; 31903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node->gen = gen; 32011ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham add_node_to_parent(node, parent); 32103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland memcpy(node->name, name, namelen + 1); 32203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node->namelen = namelen; 323575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood node_find_actual_name(node); 32403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return node; 32503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 32603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 32711ccdb3be67b22f677065715ace68aabf371acc7Paul Easthamstatic char *rename_node(struct node *node, const char *name) 32811ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham{ 32911ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham node->namelen = strlen(name); 33011ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham char *newname = realloc(node->name, node->namelen + 1); 33111ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham if (newname == 0) 33211ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham return 0; 33311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham node->name = newname; 33411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham memcpy(node->name, name, node->namelen + 1); 335575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood node_find_actual_name(node); 33611ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham return node->name; 33711ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham} 33811ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham 33903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandvoid fuse_init(struct fuse *fuse, int fd, const char *path) 34003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 34103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse->fd = fd; 34203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse->next_node_id = 2; 34303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse->next_generation = 0; 34403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 34503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse->all = &fuse->root; 34603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 3478349cce829388503fae67d454aff6a544ccd36aaTerry Heo (Woncheol) memset(&fuse->root, 0, sizeof(fuse->root)); 34803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse->root.nid = FUSE_ROOT_ID; /* 1 */ 34903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse->root.refcount = 2; 35011ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham rename_node(&fuse->root, path); 35103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 35203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 35303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstatic inline void *id_to_ptr(__u64 nid) 35403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 3552656735f515a41cf131c87be5f40550b6538ce80Jeff Brown return (void *) (uintptr_t) nid; 35603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 35703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 35803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstatic inline __u64 ptr_to_id(void *ptr) 35903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 3602656735f515a41cf131c87be5f40550b6538ce80Jeff Brown return (__u64) (uintptr_t) ptr; 36103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 36203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 36303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 36403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct node *lookup_by_inode(struct fuse *fuse, __u64 nid) 36503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 36603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (nid == FUSE_ROOT_ID) { 36703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return &fuse->root; 36803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } else { 36903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return id_to_ptr(nid); 37003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 37103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 37203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 37303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct node *lookup_child_by_name(struct node *node, const char *name) 37403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 37503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland for (node = node->child; node; node = node->next) { 37603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (!strcmp(name, node->name)) { 37703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return node; 37803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 37903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 38003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return 0; 38103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 38203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 38303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct node *lookup_child_by_inode(struct node *node, __u64 nid) 38403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 38503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland for (node = node->child; node; node = node->next) { 38603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (node->nid == nid) { 38703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return node; 38803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 38903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 39003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return 0; 39103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 39203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 39377085c570e7db2ea4a52e3a0fec5100687c31b46Paul Easthamstatic void dec_refcount(struct node *node) { 39477085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham if (node->refcount > 0) { 39577085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham node->refcount--; 39677085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham TRACE("dec_refcount %p(%s) -> %d\n", node, node->name, node->refcount); 39777085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham } else { 39877085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham ERROR("Zero refcnt %p\n", node); 39977085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham } 40077085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham } 40177085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham 40211ccdb3be67b22f677065715ace68aabf371acc7Paul Easthamstatic struct node *remove_child(struct node *parent, __u64 nid) 40311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham{ 40411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham struct node *prev = 0; 40511ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham struct node *node; 40611ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham 40711ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham for (node = parent->child; node; node = node->next) { 40811ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham if (node->nid == nid) { 40911ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham if (prev) { 41011ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham prev->next = node->next; 41111ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham } else { 41211ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham parent->child = node->next; 41311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham } 41411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham node->next = 0; 41511ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham node->parent = 0; 41677085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham dec_refcount(parent); 41711ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham return node; 41811ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham } 41911ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham prev = node; 42011ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham } 42111ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham return 0; 42211ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham} 42311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham 42403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandstruct node *node_lookup(struct fuse *fuse, struct node *parent, const char *name, 42503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_attr *attr) 42603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 42703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 42803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct stat s; 4297729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 43003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct node *node; 43103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 43203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland path = node_get_path(parent, buffer, name); 43303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland /* XXX error? */ 43403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 43503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland res = lstat(path, &s); 43603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (res < 0) 43703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return 0; 43803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 43903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node = lookup_child_by_name(parent, name); 44003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (!node) { 44103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node = node_create(parent, name, fuse->next_node_id++, fuse->next_generation++); 44203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (!node) 44303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return 0; 44403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node->nid = ptr_to_id(node); 44503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node->all = fuse->all; 44603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse->all = node; 44703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 44803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 44903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland attr_from_stat(attr, &s); 45003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland attr->ino = node->nid; 45103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 45203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return node; 45303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 45403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 45503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandvoid node_release(struct node *node) 45603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 45703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("RELEASE %p (%s) rc=%d\n", node, node->name, node->refcount); 45877085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham dec_refcount(node); 45903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (node->refcount == 0) { 46003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (node->parent->child == node) { 46103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node->parent->child = node->parent->child->next; 46203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } else { 46303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct node *node2; 46403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 46503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node2 = node->parent->child; 46603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland while (node2->next != node) 46703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node2 = node2->next; 46803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node2->next = node->next; 46903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 47003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 47103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("DESTROY %p (%s)\n", node, node->name); 47203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 47303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node_release(node->parent); 47403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 47503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node->parent = 0; 47603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node->next = 0; 47703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 47803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland /* TODO: remove debugging - poison memory */ 47911ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham memset(node->name, 0xef, node->namelen); 48011ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham free(node->name); 481575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood free(node->actual_name); 48277085c570e7db2ea4a52e3a0fec5100687c31b46Paul Eastham memset(node, 0xfc, sizeof(*node)); 48303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland free(node); 48403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 48503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 48603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 48703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandvoid fuse_status(struct fuse *fuse, __u64 unique, int err) 48803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 48903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_out_header hdr; 49003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland hdr.len = sizeof(hdr); 49103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland hdr.error = err; 49203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland hdr.unique = unique; 49303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (err) { 49403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland// ERROR("*** %d ***\n", err); 49503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 49603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland write(fuse->fd, &hdr, sizeof(hdr)); 49703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 49803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 49903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandvoid fuse_reply(struct fuse *fuse, __u64 unique, void *data, int len) 50003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 50103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_out_header hdr; 50203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct iovec vec[2]; 50303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 50403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 50503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland hdr.len = len + sizeof(hdr); 50603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland hdr.error = 0; 50703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland hdr.unique = unique; 50803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 50903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland vec[0].iov_base = &hdr; 51003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland vec[0].iov_len = sizeof(hdr); 51103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland vec[1].iov_base = data; 51203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland vec[1].iov_len = len; 51303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 51403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland res = writev(fuse->fd, vec, 2); 51503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (res < 0) { 51603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland ERROR("*** REPLY FAILED *** %d\n", errno); 51703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 51803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 51903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 52003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetlandvoid lookup_entry(struct fuse *fuse, struct node *node, 52103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland const char *name, __u64 unique) 52203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 52303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_entry_out out; 52403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 52503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland memset(&out, 0, sizeof(out)); 52603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 52703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node = node_lookup(fuse, node, name, &out.attr); 52803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (!node) { 52903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, unique, -ENOENT); 53003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 53103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 53203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 53303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node->refcount++; 53403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland// fprintf(stderr,"ACQUIRE %p (%s) rc=%d\n", node, node->name, node->refcount); 53503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.nodeid = node->nid; 53603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.generation = node->gen; 53703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.entry_valid = 10; 53803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.attr_valid = 10; 53903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 54003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_reply(fuse, unique, &out, sizeof(out)); 54103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 54203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 5437729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brownvoid handle_fuse_request(struct fuse *fuse, struct fuse_handler* handler, 544847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_in_header *hdr, const void *data, size_t data_len) 54503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 54603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct node *node; 54703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 54803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (hdr->nodeid) { 54903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node = lookup_by_inode(fuse, hdr->nodeid); 55003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (!node) { 55103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, -ENOENT); 55203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 55303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 55403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } else { 55503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node = 0; 55603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 55703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 55803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland switch (hdr->opcode) { 55903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_LOOKUP: { /* bytez[] -> entry_out */ 560847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const char* name = data; 561847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown TRACE("LOOKUP %llx %s\n", hdr->nodeid, name); 562847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown lookup_entry(fuse, node, name, hdr->unique); 56303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 56403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 565847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 56603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_FORGET: { 567847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_forget_in *req = data; 568847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown __u64 n = req->nlookup; 569847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown TRACE("FORGET %llx (%s) #%lld\n", hdr->nodeid, node->name, n); 57003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland /* no reply */ 571847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown while (n--) 57203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node_release(node); 57303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 57403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 575847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 57603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_GETATTR: { /* getattr_in -> attr_out */ 577847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_getattr_in *req = data; 57803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_attr_out out; 57903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 58011ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham TRACE("GETATTR flags=%x fh=%llx\n", req->getattr_flags, req->fh); 58103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 58203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland memset(&out, 0, sizeof(out)); 58303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node_get_attr(node, &out.attr); 58403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.attr_valid = 10; 58503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 58603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 58703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 58803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 589847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 59003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_SETATTR: { /* setattr_in -> attr_out */ 591847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_setattr_in *req = data; 59203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_attr_out out; 5937729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 594f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham int res = 0; 59597919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall struct timespec times[2]; 596f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham 59703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("SETATTR fh=%llx id=%llx valid=%x\n", 59803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland req->fh, hdr->nodeid, req->valid); 59903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 60097919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall /* XXX: incomplete implementation on purpose. chmod/chown 60197919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall * should NEVER be implemented.*/ 602f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham 603f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham path = node_get_path(node, buffer, 0); 604f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham if (req->valid & FATTR_SIZE) 605f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham res = truncate(path, req->size); 60697919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall if (res) 60797919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall goto getout; 60897919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall 60997919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall /* Handle changing atime and mtime. If FATTR_ATIME_and FATTR_ATIME_NOW 61097919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall * are both set, then set it to the current time. Else, set it to the 61197919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall * time specified in the request. Same goes for mtime. Use utimensat(2) 61297919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall * as it allows ATIME and MTIME to be changed independently, and has 61397919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall * nanosecond resolution which fuse also has. 61497919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall */ 61597919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall if (req->valid & (FATTR_ATIME | FATTR_MTIME)) { 61697919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall times[0].tv_nsec = UTIME_OMIT; 61797919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall times[1].tv_nsec = UTIME_OMIT; 61897919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall if (req->valid & FATTR_ATIME) { 61997919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall if (req->valid & FATTR_ATIME_NOW) { 62097919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall times[0].tv_nsec = UTIME_NOW; 62197919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall } else { 62297919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall times[0].tv_sec = req->atime; 62397919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall times[0].tv_nsec = req->atimensec; 62497919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall } 62597919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall } 62697919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall if (req->valid & FATTR_MTIME) { 62797919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall if (req->valid & FATTR_MTIME_NOW) { 62897919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall times[1].tv_nsec = UTIME_NOW; 62997919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall } else { 63097919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall times[1].tv_sec = req->mtime; 63197919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall times[1].tv_nsec = req->mtimensec; 63297919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall } 63397919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall } 63497919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall TRACE("Calling utimensat on %s with atime %ld, mtime=%ld\n", path, times[0].tv_sec, times[1].tv_sec); 63597919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall res = utimensat(-1, path, times, 0); 63697919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall } 63703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 63897919656803126c6b28ea6070fc86d124ac4ef4bKen Sumrall getout: 63903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland memset(&out, 0, sizeof(out)); 64003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland node_get_attr(node, &out.attr); 64103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.attr_valid = 10; 642f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham 643f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham if (res) 644f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham fuse_status(fuse, hdr->unique, -errno); 645f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham else 646f43219e0b1022b257499289ceb951f6a1a44bf9cPaul Eastham fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 64703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 64803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 649847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 65003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland// case FUSE_READLINK: 65103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland// case FUSE_SYMLINK: 65203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_MKNOD: { /* mknod_in, bytez[] -> entry_out */ 653847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_mknod_in *req = data; 654847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const char *name = ((const char*) data) + sizeof(*req); 6557729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 65603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 65751b3a2d77a3361f6088172a4a68a0111058d3aabMike Lockwood 65803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("MKNOD %s @ %llx\n", name, hdr->nodeid); 65903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland path = node_get_path(node, buffer, name); 66003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 661847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown __u32 mode = (req->mode & (~0777)) | 0664; 662847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown res = mknod(path, mode, req->rdev); /* XXX perm?*/ 66303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (res < 0) { 66403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, -errno); 66503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } else { 66603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland lookup_entry(fuse, node, name, hdr->unique); 66703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 66803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 66903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 670847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 67103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_MKDIR: { /* mkdir_in, bytez[] -> entry_out */ 672847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_mkdir_in *req = data; 673847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const char *name = ((const char*) data) + sizeof(*req); 67403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_entry_out out; 6757729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 67603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 67751b3a2d77a3361f6088172a4a68a0111058d3aabMike Lockwood 67803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("MKDIR %s @ %llx 0%o\n", name, hdr->nodeid, req->mode); 67903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland path = node_get_path(node, buffer, name); 68003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 681847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown __u32 mode = (req->mode & (~0777)) | 0775; 682847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown res = mkdir(path, mode); 68303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (res < 0) { 68403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, -errno); 68503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } else { 68603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland lookup_entry(fuse, node, name, hdr->unique); 68703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 68803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 68903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 690847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 69103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_UNLINK: { /* bytez[] -> */ 692847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const char* name = data; 6937729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 69403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 695847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown TRACE("UNLINK %s @ %llx\n", name, hdr->nodeid); 696847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown path = node_get_path(node, buffer, name); 69703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland res = unlink(path); 69803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, res ? -errno : 0); 69903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 70003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 701847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 70203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_RMDIR: { /* bytez[] -> */ 703847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const char* name = data; 7047729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 70503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 706847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown TRACE("RMDIR %s @ %llx\n", name, hdr->nodeid); 707847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown path = node_get_path(node, buffer, name); 70803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland res = rmdir(path); 70903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, res ? -errno : 0); 71003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 71103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 712847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 71303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_RENAME: { /* rename_in, oldname, newname -> */ 714847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_rename_in *req = data; 715847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const char *oldname = ((const char*) data) + sizeof(*req); 716847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const char *newname = oldname + strlen(oldname) + 1; 7177729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *oldpath, oldbuffer[PATH_MAX]; 7187729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *newpath, newbuffer[PATH_MAX]; 71911ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham struct node *target; 72011ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham struct node *newparent; 72103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 72203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 72311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham TRACE("RENAME %s->%s @ %llx\n", oldname, newname, hdr->nodeid); 72411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham 72511ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham target = lookup_child_by_name(node, oldname); 72611ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham if (!target) { 72703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, -ENOENT); 72803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 72903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 73003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland oldpath = node_get_path(node, oldbuffer, oldname); 73111ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham 73211ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham newparent = lookup_by_inode(fuse, req->newdir); 73311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham if (!newparent) { 73411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham fuse_status(fuse, hdr->unique, -ENOENT); 73511ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham return; 73611ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham } 737575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood if (newparent == node) { 738575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood /* Special case for renaming a file where destination 739575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood * is same path differing only by case. 740575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood * In this case we don't want to look for a case insensitive match. 741575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood * This allows commands like "mv foo FOO" to work as expected. 742575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood */ 743575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood newpath = do_node_get_path(newparent, newbuffer, newname, NO_CASE_SENSITIVE_MATCH); 744575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } else { 745575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood newpath = node_get_path(newparent, newbuffer, newname); 746575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood } 74711ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham 74811ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham if (!remove_child(node, target->nid)) { 74911ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham ERROR("RENAME remove_child not found"); 75011ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham fuse_status(fuse, hdr->unique, -ENOENT); 75111ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham return; 75211ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham } 75311ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham if (!rename_node(target, newname)) { 75411ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham fuse_status(fuse, hdr->unique, -ENOMEM); 75511ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham return; 75611ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham } 75711ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham add_node_to_parent(target, newparent); 75803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 75903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland res = rename(oldpath, newpath); 76011ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham TRACE("RENAME result %d\n", res); 76111ccdb3be67b22f677065715ace68aabf371acc7Paul Eastham 76203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, res ? -errno : 0); 76303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 76403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 765847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 76603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland// case FUSE_LINK: 76703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_OPEN: { /* open_in -> open_out */ 768847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_open_in *req = data; 76903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_open_out out; 7707729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 77103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct handle *h; 77203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 77303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland h = malloc(sizeof(*h)); 77403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (!h) { 77503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, -ENOMEM); 77603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 77703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 77803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 77903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland path = node_get_path(node, buffer, 0); 78003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("OPEN %llx '%s' 0%o fh=%p\n", hdr->nodeid, path, req->flags, h); 78103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland h->fd = open(path, req->flags); 78203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (h->fd < 0) { 78303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland ERROR("ERROR\n"); 7842fc9fc7c8e26a35059ad39fe35ed256bfadb2891Yuncheol Heo fuse_status(fuse, hdr->unique, -errno); 78503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland free(h); 78603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 78703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 78803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.fh = ptr_to_id(h); 78903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.open_flags = 0; 79003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.padding = 0; 79103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 79203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 79303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 794847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 79503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_READ: { /* read_in -> byte[] */ 796847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_read_in *req = data; 79703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct handle *h = id_to_ptr(req->fh); 7987729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown __u64 unique = hdr->unique; 7997729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown __u32 size = req->size; 8007729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown __u64 offset = req->offset; 8017729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown /* Don't access any other fields of hdr or req beyond this point, the read buffer 8027729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown * overlaps the request buffer and will clobber data in the request. This 8037729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown * saves us 128KB per request handler thread at the cost of this scary comment. */ 80403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 8057729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown TRACE("READ %p(%d) %u@%llu\n", h, h->fd, size, offset); 8067729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown if (size > sizeof(handler->read_buffer)) { 8077729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown fuse_status(fuse, unique, -EINVAL); 80803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 80903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 8107729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown res = pread64(h->fd, handler->read_buffer, size, offset); 81103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (res < 0) { 8127729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown fuse_status(fuse, unique, -errno); 81303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 81403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 8157729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown fuse_reply(fuse, unique, handler->read_buffer, res); 81603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 81703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 818847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 81903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_WRITE: { /* write_in, byte[write_in.size] -> write_out */ 820847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_write_in *req = data; 821847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const void* buffer = (const __u8*)data + sizeof(*req); 82203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_write_out out; 82303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct handle *h = id_to_ptr(req->fh); 82403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 82503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("WRITE %p(%d) %u@%llu\n", h, h->fd, req->size, req->offset); 826847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown res = pwrite64(h->fd, buffer, req->size, req->offset); 82703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (res < 0) { 8282fc9fc7c8e26a35059ad39fe35ed256bfadb2891Yuncheol Heo fuse_status(fuse, hdr->unique, -errno); 82903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 83003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 83103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.size = res; 83203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 833847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown return; 83403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 835847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 8364553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood case FUSE_STATFS: { /* getattr_in -> attr_out */ 8374553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood struct statfs stat; 8384553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood struct fuse_statfs_out out; 8394553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood int res; 8404553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood 8414553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood TRACE("STATFS\n"); 8424553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood 8434553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood if (statfs(fuse->root.name, &stat)) { 8444553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood fuse_status(fuse, hdr->unique, -errno); 8454553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood return; 8464553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood } 8474553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood 8484553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood memset(&out, 0, sizeof(out)); 8494553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood out.st.blocks = stat.f_blocks; 8504553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood out.st.bfree = stat.f_bfree; 8514553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood out.st.bavail = stat.f_bavail; 8524553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood out.st.files = stat.f_files; 8534553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood out.st.ffree = stat.f_ffree; 8544553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood out.st.bsize = stat.f_bsize; 8554553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood out.st.namelen = stat.f_namelen; 8564553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood out.st.frsize = stat.f_frsize; 8574553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 8584553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood return; 8594553b08d7555a103fdbe8623a9cbd826a7e413ffMike Lockwood } 860847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 86103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_RELEASE: { /* release_in -> */ 862847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_release_in *req = data; 86303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct handle *h = id_to_ptr(req->fh); 86403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("RELEASE %p(%d)\n", h, h->fd); 86503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland close(h->fd); 86603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland free(h); 86703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, 0); 86803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 86903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 870847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 8716fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown case FUSE_FSYNC: { 8726fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown const struct fuse_fsync_in *req = data; 8736fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown int is_data_sync = req->fsync_flags & 1; 8746fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown struct handle *h = id_to_ptr(req->fh); 8756fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown int res; 8766fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown TRACE("FSYNC %p(%d) is_data_sync=%d\n", h, h->fd, is_data_sync); 8776fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown res = is_data_sync ? fdatasync(h->fd) : fsync(h->fd); 8786fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown if (res < 0) { 8796fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown fuse_status(fuse, hdr->unique, -errno); 8806fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown return; 8816fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown } 8826fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown fuse_status(fuse, hdr->unique, 0); 8836fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown return; 8846fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown } 8856fd921ae03a0fa17acfe118753ecd76d25f02e10Jeff Brown 88603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland// case FUSE_SETXATTR: 88703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland// case FUSE_GETXATTR: 88803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland// case FUSE_LISTXATTR: 88903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland// case FUSE_REMOVEXATTR: 890847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown case FUSE_FLUSH: { 89103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, 0); 89203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 893847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown } 894847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 89503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_OPENDIR: { /* open_in -> open_out */ 896847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_open_in *req = data; 89703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_open_out out; 8987729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown char *path, buffer[PATH_MAX]; 89903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct dirhandle *h; 90003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 90103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland h = malloc(sizeof(*h)); 90203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (!h) { 90303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, -ENOMEM); 90403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 90503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 90603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 90703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland path = node_get_path(node, buffer, 0); 90803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("OPENDIR %llx '%s'\n", hdr->nodeid, path); 90903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland h->d = opendir(path); 91003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (h->d == 0) { 91103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland ERROR("ERROR\n"); 91203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, -errno); 91303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland free(h); 91403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 91503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 91603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.fh = ptr_to_id(h); 91703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 91803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 91903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 920847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 92103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_READDIR: { 922847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_read_in *req = data; 92303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland char buffer[8192]; 92403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_dirent *fde = (struct fuse_dirent*) buffer; 92503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct dirent *de; 92603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct dirhandle *h = id_to_ptr(req->fh); 92703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("READDIR %p\n", h); 92875e17a8908d52e32f5de85b90b74e156265c60c6Mike Lockwood if (req->offset == 0) { 92975e17a8908d52e32f5de85b90b74e156265c60c6Mike Lockwood /* rewinddir() might have been called above us, so rewind here too */ 93075e17a8908d52e32f5de85b90b74e156265c60c6Mike Lockwood TRACE("calling rewinddir()\n"); 93175e17a8908d52e32f5de85b90b74e156265c60c6Mike Lockwood rewinddir(h->d); 93275e17a8908d52e32f5de85b90b74e156265c60c6Mike Lockwood } 93303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland de = readdir(h->d); 93403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (!de) { 93503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, 0); 93603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 93703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 93803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fde->ino = FUSE_UNKNOWN_INO; 93975e17a8908d52e32f5de85b90b74e156265c60c6Mike Lockwood /* increment the offset so we can detect when rewinddir() seeks back to the beginning */ 94075e17a8908d52e32f5de85b90b74e156265c60c6Mike Lockwood fde->off = req->offset + 1; 94103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fde->type = de->d_type; 94203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fde->namelen = strlen(de->d_name); 94303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland memcpy(fde->name, de->d_name, fde->namelen + 1); 94403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_reply(fuse, hdr->unique, fde, 94503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland FUSE_DIRENT_ALIGN(sizeof(struct fuse_dirent) + fde->namelen)); 94603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 94703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 948847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 94903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_RELEASEDIR: { /* release_in -> */ 950847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_release_in *req = data; 95103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct dirhandle *h = id_to_ptr(req->fh); 95203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("RELEASEDIR %p\n",h); 95303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland closedir(h->d); 95403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland free(h); 95503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_status(fuse, hdr->unique, 0); 95603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 95703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 958847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 95903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland// case FUSE_FSYNCDIR: 96003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland case FUSE_INIT: { /* init_in -> init_out */ 961847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown const struct fuse_init_in *req = data; 96203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland struct fuse_init_out out; 96303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 96403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland TRACE("INIT ver=%d.%d maxread=%d flags=%x\n", 96503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland req->major, req->minor, req->max_readahead, req->flags); 96603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 96703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.major = FUSE_KERNEL_VERSION; 96803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.minor = FUSE_KERNEL_MINOR_VERSION; 96903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.max_readahead = req->max_readahead; 970e5d32128b0f1373822b02b2a2e69c6b199e0f805Sundar Raman out.flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES; 97103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.max_background = 32; 97203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland out.congestion_threshold = 32; 973847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown out.max_write = MAX_WRITE; 97403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 97503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 97603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 97703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 978847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 97903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland default: { 98003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland ERROR("NOTIMPL op=%d uniq=%llx nid=%llx\n", 98103ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland hdr->opcode, hdr->unique, hdr->nodeid); 982847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown fuse_status(fuse, hdr->unique, -ENOSYS); 98303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland break; 98403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 985847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown } 98603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 98703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 9887729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brownvoid handle_fuse_requests(struct fuse *fuse, struct fuse_handler* handler) 98903ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 99003ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland for (;;) { 9917729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown ssize_t len = read(fuse->fd, handler->request_buffer, sizeof(handler->request_buffer)); 99203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (len < 0) { 99303ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland if (errno == EINTR) 99403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland continue; 99503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland ERROR("handle_fuse_requests: errno=%d\n", errno); 99603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland return; 99703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 998847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 999847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown if ((size_t)len < sizeof(struct fuse_in_header)) { 1000847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown ERROR("request too short: len=%zu\n", (size_t)len); 1001847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown return; 1002847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown } 1003847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 10047729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown const struct fuse_in_header *hdr = (void*)handler->request_buffer; 1005847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown if (hdr->len != (size_t)len) { 1006847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown ERROR("malformed header: len=%zu, hdr->len=%u\n", (size_t)len, hdr->len); 1007847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown return; 1008847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown } 1009847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown 10107729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown const void *data = handler->request_buffer + sizeof(struct fuse_in_header); 1011847158476c1b7662eeec77808d8ecdbb329e6f28Jeff Brown size_t data_len = len - sizeof(struct fuse_in_header); 10127729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown handle_fuse_request(fuse, handler, hdr, data, data_len); 10137729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown 10147729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown /* We do not access the request again after this point because the underlying 10157729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown * buffer storage may have been reused while processing the request. */ 101603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 101703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 101803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 10197729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brownint ignite_fuse(struct fuse* fuse) 10207729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown{ 10217729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown /* use only one handler thread for now */ 10227729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown struct fuse_handler handler; 10237729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown handle_fuse_requests(fuse, &handler); 10247729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown return 0; 10257729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown} 10267729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown 10274f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwoodstatic int usage() 10284f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood{ 10292656735f515a41cf131c87be5f40550b6538ce80Jeff Brown ERROR("usage: sdcard <path> <uid> <gid>\n\n"); 10302656735f515a41cf131c87be5f40550b6538ce80Jeff Brown return 1; 10314f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood} 10324f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood 10332656735f515a41cf131c87be5f40550b6538ce80Jeff Brownstatic int run(const char* path, uid_t uid, gid_t gid) 103403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland{ 10352656735f515a41cf131c87be5f40550b6538ce80Jeff Brown int fd; 103603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland char opts[256]; 10372656735f515a41cf131c87be5f40550b6538ce80Jeff Brown int res; 10382656735f515a41cf131c87be5f40550b6538ce80Jeff Brown struct fuse fuse; 10392656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10402656735f515a41cf131c87be5f40550b6538ce80Jeff Brown /* cleanup from previous instance, if necessary */ 10412656735f515a41cf131c87be5f40550b6538ce80Jeff Brown umount2(MOUNT_POINT, 2); 10422656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10432656735f515a41cf131c87be5f40550b6538ce80Jeff Brown fd = open("/dev/fuse", O_RDWR); 10442656735f515a41cf131c87be5f40550b6538ce80Jeff Brown if (fd < 0){ 10452656735f515a41cf131c87be5f40550b6538ce80Jeff Brown ERROR("cannot open fuse device (error %d)\n", errno); 10462656735f515a41cf131c87be5f40550b6538ce80Jeff Brown return -1; 10472656735f515a41cf131c87be5f40550b6538ce80Jeff Brown } 10482656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10492656735f515a41cf131c87be5f40550b6538ce80Jeff Brown snprintf(opts, sizeof(opts), 10502656735f515a41cf131c87be5f40550b6538ce80Jeff Brown "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d", 10512656735f515a41cf131c87be5f40550b6538ce80Jeff Brown fd, uid, gid); 10522656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10532656735f515a41cf131c87be5f40550b6538ce80Jeff Brown res = mount("/dev/fuse", MOUNT_POINT, "fuse", MS_NOSUID | MS_NODEV, opts); 10542656735f515a41cf131c87be5f40550b6538ce80Jeff Brown if (res < 0) { 10552656735f515a41cf131c87be5f40550b6538ce80Jeff Brown ERROR("cannot mount fuse filesystem (error %d)\n", errno); 10562656735f515a41cf131c87be5f40550b6538ce80Jeff Brown goto error; 10572656735f515a41cf131c87be5f40550b6538ce80Jeff Brown } 10582656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10592656735f515a41cf131c87be5f40550b6538ce80Jeff Brown res = setgid(gid); 10602656735f515a41cf131c87be5f40550b6538ce80Jeff Brown if (res < 0) { 10612656735f515a41cf131c87be5f40550b6538ce80Jeff Brown ERROR("cannot setgid (error %d)\n", errno); 10622656735f515a41cf131c87be5f40550b6538ce80Jeff Brown goto error; 10632656735f515a41cf131c87be5f40550b6538ce80Jeff Brown } 10642656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10652656735f515a41cf131c87be5f40550b6538ce80Jeff Brown res = setuid(uid); 10662656735f515a41cf131c87be5f40550b6538ce80Jeff Brown if (res < 0) { 10672656735f515a41cf131c87be5f40550b6538ce80Jeff Brown ERROR("cannot setuid (error %d)\n", errno); 10682656735f515a41cf131c87be5f40550b6538ce80Jeff Brown goto error; 10692656735f515a41cf131c87be5f40550b6538ce80Jeff Brown } 10702656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10712656735f515a41cf131c87be5f40550b6538ce80Jeff Brown fuse_init(&fuse, fd, path); 10722656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10732656735f515a41cf131c87be5f40550b6538ce80Jeff Brown umask(0); 10747729d2450faeb1a02c72b29f48efc208de1cb444Jeff Brown res = ignite_fuse(&fuse); 10752656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10762656735f515a41cf131c87be5f40550b6538ce80Jeff Brown /* we do not attempt to umount the file system here because we are no longer 10772656735f515a41cf131c87be5f40550b6538ce80Jeff Brown * running as the root user */ 10782656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10792656735f515a41cf131c87be5f40550b6538ce80Jeff Brownerror: 10802656735f515a41cf131c87be5f40550b6538ce80Jeff Brown close(fd); 10812656735f515a41cf131c87be5f40550b6538ce80Jeff Brown return res; 10822656735f515a41cf131c87be5f40550b6538ce80Jeff Brown} 10832656735f515a41cf131c87be5f40550b6538ce80Jeff Brown 10842656735f515a41cf131c87be5f40550b6538ce80Jeff Brownint main(int argc, char **argv) 10852656735f515a41cf131c87be5f40550b6538ce80Jeff Brown{ 108603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int fd; 108703ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland int res; 10884f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood const char *path = NULL; 10892656735f515a41cf131c87be5f40550b6538ce80Jeff Brown uid_t uid = 0; 10902656735f515a41cf131c87be5f40550b6538ce80Jeff Brown gid_t gid = 0; 10914f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood int i; 10924f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood 10934f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood for (i = 1; i < argc; i++) { 10944f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood char* arg = argv[i]; 1095575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood if (!path) 1096575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood path = arg; 10972656735f515a41cf131c87be5f40550b6538ce80Jeff Brown else if (!uid) 1098575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood uid = strtoul(arg, 0, 10); 10992656735f515a41cf131c87be5f40550b6538ce80Jeff Brown else if (!gid) 1100575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood gid = strtoul(arg, 0, 10); 1101575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood else { 1102575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood ERROR("too many arguments\n"); 1103575a2bbee30d70a1940077a5b699aaf93cb4e2cdMike Lockwood return usage(); 11044f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood } 110503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 110603ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 11074f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood if (!path) { 11084f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood ERROR("no path specified\n"); 11094f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood return usage(); 11104f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood } 11112656735f515a41cf131c87be5f40550b6538ce80Jeff Brown if (!uid || !gid) { 111203ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland ERROR("uid and gid must be nonzero\n"); 11134f35e623a2359789406772009078d1a6ca7af6b3Mike Lockwood return usage(); 111403ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland } 111503ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland 11162656735f515a41cf131c87be5f40550b6538ce80Jeff Brown res = run(path, uid, gid); 11172656735f515a41cf131c87be5f40550b6538ce80Jeff Brown return res < 0 ? 1 : 0; 111803ee9479a4ed67689b9bbccda20c60800a38b178Brian Swetland} 1119