libfuse
passthrough_helpers.h
1/*
2 * FUSE: Filesystem in Userspace
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE
24 */
25
26#ifndef FUSE_EXAMPLE_PASSTHROUGH_HELPERS_H_
27#define FUSE_EXAMPLE_PASSTHROUGH_HELPERS_H_
28
29#include <errno.h>
30#include <fcntl.h>
31#include <string.h>
32#include <sys/stat.h>
33#include <unistd.h>
34
35#ifdef __FreeBSD__
36#include <sys/socket.h>
37#include <sys/un.h>
38#endif
39
40static inline int do_fallocate(int fd, int mode, off_t offset, off_t length)
41{
42#ifdef HAVE_FALLOCATE
43 if (fallocate(fd, mode, offset, length) == -1)
44 return -errno;
45 return 0;
46#else // HAVE_FALLOCATE
47
48#ifdef HAVE_POSIX_FALLOCATE
49 if (mode == 0)
50 return -posix_fallocate(fd, offset, length);
51#endif
52
53#ifdef HAVE_FSPACECTL
54 // 0x3 == FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE
55 if (mode == 0x3) {
56 struct spacectl_range sr;
57
58 sr.r_offset = offset;
59 sr.r_len = length;
60 if (fspacectl(fd, SPACECTL_DEALLOC, &sr, 0, NULL) == -1)
61 return -errno;
62 return 0;
63 }
64#endif
65
66 return -EOPNOTSUPP;
67#endif // HAVE_FALLOCATE
68}
69
70/*
71 * Creates files on the underlying file system in response to a FUSE_MKNOD
72 * operation
73 */
74static inline int mknod_wrapper(int dirfd, const char *path, const char *link,
75 int mode, dev_t rdev)
76{
77 int res;
78
79 if (S_ISREG(mode)) {
80 res = openat(dirfd, path, O_CREAT | O_EXCL | O_WRONLY, mode);
81 if (res >= 0)
82 res = close(res);
83 } else if (S_ISDIR(mode)) {
84 res = mkdirat(dirfd, path, mode);
85 } else if (S_ISLNK(mode) && link != NULL) {
86 res = symlinkat(link, dirfd, path);
87 } else if (S_ISFIFO(mode)) {
88 res = mkfifoat(dirfd, path, mode);
89#ifdef __FreeBSD__
90 } else if (S_ISSOCK(mode)) {
91 struct sockaddr_un su;
92 int fd;
93
94 if (strlen(path) >= sizeof(su.sun_path)) {
95 errno = ENAMETOOLONG;
96 return -1;
97 }
98 fd = socket(AF_UNIX, SOCK_STREAM, 0);
99 if (fd >= 0) {
100 /*
101 * We must bind the socket to the underlying file
102 * system to create the socket file, even though
103 * we'll never listen on this socket.
104 */
105 su.sun_family = AF_UNIX;
106 strncpy(su.sun_path, path, sizeof(su.sun_path));
107 res = bindat(dirfd, fd, (struct sockaddr*)&su,
108 sizeof(su));
109 if (res == 0)
110 close(fd);
111 } else {
112 res = -1;
113 }
114#endif
115 } else {
116 res = mknodat(dirfd, path, mode, rdev);
117 }
118
119 return res;
120}
121
122#endif // FUSE_PASSTHROUGH_HELPERS_H_