1 /*
2   FUSE: Filesystem in Userspace
3   Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
4 
5   This program can be distributed under the terms of the GNU GPLv2.
6   See the file COPYING.
7 */
8 
9 /** @file
10  *
11  * This "filesystem" provides only a single file. The mountpoint
12  * needs to be a file rather than a directory. All writes to the
13  * file will be discarded, and reading the file always returns
14  * \0.
15  *
16  * Compile with:
17  *
18  *     gcc -Wall null.c `pkg-config fuse3 --cflags --libs` -o null
19  *
20  * ## Source code ##
21  * \include passthrough_fh.c
22  */
23 
24 
25 #define FUSE_USE_VERSION 31
26 
27 #include <fuse.h>
28 #include <fuse_lowlevel.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <time.h>
34 #include <errno.h>
35 
null_getattr(const char * path,struct stat * stbuf,struct fuse_file_info * fi)36 static int null_getattr(const char *path, struct stat *stbuf,
37 			struct fuse_file_info *fi)
38 {
39 	(void) fi;
40 
41 	if(strcmp(path, "/") != 0)
42 		return -ENOENT;
43 
44 	stbuf->st_mode = S_IFREG | 0644;
45 	stbuf->st_nlink = 1;
46 	stbuf->st_uid = getuid();
47 	stbuf->st_gid = getgid();
48 	stbuf->st_size = (1ULL << 32); /* 4G */
49 	stbuf->st_blocks = 0;
50 	stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = time(NULL);
51 
52 	return 0;
53 }
54 
null_truncate(const char * path,off_t size,struct fuse_file_info * fi)55 static int null_truncate(const char *path, off_t size,
56 			 struct fuse_file_info *fi)
57 {
58 	(void) size;
59 	(void) fi;
60 
61 	if(strcmp(path, "/") != 0)
62 		return -ENOENT;
63 
64 	return 0;
65 }
66 
null_open(const char * path,struct fuse_file_info * fi)67 static int null_open(const char *path, struct fuse_file_info *fi)
68 {
69 	(void) fi;
70 
71 	if(strcmp(path, "/") != 0)
72 		return -ENOENT;
73 
74 	return 0;
75 }
76 
null_read(const char * path,char * buf,size_t size,off_t offset,struct fuse_file_info * fi)77 static int null_read(const char *path, char *buf, size_t size,
78 		     off_t offset, struct fuse_file_info *fi)
79 {
80 	(void) buf;
81 	(void) offset;
82 	(void) fi;
83 
84 	if(strcmp(path, "/") != 0)
85 		return -ENOENT;
86 
87 	if (offset >= (1ULL << 32))
88 		return 0;
89 
90 	memset(buf, 0, size);
91 	return size;
92 }
93 
null_write(const char * path,const char * buf,size_t size,off_t offset,struct fuse_file_info * fi)94 static int null_write(const char *path, const char *buf, size_t size,
95 		      off_t offset, struct fuse_file_info *fi)
96 {
97 	(void) buf;
98 	(void) offset;
99 	(void) fi;
100 
101 	if(strcmp(path, "/") != 0)
102 		return -ENOENT;
103 
104 	return size;
105 }
106 
107 static const struct fuse_operations null_oper = {
108 	.getattr	= null_getattr,
109 	.truncate	= null_truncate,
110 	.open		= null_open,
111 	.read		= null_read,
112 	.write		= null_write,
113 };
114 
main(int argc,char * argv[])115 int main(int argc, char *argv[])
116 {
117 	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
118 	struct fuse_cmdline_opts opts;
119 	struct stat stbuf;
120 
121 	if (fuse_parse_cmdline(&args, &opts) != 0)
122 		return 1;
123 	fuse_opt_free_args(&args);
124 
125 	if (!opts.mountpoint) {
126 		fprintf(stderr, "missing mountpoint parameter\n");
127 		return 1;
128 	}
129 
130 	if (stat(opts.mountpoint, &stbuf) == -1) {
131 		fprintf(stderr ,"failed to access mountpoint %s: %s\n",
132 			opts.mountpoint, strerror(errno));
133 		free(opts.mountpoint);
134 		return 1;
135 	}
136 	free(opts.mountpoint);
137 	if (!S_ISREG(stbuf.st_mode)) {
138 		fprintf(stderr, "mountpoint is not a regular file\n");
139 		return 1;
140 	}
141 
142 	return fuse_main(argc, argv, &null_oper, NULL);
143 }
144