"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.10.4/doc/html/notify__inval__entry_8c_source.html" (9 Jun 2021, 54908 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
notify_inval_entry.c
Go to the documentation of this file.
1 /*
2  FUSE: Filesystem in Userspace
3  Copyright (C) 2016 Nikolaus Rath <Nikolaus@rath.org>
4 
5  This program can be distributed under the terms of the GNU GPLv2.
6  See the file COPYING.
7 */
8 
76 #define FUSE_USE_VERSION 34
77 
78 #include <fuse_lowlevel.h>
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <errno.h>
83 #include <fcntl.h>
84 #include <assert.h>
85 #include <stddef.h>
86 #include <unistd.h>
87 #include <pthread.h>
88 
89 #define MAX_STR_LEN 128
90 static char file_name[MAX_STR_LEN];
91 static fuse_ino_t file_ino = 2;
92 static int lookup_cnt = 0;
93 
94 /* Command line parsing */
95 struct options {
96  int no_notify;
97  float timeout;
98  int update_interval;
99 };
100 static struct options options = {
101  .timeout = 5,
102  .no_notify = 0,
103  .update_interval = 1,
104 };
105 
106 #define OPTION(t, p) \
107  { t, offsetof(struct options, p), 1 }
108 static const struct fuse_opt option_spec[] = {
109  OPTION("--no-notify", no_notify),
110  OPTION("--update-interval=%d", update_interval),
111  OPTION("--timeout=%f", timeout),
113 };
114 
115 static int tfs_stat(fuse_ino_t ino, struct stat *stbuf) {
116  stbuf->st_ino = ino;
117  if (ino == FUSE_ROOT_ID) {
118  stbuf->st_mode = S_IFDIR | 0755;
119  stbuf->st_nlink = 1;
120  }
121 
122  else if (ino == file_ino) {
123  stbuf->st_mode = S_IFREG | 0000;
124  stbuf->st_nlink = 1;
125  stbuf->st_size = 0;
126  }
127 
128  else
129  return -1;
130 
131  return 0;
132 }
133 
134 static void tfs_lookup(fuse_req_t req, fuse_ino_t parent,
135  const char *name) {
136  struct fuse_entry_param e;
137  memset(&e, 0, sizeof(e));
138 
139  if (parent != FUSE_ROOT_ID)
140  goto err_out;
141  else if (strcmp(name, file_name) == 0) {
142  e.ino = file_ino;
143  lookup_cnt++;
144  } else
145  goto err_out;
146 
147  e.attr_timeout = options.timeout;
148  e.entry_timeout = options.timeout;
149  if (tfs_stat(e.ino, &e.attr) != 0)
150  goto err_out;
151  fuse_reply_entry(req, &e);
152  return;
153 
154 err_out:
155  fuse_reply_err(req, ENOENT);
156 }
157 
158 static void tfs_forget (fuse_req_t req, fuse_ino_t ino,
159  uint64_t nlookup) {
160  (void) req;
161  if(ino == file_ino)
162  lookup_cnt -= nlookup;
163  else
164  assert(ino == FUSE_ROOT_ID);
165  fuse_reply_none(req);
166 }
167 
168 static void tfs_getattr(fuse_req_t req, fuse_ino_t ino,
169  struct fuse_file_info *fi) {
170  struct stat stbuf;
171 
172  (void) fi;
173 
174  memset(&stbuf, 0, sizeof(stbuf));
175  if (tfs_stat(ino, &stbuf) != 0)
176  fuse_reply_err(req, ENOENT);
177  else
178  fuse_reply_attr(req, &stbuf, options.timeout);
179 }
180 
181 struct dirbuf {
182  char *p;
183  size_t size;
184 };
185 
186 static void dirbuf_add(fuse_req_t req, struct dirbuf *b, const char *name,
187  fuse_ino_t ino) {
188  struct stat stbuf;
189  size_t oldsize = b->size;
190  b->size += fuse_add_direntry(req, NULL, 0, name, NULL, 0);
191  b->p = (char *) realloc(b->p, b->size);
192  memset(&stbuf, 0, sizeof(stbuf));
193  stbuf.st_ino = ino;
194  fuse_add_direntry(req, b->p + oldsize, b->size - oldsize, name, &stbuf,
195  b->size);
196 }
197 
198 #define min(x, y) ((x) < (y) ? (x) : (y))
199 
200 static int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize,
201  off_t off, size_t maxsize) {
202  if (off < bufsize)
203  return fuse_reply_buf(req, buf + off,
204  min(bufsize - off, maxsize));
205  else
206  return fuse_reply_buf(req, NULL, 0);
207 }
208 
209 static void tfs_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
210  off_t off, struct fuse_file_info *fi) {
211  (void) fi;
212 
213  if (ino != FUSE_ROOT_ID)
214  fuse_reply_err(req, ENOTDIR);
215  else {
216  struct dirbuf b;
217 
218  memset(&b, 0, sizeof(b));
219  dirbuf_add(req, &b, file_name, file_ino);
220  reply_buf_limited(req, b.p, b.size, off, size);
221  free(b.p);
222  }
223 }
224 
225 static const struct fuse_lowlevel_ops tfs_oper = {
226  .lookup = tfs_lookup,
227  .getattr = tfs_getattr,
228  .readdir = tfs_readdir,
229  .forget = tfs_forget,
230 };
231 
232 static void update_fs(void) {
233  time_t t;
234  struct tm *now;
235  ssize_t ret;
236 
237  t = time(NULL);
238  now = localtime(&t);
239  assert(now != NULL);
240 
241  ret = strftime(file_name, MAX_STR_LEN,
242  "Time_is_%Hh_%Mm_%Ss", now);
243  assert(ret != 0);
244 }
245 
246 static void* update_fs_loop(void *data) {
247  struct fuse_session *se = (struct fuse_session*) data;
248  char *old_name;
249 
250  while(1) {
251  old_name = strdup(file_name);
252  update_fs();
253  if (!options.no_notify && lookup_cnt)
255  (se, FUSE_ROOT_ID, old_name, strlen(old_name)) == 0);
256  free(old_name);
257  sleep(options.update_interval);
258  }
259  return NULL;
260 }
261 
262 static void show_help(const char *progname)
263 {
264  printf("usage: %s [options] <mountpoint>\n\n", progname);
265  printf("File-system specific options:\n"
266  " --timeout=<secs> Timeout for kernel caches\n"
267  " --update-interval=<secs> Update-rate of file system contents\n"
268  " --no-notify Disable kernel notifications\n"
269  "\n");
270 }
271 
272 int main(int argc, char *argv[]) {
273  struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
274  struct fuse_session *se;
275  struct fuse_cmdline_opts opts;
276  struct fuse_loop_config config;
277  pthread_t updater;
278  int ret = -1;
279 
280  if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1)
281  return 1;
282 
283  if (fuse_parse_cmdline(&args, &opts) != 0)
284  return 1;
285  if (opts.show_help) {
286  show_help(argv[0]);
289  ret = 0;
290  goto err_out1;
291  } else if (opts.show_version) {
292  printf("FUSE library version %s\n", fuse_pkgversion());
294  ret = 0;
295  goto err_out1;
296  }
297 
298  /* Initial contents */
299  update_fs();
300 
301  se = fuse_session_new(&args, &tfs_oper,
302  sizeof(tfs_oper), NULL);
303  if (se == NULL)
304  goto err_out1;
305 
306  if (fuse_set_signal_handlers(se) != 0)
307  goto err_out2;
308 
309  if (fuse_session_mount(se, opts.mountpoint) != 0)
310  goto err_out3;
311 
312  fuse_daemonize(opts.foreground);
313 
314  /* Start thread to update file contents */
315  ret = pthread_create(&updater, NULL, update_fs_loop, (void *)se);
316  if (ret != 0) {
317  fprintf(stderr, "pthread_create failed with %s\n",
318  strerror(ret));
319  goto err_out3;
320  }
321 
322  /* Block until ctrl+c or fusermount -u */
323  if (opts.singlethread)
324  ret = fuse_session_loop(se);
325  else {
326  config.clone_fd = opts.clone_fd;
327  config.max_idle_threads = opts.max_idle_threads;
328  ret = fuse_session_loop_mt(se, &config);
329  }
330 
332 err_out3:
334 err_out2:
336 err_out1:
337  free(opts.mountpoint);
338  fuse_opt_free_args(&args);
339 
340  return ret ? 1 : 0;
341 }
342 
343 
void fuse_session_destroy(struct fuse_session *se)
int fuse_reply_err(fuse_req_t req, int err)
struct fuse_session * fuse_session_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, size_t op_size, void *userdata)
int fuse_session_loop(struct fuse_session *se)
Definition: fuse_loop.c:19
void fuse_lowlevel_help(void)
int fuse_daemonize(int foreground)
Definition: helper.c:225
int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
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
struct fuse_req * fuse_req_t
Definition: fuse_lowlevel.h:49
size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, const char *name, const struct stat *stbuf, off_t off)
Definition: fuse_lowlevel.h:59
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
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
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 fuse_lowlevel_version(void)
void fuse_reply_none(fuse_req_t req)
void fuse_opt_free_args(struct fuse_args *args)
Definition: fuse_opt.c:34
int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent, const char *name, size_t namelen)
int fuse_reply_attr(fuse_req_t req, const struct stat *attr, double attr_timeout)
void fuse_session_unmount(struct fuse_session *se)
#define FUSE_OPT_END
Definition: fuse_opt.h:104
void(* lookup)(fuse_req_t req, fuse_ino_t parent, const char *name)
#define FUSE_ROOT_ID
Definition: fuse_lowlevel.h:43
uint64_t fuse_ino_t
Definition: fuse_lowlevel.h:46
int fuse_session_loop_mt(struct fuse_session *se, struct fuse_loop_config *config)
const char * fuse_pkgversion(void)
Definition: fuse.c:5122
#define FUSE_ARGS_INIT(argc, argv)
Definition: fuse_opt.h:123
int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)