3 * Copyright © 2014-2016 Canonical, Inc
4 * Author: Serge Hallyn <serge.hallyn@ubuntu.com>
6 * See COPYING file for details.
13 #ifndef FUSE_USE_VERSION
14 #define FUSE_USE_VERSION 26
17 #define _FILE_OFFSET_BITS 64
35 #include <linux/sched.h>
36 #include <sys/epoll.h>
37 #include <sys/mount.h>
38 #include <sys/socket.h>
39 #include <linux/limits.h>
46 /* Functions to keep track of number of threads using the library */
48 static int users_count
;
49 static pthread_mutex_t user_count_mutex
= PTHREAD_MUTEX_INITIALIZER
;
50 static void lock_mutex(pthread_mutex_t
*l
)
54 if ((ret
= pthread_mutex_lock(l
)) != 0) {
55 lxcfs_error("returned:%d %s\n", ret
, strerror(ret
));
60 static void unlock_mutex(pthread_mutex_t
*l
)
64 if ((ret
= pthread_mutex_unlock(l
)) != 0) {
65 lxcfs_error("returned:%d %s\n", ret
, strerror(ret
));
70 static void users_lock(void)
72 lock_mutex(&user_count_mutex
);
75 static void users_unlock(void)
77 unlock_mutex(&user_count_mutex
);
80 static pthread_t loadavg_pid
= 0;
82 /* Returns zero on success */
83 static int start_loadavg(void) {
85 pthread_t (*load_daemon
)(int);
87 dlerror(); /* Clear any existing error */
89 load_daemon
= (pthread_t (*)(int)) dlsym(dlopen_handle
, "load_daemon");
92 lxcfs_error("load_daemon fails:%s\n", error
);
95 loadavg_pid
= load_daemon(1);
102 /* Returns zero on success */
103 static int stop_loadavg(void) {
105 int (*stop_load_daemon
)(pthread_t
);
107 stop_load_daemon
= (int (*)(pthread_t
)) dlsym(dlopen_handle
, "stop_load_daemon");
110 lxcfs_error("stop_load_daemon error: %s\n", error
);
114 if (stop_load_daemon(loadavg_pid
) != 0)
120 static volatile sig_atomic_t need_reload
;
122 /* do_reload - reload the dynamic library. Done under
123 * lock and when we know the user_count was 0 */
124 static void do_reload(void)
126 char lxcfs_lib_path
[PATH_MAX
];
132 lxcfs_debug("%s\n", "Closing liblxcfs.so handle.");
133 dlclose(dlopen_handle
);
136 /* First try loading using ld.so */
137 dlopen_handle
= dlopen("liblxcfs.so", RTLD_LAZY
);
139 lxcfs_debug("%s\n", "Successfully called dlopen() on liblxcfs.so.");
144 /* LIBDIR: autoconf will setup this MACRO. Default value is $PREFIX/lib */
145 snprintf(lxcfs_lib_path
, PATH_MAX
, "%s/lxcfs/liblxcfs.so", LIBDIR
);
147 snprintf(lxcfs_lib_path
, PATH_MAX
, "/usr/local/lib/lxcfs/liblxcfs.so");
149 dlopen_handle
= dlopen(lxcfs_lib_path
, RTLD_LAZY
);
150 if (!dlopen_handle
) {
151 lxcfs_error("Failed to open liblxcfs.so: %s.\n", dlerror());
160 lxcfs_error("%s\n", "lxcfs: reloaded");
164 static void up_users(void)
167 if (users_count
== 0 && need_reload
)
173 static void down_users(void)
180 static void reload_handler(int sig
)
185 /* Functions to run the library methods */
186 static int do_cg_getattr(const char *path
, struct stat
*sb
)
188 int (*cg_getattr
)(const char *path
, struct stat
*sb
);
190 dlerror(); /* Clear any existing error */
191 cg_getattr
= (int (*)(const char *, struct stat
*)) dlsym(dlopen_handle
, "cg_getattr");
194 lxcfs_error("%s\n", error
);
198 return cg_getattr(path
, sb
);
201 static int do_proc_getattr(const char *path
, struct stat
*sb
)
203 int (*proc_getattr
)(const char *path
, struct stat
*sb
);
205 dlerror(); /* Clear any existing error */
206 proc_getattr
= (int (*)(const char *, struct stat
*)) dlsym(dlopen_handle
, "proc_getattr");
209 lxcfs_error("%s\n", error
);
213 return proc_getattr(path
, sb
);
216 static int do_sys_getattr(const char *path
, struct stat
*sb
)
218 int (*sys_getattr
)(const char *path
, struct stat
*sb
);
220 dlerror(); /* Clear any existing error */
221 sys_getattr
= (int (*)(const char *, struct stat
*)) dlsym(dlopen_handle
, "sys_getattr");
224 lxcfs_error("%s\n", error
);
228 return sys_getattr(path
, sb
);
231 static int do_cg_read(const char *path
, char *buf
, size_t size
, off_t offset
,
232 struct fuse_file_info
*fi
)
234 int (*cg_read
)(const char *path
, char *buf
, size_t size
, off_t offset
,
235 struct fuse_file_info
*fi
);
238 dlerror(); /* Clear any existing error */
239 cg_read
= (int (*)(const char *, char *, size_t, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_read");
242 lxcfs_error("%s\n", error
);
246 return cg_read(path
, buf
, size
, offset
, fi
);
249 static int do_proc_read(const char *path
, char *buf
, size_t size
, off_t offset
,
250 struct fuse_file_info
*fi
)
252 int (*proc_read
)(const char *path
, char *buf
, size_t size
, off_t offset
,
253 struct fuse_file_info
*fi
);
256 dlerror(); /* Clear any existing error */
257 proc_read
= (int (*)(const char *, char *, size_t, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "proc_read");
260 lxcfs_error("%s\n", error
);
264 return proc_read(path
, buf
, size
, offset
, fi
);
267 static int do_sys_read(const char *path
, char *buf
, size_t size
, off_t offset
,
268 struct fuse_file_info
*fi
)
270 int (*sys_read
)(const char *path
, char *buf
, size_t size
, off_t offset
,
271 struct fuse_file_info
*fi
);
274 dlerror(); /* Clear any existing error */
275 sys_read
= (int (*)(const char *, char *, size_t, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_read");
278 lxcfs_error("%s\n", error
);
282 return sys_read(path
, buf
, size
, offset
, fi
);
285 static int do_cg_write(const char *path
, const char *buf
, size_t size
, off_t offset
,
286 struct fuse_file_info
*fi
)
288 int (*cg_write
)(const char *path
, const char *buf
, size_t size
, off_t offset
,
289 struct fuse_file_info
*fi
);
291 dlerror(); /* Clear any existing error */
292 cg_write
= (int (*)(const char *, const char *, size_t, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_write");
295 lxcfs_error("%s\n", error
);
299 return cg_write(path
, buf
, size
, offset
, fi
);
302 static int do_cg_mkdir(const char *path
, mode_t mode
)
304 int (*cg_mkdir
)(const char *path
, mode_t mode
);
306 dlerror(); /* Clear any existing error */
307 cg_mkdir
= (int (*)(const char *, mode_t
)) dlsym(dlopen_handle
, "cg_mkdir");
310 lxcfs_error("%s\n", error
);
314 return cg_mkdir(path
, mode
);
317 static int do_cg_chown(const char *path
, uid_t uid
, gid_t gid
)
319 int (*cg_chown
)(const char *path
, uid_t uid
, gid_t gid
);
321 dlerror(); /* Clear any existing error */
322 cg_chown
= (int (*)(const char *, uid_t
, gid_t
)) dlsym(dlopen_handle
, "cg_chown");
325 lxcfs_error("%s\n", error
);
329 return cg_chown(path
, uid
, gid
);
332 static int do_cg_rmdir(const char *path
)
334 int (*cg_rmdir
)(const char *path
);
336 dlerror(); /* Clear any existing error */
337 cg_rmdir
= (int (*)(const char *path
)) dlsym(dlopen_handle
, "cg_rmdir");
340 lxcfs_error("%s\n", error
);
344 return cg_rmdir(path
);
347 static int do_cg_chmod(const char *path
, mode_t mode
)
349 int (*cg_chmod
)(const char *path
, mode_t mode
);
351 dlerror(); /* Clear any existing error */
352 cg_chmod
= (int (*)(const char *, mode_t
)) dlsym(dlopen_handle
, "cg_chmod");
355 lxcfs_error("%s\n", error
);
359 return cg_chmod(path
, mode
);
362 static int do_cg_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
363 struct fuse_file_info
*fi
)
365 int (*cg_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
366 struct fuse_file_info
*fi
);
369 dlerror(); /* Clear any existing error */
370 cg_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_readdir");
373 lxcfs_error("%s\n", error
);
377 return cg_readdir(path
, buf
, filler
, offset
, fi
);
380 static int do_proc_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
381 struct fuse_file_info
*fi
)
383 int (*proc_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
384 struct fuse_file_info
*fi
);
387 dlerror(); /* Clear any existing error */
388 proc_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "proc_readdir");
391 lxcfs_error("%s\n", error
);
395 return proc_readdir(path
, buf
, filler
, offset
, fi
);
398 static int do_sys_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
399 struct fuse_file_info
*fi
)
401 int (*sys_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
402 struct fuse_file_info
*fi
);
405 dlerror(); /* Clear any existing error */
406 sys_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_readdir");
409 lxcfs_error("%s\n", error
);
413 return sys_readdir(path
, buf
, filler
, offset
, fi
);
417 static int do_cg_open(const char *path
, struct fuse_file_info
*fi
)
419 int (*cg_open
)(const char *path
, struct fuse_file_info
*fi
);
421 dlerror(); /* Clear any existing error */
422 cg_open
= (int (*)(const char *, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_open");
425 lxcfs_error("%s\n", error
);
429 return cg_open(path
, fi
);
432 static int do_cg_access(const char *path
, int mode
)
434 int (*cg_access
)(const char *path
, int mode
);
436 dlerror(); /* Clear any existing error */
437 cg_access
= (int (*)(const char *, int mode
)) dlsym(dlopen_handle
, "cg_access");
440 lxcfs_error("%s\n", error
);
444 return cg_access(path
, mode
);
447 static int do_proc_open(const char *path
, struct fuse_file_info
*fi
)
449 int (*proc_open
)(const char *path
, struct fuse_file_info
*fi
);
451 dlerror(); /* Clear any existing error */
452 proc_open
= (int (*)(const char *path
, struct fuse_file_info
*fi
)) dlsym(dlopen_handle
, "proc_open");
455 lxcfs_error("%s\n", error
);
459 return proc_open(path
, fi
);
462 static int do_proc_access(const char *path
, int mode
)
464 int (*proc_access
)(const char *path
, int mode
);
466 dlerror(); /* Clear any existing error */
467 proc_access
= (int (*)(const char *, int mode
)) dlsym(dlopen_handle
, "proc_access");
470 lxcfs_error("%s\n", error
);
474 return proc_access(path
, mode
);
477 static int do_sys_open(const char *path
, struct fuse_file_info
*fi
)
479 int (*sys_open
)(const char *path
, struct fuse_file_info
*fi
);
481 dlerror(); /* Clear any existing error */
482 sys_open
= (int (*)(const char *path
, struct fuse_file_info
*fi
)) dlsym(dlopen_handle
, "sys_open");
485 lxcfs_error("%s\n", error
);
489 return sys_open(path
, fi
);
492 static int do_sys_access(const char *path
, int mode
)
494 int (*sys_access
)(const char *path
, int mode
);
496 dlerror(); /* Clear any existing error */
497 sys_access
= (int (*)(const char *, int mode
)) dlsym(dlopen_handle
, "sys_access");
500 lxcfs_error("%s\n", error
);
504 return sys_access(path
, mode
);
508 static int do_cg_release(const char *path
, struct fuse_file_info
*fi
)
510 int (*cg_release
)(const char *path
, struct fuse_file_info
*fi
);
512 dlerror(); /* Clear any existing error */
513 cg_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_release");
516 lxcfs_error("%s\n", error
);
520 return cg_release(path
, fi
);
523 static int do_proc_release(const char *path
, struct fuse_file_info
*fi
)
525 int (*proc_release
)(const char *path
, struct fuse_file_info
*fi
);
527 dlerror(); /* Clear any existing error */
528 proc_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "proc_release");
531 lxcfs_error("%s\n", error
);
535 return proc_release(path
, fi
);
538 static int do_sys_release(const char *path
, struct fuse_file_info
*fi
)
540 int (*sys_release
)(const char *path
, struct fuse_file_info
*fi
);
542 dlerror(); /* Clear any existing error */
543 sys_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_release");
546 lxcfs_error("%s\n", error
);
550 return sys_release(path
, fi
);
553 static int do_cg_opendir(const char *path
, struct fuse_file_info
*fi
)
555 int (*cg_opendir
)(const char *path
, struct fuse_file_info
*fi
);
557 dlerror(); /* Clear any existing error */
558 cg_opendir
= (int (*)(const char *path
, struct fuse_file_info
*fi
)) dlsym(dlopen_handle
, "cg_opendir");
561 lxcfs_error("%s\n", error
);
565 return cg_opendir(path
, fi
);
568 static int do_cg_releasedir(const char *path
, struct fuse_file_info
*fi
)
570 int (*cg_releasedir
)(const char *path
, struct fuse_file_info
*fi
);
572 dlerror(); /* Clear any existing error */
573 cg_releasedir
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_releasedir");
576 lxcfs_error("%s\n", error
);
580 return cg_releasedir(path
, fi
);
583 static int do_sys_releasedir(const char *path
, struct fuse_file_info
*fi
)
585 int (*sys_releasedir
)(const char *path
, struct fuse_file_info
*fi
);
587 dlerror(); /* Clear any existing error */
588 sys_releasedir
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_releasedir");
591 lxcfs_error("%s\n", error
);
595 return sys_releasedir(path
, fi
);
600 * these just delegate to the /proc and /cgroup ops as
604 static int lxcfs_getattr(const char *path
, struct stat
*sb
)
609 if (strcmp(path
, "/") == 0) {
610 if (clock_gettime(CLOCK_REALTIME
, &now
) < 0)
612 sb
->st_uid
= sb
->st_gid
= 0;
613 sb
->st_atim
= sb
->st_mtim
= sb
->st_ctim
= now
;
615 sb
->st_mode
= S_IFDIR
| 00755;
620 if (strncmp(path
, "/cgroup", 7) == 0) {
622 ret
= do_cg_getattr(path
, sb
);
626 if (strncmp(path
, "/proc", 5) == 0) {
628 ret
= do_proc_getattr(path
, sb
);
632 if (strncmp(path
, "/sys", 4) == 0) {
634 ret
= do_sys_getattr(path
, sb
);
641 static int lxcfs_opendir(const char *path
, struct fuse_file_info
*fi
)
644 if (strcmp(path
, "/") == 0)
647 if (strncmp(path
, "/cgroup", 7) == 0) {
649 ret
= do_cg_opendir(path
, fi
);
653 if (strcmp(path
, "/proc") == 0)
655 if (strncmp(path
, "/sys", 4) == 0)
661 static int lxcfs_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
662 struct fuse_file_info
*fi
)
665 if (strcmp(path
, "/") == 0) {
666 if (filler(buf
, ".", NULL
, 0) != 0 ||
667 filler(buf
, "..", NULL
, 0) != 0 ||
668 filler(buf
, "proc", NULL
, 0) != 0 ||
669 filler(buf
, "sys", NULL
, 0) != 0 ||
670 filler(buf
, "cgroup", NULL
, 0) != 0)
674 if (strncmp(path
, "/cgroup", 7) == 0) {
676 ret
= do_cg_readdir(path
, buf
, filler
, offset
, fi
);
680 if (strcmp(path
, "/proc") == 0) {
682 ret
= do_proc_readdir(path
, buf
, filler
, offset
, fi
);
687 if (strncmp(path
, "/sys", 4) == 0) {
689 ret
= do_sys_readdir(path
, buf
, filler
, offset
, fi
);
697 static int lxcfs_access(const char *path
, int mode
)
701 if (strcmp(path
, "/") == 0 && (mode
& W_OK
) == 0)
704 if (strncmp(path
, "/cgroup", 7) == 0) {
706 ret
= do_cg_access(path
, mode
);
710 if (strncmp(path
, "/proc", 5) == 0) {
712 ret
= do_proc_access(path
, mode
);
716 if (strncmp(path
, "/sys", 4) == 0) {
718 ret
= do_sys_access(path
, mode
);
727 static int lxcfs_releasedir(const char *path
, struct fuse_file_info
*fi
)
730 if (strcmp(path
, "/") == 0)
732 if (strncmp(path
, "/cgroup", 7) == 0) {
734 ret
= do_cg_releasedir(path
, fi
);
738 if (strcmp(path
, "/proc") == 0)
740 if (strncmp(path
, "/sys", 4) == 0){
742 ret
= do_sys_releasedir(path
, fi
);
750 static int lxcfs_open(const char *path
, struct fuse_file_info
*fi
)
753 if (strncmp(path
, "/cgroup", 7) == 0) {
755 ret
= do_cg_open(path
, fi
);
759 if (strncmp(path
, "/proc", 5) == 0) {
761 ret
= do_proc_open(path
, fi
);
765 if (strncmp(path
, "/sys", 4) == 0) {
767 ret
= do_sys_open(path
, fi
);
776 static int lxcfs_read(const char *path
, char *buf
, size_t size
, off_t offset
,
777 struct fuse_file_info
*fi
)
780 if (strncmp(path
, "/cgroup", 7) == 0) {
782 ret
= do_cg_read(path
, buf
, size
, offset
, fi
);
786 if (strncmp(path
, "/proc", 5) == 0) {
788 ret
= do_proc_read(path
, buf
, size
, offset
, fi
);
792 if (strncmp(path
, "/sys", 4) == 0) {
794 ret
= do_sys_read(path
, buf
, size
, offset
, fi
);
803 int lxcfs_write(const char *path
, const char *buf
, size_t size
, off_t offset
,
804 struct fuse_file_info
*fi
)
807 if (strncmp(path
, "/cgroup", 7) == 0) {
809 ret
= do_cg_write(path
, buf
, size
, offset
, fi
);
817 static int lxcfs_flush(const char *path
, struct fuse_file_info
*fi
)
822 static int lxcfs_release(const char *path
, struct fuse_file_info
*fi
)
825 if (strncmp(path
, "/cgroup", 7) == 0) {
827 ret
= do_cg_release(path
, fi
);
831 if (strncmp(path
, "/proc", 5) == 0) {
833 ret
= do_proc_release(path
, fi
);
837 if (strncmp(path
, "/sys", 4) == 0) {
839 ret
= do_sys_release(path
, fi
);
848 static int lxcfs_fsync(const char *path
, int datasync
, struct fuse_file_info
*fi
)
853 int lxcfs_mkdir(const char *path
, mode_t mode
)
856 if (strncmp(path
, "/cgroup", 7) == 0) {
858 ret
= do_cg_mkdir(path
, mode
);
866 int lxcfs_chown(const char *path
, uid_t uid
, gid_t gid
)
869 if (strncmp(path
, "/cgroup", 7) == 0) {
871 ret
= do_cg_chown(path
, uid
, gid
);
876 if (strncmp(path
, "/proc", 5) == 0)
879 if (strncmp(path
, "/sys", 4) == 0)
885 * cat first does a truncate before doing ops->write. This doesn't
886 * really make sense for cgroups. So just return 0 always but do
889 int lxcfs_truncate(const char *path
, off_t newsize
)
891 if (strncmp(path
, "/cgroup", 7) == 0)
896 int lxcfs_rmdir(const char *path
)
899 if (strncmp(path
, "/cgroup", 7) == 0) {
901 ret
= do_cg_rmdir(path
);
908 int lxcfs_chmod(const char *path
, mode_t mode
)
911 if (strncmp(path
, "/cgroup", 7) == 0) {
913 ret
= do_cg_chmod(path
, mode
);
918 if (strncmp(path
, "/proc", 5) == 0)
921 if (strncmp(path
, "/sys", 4) == 0)
927 const struct fuse_operations lxcfs_ops
= {
928 .getattr
= lxcfs_getattr
,
932 .mkdir
= lxcfs_mkdir
,
934 .rmdir
= lxcfs_rmdir
,
938 .chmod
= lxcfs_chmod
,
939 .chown
= lxcfs_chown
,
940 .truncate
= lxcfs_truncate
,
945 .release
= lxcfs_release
,
946 .write
= lxcfs_write
,
949 .flush
= lxcfs_flush
,
950 .fsync
= lxcfs_fsync
,
957 .opendir
= lxcfs_opendir
,
958 .readdir
= lxcfs_readdir
,
959 .releasedir
= lxcfs_releasedir
,
964 .access
= lxcfs_access
,
972 fprintf(stderr
, "Usage:\n");
973 fprintf(stderr
, "\n");
974 fprintf(stderr
, "lxcfs [-f|-d] -u -l -n [-p pidfile] mountpoint\n");
975 fprintf(stderr
, " -f running foreground by default; -d enable debug output \n");
976 fprintf(stderr
, " -l use loadavg \n");
977 fprintf(stderr
, " -u no swap \n");
978 fprintf(stderr
, " Default pidfile is %s/lxcfs.pid\n", RUNTIME_PATH
);
979 fprintf(stderr
, "lxcfs -h\n");
980 fprintf(stderr
, "lxcfs -v\n");
984 static bool is_help(char *w
)
986 if (strcmp(w
, "-h") == 0 ||
987 strcmp(w
, "--help") == 0 ||
988 strcmp(w
, "-help") == 0 ||
989 strcmp(w
, "help") == 0)
994 static bool is_version(char *w
)
996 if (strcmp(w
, "-v") == 0 ||
997 strcmp(w
, "--version") == 0 ||
998 strcmp(w
, "-version") == 0 ||
999 strcmp(w
, "version") == 0)
1004 bool swallow_arg(int *argcp
, char *argv
[], char *which
)
1008 for (i
= 1; argv
[i
]; i
++) {
1009 if (strcmp(argv
[i
], which
) != 0)
1011 for (; argv
[i
]; i
++) {
1012 argv
[i
] = argv
[i
+1];
1020 bool swallow_option(int *argcp
, char *argv
[], char *opt
, char **v
)
1024 for (i
= 1; argv
[i
]; i
++) {
1027 if (strcmp(argv
[i
], opt
) != 0)
1030 *v
= strdup(argv
[i
+1]);
1032 for (; argv
[i
+1]; i
++) {
1033 argv
[i
] = argv
[i
+2];
1041 static int set_pidfile(char *pidfile
)
1047 fl
.l_type
= F_WRLCK
;
1048 fl
.l_whence
= SEEK_SET
;
1052 fd
= open(pidfile
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
1054 fprintf(stderr
, "Could not open pidfile %s: %m\n", pidfile
);
1058 if (fcntl(fd
, F_SETLK
, &fl
) == -1) {
1059 if (errno
== EAGAIN
|| errno
== EACCES
) {
1060 fprintf(stderr
, "PID file '%s' is already locked.\n", pidfile
);
1064 fprintf(stderr
, "Warning; unable to lock PID file, proceeding.\n");
1067 if (ftruncate(fd
, 0) == -1) {
1068 fprintf(stderr
, "Error truncating PID file '%s': %m", pidfile
);
1073 snprintf(buf
, 50, "%ld\n", (long) getpid());
1074 if (write(fd
, buf
, strlen(buf
)) != strlen(buf
)) {
1075 fprintf(stderr
, "Error writing to PID file '%s': %m", pidfile
);
1083 int main(int argc
, char *argv
[])
1085 int ret
= EXIT_FAILURE
;
1087 char *pidfile
= NULL
, *saveptr
= NULL
, *token
= NULL
, *v
= NULL
;
1089 bool debug
= false, nonempty
= false;
1090 bool load_use
= false;
1092 * what we pass to fuse_main is:
1093 * argv[0] -s [-f|-d] -o allow_other,directio argv[1] NULL
1095 int nargs
= 5, cnt
= 0;
1097 struct lxcfs_opts
*opts
;
1099 opts
= malloc(sizeof(struct lxcfs_opts
));
1101 fprintf(stderr
, "Error allocating memory for options.\n");
1104 opts
->swap_off
= false;
1105 opts
->use_pidfd
= false;
1107 /* accomodate older init scripts */
1108 swallow_arg(&argc
, argv
, "-s");
1109 swallow_arg(&argc
, argv
, "-f");
1110 debug
= swallow_arg(&argc
, argv
, "-d");
1111 if (swallow_arg(&argc
, argv
, "-l"))
1113 if (swallow_arg(&argc
, argv
, "-u"))
1114 opts
->swap_off
= true;
1116 if (swallow_arg(&argc
, argv
, "--pidfd"))
1117 opts
->use_pidfd
= true;
1119 if (swallow_option(&argc
, argv
, "-o", &v
)) {
1120 /* Parse multiple values */
1121 for (; (token
= strtok_r(v
, ",", &saveptr
)); v
= NULL
) {
1122 if (strcmp(token
, "allow_other") == 0) {
1123 /* Noop. this is the default. Always enabled. */
1124 } else if (strcmp(token
, "nonempty") == 0) {
1128 fprintf(stderr
, "Warning: unexpected fuse option %s\n", v
);
1135 if (swallow_option(&argc
, argv
, "-p", &v
))
1138 if (argc
== 2 && is_version(argv
[1])) {
1139 fprintf(stderr
, "%s\n", VERSION
);
1143 if (argc
!= 2 || is_help(argv
[1]))
1147 if (signal(SIGUSR1
, reload_handler
) == SIG_ERR
) {
1148 fprintf(stderr
, "Error setting USR1 signal handler: %m\n");
1152 newargv
[cnt
++] = argv
[0];
1154 newargv
[cnt
++] = "-d";
1156 newargv
[cnt
++] = "-f";
1157 newargv
[cnt
++] = "-o";
1159 newargv
[cnt
++] = "allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5,nonempty";
1161 newargv
[cnt
++] = "allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5";
1162 newargv
[cnt
++] = argv
[1];
1163 newargv
[cnt
++] = NULL
;
1166 pidfile_len
= strlen(RUNTIME_PATH
) + strlen("/lxcfs.pid") + 1;
1167 pidfile
= alloca(pidfile_len
);
1168 snprintf(pidfile
, pidfile_len
, "%s/lxcfs.pid", RUNTIME_PATH
);
1170 if ((pidfd
= set_pidfile(pidfile
)) < 0)
1173 if (load_use
&& start_loadavg() != 0)
1176 if (!fuse_main(nargs
, newargv
, &lxcfs_ops
, opts
))
1183 dlclose(dlopen_handle
);