"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.10.4/doc/html/invalidate__path_8c_source.html" (9 Jun 2021, 54430 Bytes) of package /linux/misc/fuse-3.10.4.tar.xz:


Caution: In this restricted "Fossies" environment the current HTML page may not be correctly presentated and may have some non-functional links. You can here alternatively try to browse the pure source code or just view or download the uninterpreted raw source code. If the rendering is insufficient you may try to find and view the page on the project site itself.

libfuse
invalidate_path.c
Go to the documentation of this file.
1 /*
2  FUSE: Filesystem in Userspace
3  Copyright (C) 2016 Nikolaus Rath <Nikolaus@rath.org>
4  (C) 2017 EditShare LLC <slawek.rudnicki@editshare.com>
5 
6  This program can be distributed under the terms of the GNU GPLv2.
7  See the file COPYING.
8  */
9 
28 #define FUSE_USE_VERSION 34
29 
30 #include <fuse.h>
31 #include <fuse_lowlevel.h> /* for fuse_cmdline_opts */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <assert.h>
39 #include <stddef.h>
40 #include <unistd.h>
41 #include <pthread.h>
42 
43 /* We can't actually tell the kernel that there is no
44  timeout, so we just send a big value */
45 #define NO_TIMEOUT 500000
46 
47 #define MAX_STR_LEN 128
48 #define TIME_FILE_NAME "current_time"
49 #define TIME_FILE_INO 2
50 #define GROW_FILE_NAME "growing"
51 #define GROW_FILE_INO 3
52 
53 static char time_file_contents[MAX_STR_LEN];
54 static size_t grow_file_size;
55 
56 /* Command line parsing */
57 struct options {
58  int no_notify;
59  int update_interval;
60 };
61 static struct options options = {
62  .no_notify = 0,
63  .update_interval = 1,
64 };
65 
66 #define OPTION(t, p) { t, offsetof(struct options, p), 1 }
67 static const struct fuse_opt option_spec[] = {
68  OPTION("--no-notify", no_notify),
69  OPTION("--update-interval=%d", update_interval),
71 };
72 
73 static void *xmp_init(struct fuse_conn_info *conn, struct fuse_config *cfg)
74 {
75  (void) conn;
76  cfg->entry_timeout = NO_TIMEOUT;
77  cfg->attr_timeout = NO_TIMEOUT;
78  cfg->negative_timeout = 0;
79 
80  return NULL;
81 }
82 
83 static int xmp_getattr(const char *path,
84  struct stat *stbuf, struct fuse_file_info* fi) {
85  (void) fi;
86  if (strcmp(path, "/") == 0) {
87  stbuf->st_ino = 1;
88  stbuf->st_mode = S_IFDIR | 0755;
89  stbuf->st_nlink = 1;
90  } else if (strcmp(path, "/" TIME_FILE_NAME) == 0) {
91  stbuf->st_ino = TIME_FILE_INO;
92  stbuf->st_mode = S_IFREG | 0444;
93  stbuf->st_nlink = 1;
94  stbuf->st_size = strlen(time_file_contents);
95  } else if (strcmp(path, "/" GROW_FILE_NAME) == 0) {
96  stbuf->st_ino = GROW_FILE_INO;
97  stbuf->st_mode = S_IFREG | 0444;
98  stbuf->st_nlink = 1;
99  stbuf->st_size = grow_file_size;
100  } else {
101  return -ENOENT;
102  }
103 
104  return 0;
105 }
106 
107 static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
108  off_t offset, struct fuse_file_info *fi,
109  enum fuse_readdir_flags flags) {
110  (void) fi;
111  (void) offset;
112  (void) flags;
113  if (strcmp(path, "/") != 0) {
114  return -ENOTDIR;
115  } else {
116  (void) filler;
117  (void) buf;
118  struct stat file_stat;
119  xmp_getattr("/" TIME_FILE_NAME, &file_stat, NULL);
120  filler(buf, TIME_FILE_NAME, &file_stat, 0, 0);
121  xmp_getattr("/" GROW_FILE_NAME, &file_stat, NULL);
122  filler(buf, GROW_FILE_NAME, &file_stat, 0, 0);
123  return 0;
124  }
125 }
126 
127 static int xmp_open(const char *path, struct fuse_file_info *fi) {
128  (void) path;
129  /* Make cache persistent even if file is closed,
130  this makes it easier to see the effects */
131  fi->keep_cache = 1;
132  return 0;
133 }
134 
135 static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
136  struct fuse_file_info *fi) {
137  (void) fi;
138  (void) offset;
139  if (strcmp(path, "/" TIME_FILE_NAME) == 0) {
140  int file_length = strlen(time_file_contents);
141  int to_copy = offset + size <= file_length
142  ? size
143  : file_length - offset;
144  memcpy(buf, time_file_contents, to_copy);
145  return to_copy;
146  } else {
147  assert(strcmp(path, "/" GROW_FILE_NAME) == 0);
148  int to_copy = offset + size <= grow_file_size
149  ? size
150  : grow_file_size - offset;
151  memset(buf, 'x', to_copy);
152  return to_copy;
153  }
154 }
155 
156 static const struct fuse_operations xmp_oper = {
157  .init = xmp_init,
158  .getattr = xmp_getattr,
159  .readdir = xmp_readdir,
160  .open = xmp_open,
161  .read = xmp_read,
162 };
163 
164 static void update_fs(void) {
165  static int count = 0;
166  struct tm *now;
167  time_t t;
168  t = time(NULL);
169  now = localtime(&t);
170  assert(now != NULL);
171 
172  int time_file_size = strftime(time_file_contents, MAX_STR_LEN,
173  "The current time is %H:%M:%S\n", now);
174  assert(time_file_size != 0);
175 
176  grow_file_size = count++;
177 }
178 
179 static int invalidate(struct fuse *fuse, const char *path) {
180  int status = fuse_invalidate_path(fuse, path);
181  if (status == -ENOENT) {
182  return 0;
183  } else {
184  return status;
185  }
186 }
187 
188 static void* update_fs_loop(void *data) {
189  struct fuse *fuse = (struct fuse*) data;
190 
191  while (1) {
192  update_fs();
193  if (!options.no_notify) {
194  assert(invalidate(fuse, "/" TIME_FILE_NAME) == 0);
195  assert(invalidate(fuse, "/" GROW_FILE_NAME) == 0);
196  }
197  sleep(options.update_interval);
198  }
199  return NULL;
200 }
201 
202 static void show_help(const char *progname)
203 {
204  printf("usage: %s [options] <mountpoint>\n\n", progname);
205  printf("File-system specific options:\n"
206  " --update-interval=<secs> Update-rate of file system contents\n"
207  " --no-notify Disable kernel notifications\n"
208  "\n");
209 }
210 
211 int main(int argc, char *argv[]) {
212  struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
213  struct fuse *fuse;
214  struct fuse_cmdline_opts opts;
215  struct fuse_loop_config config;
216  int res;
217 
218  /* Initialize the files */
219  update_fs();
220 
221  if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1)
222  return 1;
223 
224  if (fuse_parse_cmdline(&args, &opts) != 0)
225  return 1;
226 
227  if (opts.show_version) {
228  printf("FUSE library version %s\n", fuse_pkgversion());
230  res = 0;
231  goto out1;
232  } else if (opts.show_help) {
233  show_help(argv[0]);
235  fuse_lib_help(&args);
236  res = 0;
237  goto out1;
238  } else if (!opts.mountpoint) {
239  fprintf(stderr, "error: no mountpoint specified\n");
240  res = 1;
241  goto out1;
242  }
243 
244  fuse = fuse_new(&args, &xmp_oper, sizeof(xmp_oper), NULL);
245  if (fuse == NULL) {
246  res = 1;
247  goto out1;
248  }
249 
250  if (fuse_mount(fuse,opts.mountpoint) != 0) {
251  res = 1;
252  goto out2;
253  }
254 
255  if (fuse_daemonize(opts.foreground) != 0) {
256  res = 1;
257  goto out3;
258  }
259 
260  pthread_t updater; /* Start thread to update file contents */
261  int ret = pthread_create(&updater, NULL, update_fs_loop, (void *) fuse);
262  if (ret != 0) {
263  fprintf(stderr, "pthread_create failed with %s\n", strerror(ret));
264  return 1;
265  };
266 
267  struct fuse_session *se = fuse_get_session(fuse);
268  if (fuse_set_signal_handlers(se) != 0) {
269  res = 1;
270  goto out3;
271  }
272 
273  if (opts.singlethread)
274  res = fuse_loop(fuse);
275  else {
276  config.clone_fd = opts.clone_fd;
277  config.max_idle_threads = opts.max_idle_threads;
278  res = fuse_loop_mt(fuse, &config);
279  }
280  if (res)
281  res = 1;
282 
284 out3:
285  fuse_unmount(fuse);
286 out2:
287  fuse_destroy(fuse);
288 out1:
289  free(opts.mountpoint);
290  fuse_opt_free_args(&args);
291  return res;
292 }
int fuse_daemonize(int foreground)
Definition: helper.c:225
unsigned long offset
Definition: fuse_opt.h:85
int fuse_loop(struct fuse *f)
Definition: fuse.c:4566
struct fuse * fuse_new(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *private_data)
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
Definition: fuse_opt.c:398
unsigned int keep_cache
Definition: fuse_common.h:64
fuse_readdir_flags
Definition: fuse.h:42
int fuse_parse_cmdline(struct fuse_args *args, struct fuse_cmdline_opts *opts)
Definition: helper.c:202
void fuse_cmdline_help(void)
Definition: helper.c:129
double negative_timeout
Definition: fuse.h:132
int fuse_set_signal_handlers(struct fuse_session *se)
Definition: fuse_signals.c:62
void fuse_remove_signal_handlers(struct fuse_session *se)
Definition: fuse_signals.c:79
void *(* init)(struct fuse_conn_info *conn, struct fuse_config *cfg)
Definition: fuse.h:581
void fuse_destroy(struct fuse *f)
Definition: fuse.c:5058
void fuse_lowlevel_version(void)
void fuse_opt_free_args(struct fuse_args *args)
Definition: fuse_opt.c:34
#define FUSE_OPT_END
Definition: fuse_opt.h:104
struct fuse_session * fuse_get_session(struct fuse *f)
Definition: fuse.c:4509
int fuse_invalidate_path(struct fuse *f, const char *path)
Definition: fuse.c:4636
double attr_timeout
Definition: fuse.h:138
int fuse_loop_mt(struct fuse *f, struct fuse_loop_config *config)
void fuse_lib_help(struct fuse_args *args)
Definition: fuse.c:4701
int(* fuse_fill_dir_t)(void *buf, const char *name, const struct stat *stbuf, off_t off, enum fuse_fill_dir_flags flags)
Definition: fuse.h:85
int fuse_mount(struct fuse *f, const char *mountpoint)
Definition: fuse.c:5108
void fuse_unmount(struct fuse *f)
Definition: fuse.c:5113
const char * fuse_pkgversion(void)
Definition: fuse.c:5122
#define FUSE_ARGS_INIT(argc, argv)
Definition: fuse_opt.h:123
double entry_timeout
Definition: fuse.h:122