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
,
253 off_t offset
, 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
,
271 off_t offset
, 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
,
289 off_t offset
, 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
);
307 dlerror(); /* Clear any existing error */
308 __cg_mkdir
= (int (*)(const char *, mode_t
)) dlsym(dlopen_handle
, "cg_mkdir");
311 lxcfs_error("%s\n", error
);
315 return __cg_mkdir(path
, mode
);
318 static int do_cg_chown(const char *path
, uid_t uid
, gid_t gid
)
320 int (*__cg_chown
)(const char *path
, uid_t uid
, gid_t gid
);
323 dlerror(); /* Clear any existing error */
324 __cg_chown
= (int (*)(const char *, uid_t
, gid_t
)) dlsym(dlopen_handle
, "cg_chown");
327 lxcfs_error("%s\n", error
);
331 return __cg_chown(path
, uid
, gid
);
334 static int do_cg_rmdir(const char *path
)
336 int (*__cg_rmdir
)(const char *path
);
339 dlerror(); /* Clear any existing error */
340 __cg_rmdir
= (int (*)(const char *path
)) dlsym(dlopen_handle
, "cg_rmdir");
343 lxcfs_error("%s\n", error
);
347 return __cg_rmdir(path
);
350 static int do_cg_chmod(const char *path
, mode_t mode
)
352 int (*__cg_chmod
)(const char *path
, mode_t mode
);
355 dlerror(); /* Clear any existing error */
356 __cg_chmod
= (int (*)(const char *, mode_t
)) dlsym(dlopen_handle
, "cg_chmod");
359 lxcfs_error("%s\n", error
);
363 return __cg_chmod(path
, mode
);
366 static int do_cg_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
367 off_t offset
, struct fuse_file_info
*fi
)
369 int (*__cg_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
,
370 off_t offset
, struct fuse_file_info
*fi
);
373 dlerror(); /* Clear any existing error */
374 __cg_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_readdir");
377 lxcfs_error("%s\n", error
);
381 return __cg_readdir(path
, buf
, filler
, offset
, fi
);
384 static int do_proc_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
385 off_t offset
, struct fuse_file_info
*fi
)
387 int (*__proc_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
,
388 off_t offset
, struct fuse_file_info
*fi
);
391 dlerror(); /* Clear any existing error */
392 __proc_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "proc_readdir");
395 lxcfs_error("%s\n", error
);
399 return __proc_readdir(path
, buf
, filler
, offset
, fi
);
402 static int do_sys_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
,
403 off_t offset
, struct fuse_file_info
*fi
)
405 int (*__sys_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
406 struct fuse_file_info
*fi
);
409 dlerror(); /* Clear any existing error */
410 __sys_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_readdir");
413 lxcfs_error("%s\n", error
);
417 return __sys_readdir(path
, buf
, filler
, offset
, fi
);
421 static int do_cg_open(const char *path
, struct fuse_file_info
*fi
)
423 int (*__cg_open
)(const char *path
, struct fuse_file_info
*fi
);
425 dlerror(); /* Clear any existing error */
426 __cg_open
= (int (*)(const char *, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_open");
429 lxcfs_error("%s\n", error
);
433 return __cg_open(path
, fi
);
436 static int do_cg_access(const char *path
, int mode
)
438 int (*__cg_access
)(const char *path
, int mode
);
440 dlerror(); /* Clear any existing error */
441 __cg_access
= (int (*)(const char *, int mode
)) dlsym(dlopen_handle
, "cg_access");
444 lxcfs_error("%s\n", error
);
448 return __cg_access(path
, mode
);
451 static int do_proc_open(const char *path
, struct fuse_file_info
*fi
)
453 int (*__proc_open
)(const char *path
, struct fuse_file_info
*fi
);
455 dlerror(); /* Clear any existing error */
456 __proc_open
= (int (*)(const char *path
, struct fuse_file_info
*fi
)) dlsym(dlopen_handle
, "proc_open");
459 lxcfs_error("%s\n", error
);
463 return __proc_open(path
, fi
);
466 static int do_proc_access(const char *path
, int mode
)
468 int (*__proc_access
)(const char *path
, int mode
);
470 dlerror(); /* Clear any existing error */
471 __proc_access
= (int (*)(const char *, int mode
)) dlsym(dlopen_handle
, "proc_access");
474 lxcfs_error("%s\n", error
);
478 return __proc_access(path
, mode
);
481 static int do_sys_open(const char *path
, struct fuse_file_info
*fi
)
483 int (*__sys_open
)(const char *path
, struct fuse_file_info
*fi
);
485 dlerror(); /* Clear any existing error */
486 __sys_open
= (int (*)(const char *path
, struct fuse_file_info
*fi
)) dlsym(dlopen_handle
, "sys_open");
489 lxcfs_error("%s\n", error
);
493 return __sys_open(path
, fi
);
496 static int do_sys_access(const char *path
, int mode
)
498 int (*__sys_access
)(const char *path
, int mode
);
500 dlerror(); /* Clear any existing error */
501 __sys_access
= (int (*)(const char *, int mode
)) dlsym(dlopen_handle
, "sys_access");
504 lxcfs_error("%s\n", error
);
508 return __sys_access(path
, mode
);
511 static int do_cg_release(const char *path
, struct fuse_file_info
*fi
)
513 int (*__cg_release
)(const char *path
, struct fuse_file_info
*fi
);
515 dlerror(); /* Clear any existing error */
516 __cg_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_release");
519 lxcfs_error("%s\n", error
);
523 return __cg_release(path
, fi
);
526 static int do_proc_release(const char *path
, struct fuse_file_info
*fi
)
528 int (*__proc_release
)(const char *path
, struct fuse_file_info
*fi
);
530 dlerror(); /* Clear any existing error */
531 __proc_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "proc_release");
534 lxcfs_error("%s\n", error
);
538 return __proc_release(path
, fi
);
541 static int do_sys_release(const char *path
, struct fuse_file_info
*fi
)
543 int (*__sys_release
)(const char *path
, struct fuse_file_info
*fi
);
545 dlerror(); /* Clear any existing error */
546 __sys_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_release");
549 lxcfs_error("%s\n", error
);
553 return __sys_release(path
, fi
);
556 static int do_cg_opendir(const char *path
, struct fuse_file_info
*fi
)
558 int (*__cg_opendir
)(const char *path
, struct fuse_file_info
*fi
);
560 dlerror(); /* Clear any existing error */
561 __cg_opendir
= (int (*)(const char *path
, struct fuse_file_info
*fi
)) dlsym(dlopen_handle
, "cg_opendir");
564 lxcfs_error("%s\n", error
);
568 return __cg_opendir(path
, fi
);
571 static int do_cg_releasedir(const char *path
, struct fuse_file_info
*fi
)
573 int (*__cg_releasedir
)(const char *path
, struct fuse_file_info
*fi
);
575 dlerror(); /* Clear any existing error */
576 __cg_releasedir
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_releasedir");
579 lxcfs_error("%s\n", error
);
583 return __cg_releasedir(path
, fi
);
586 static int do_sys_releasedir(const char *path
, struct fuse_file_info
*fi
)
588 int (*__sys_releasedir
)(const char *path
, struct fuse_file_info
*fi
);
590 dlerror(); /* Clear any existing error */
591 __sys_releasedir
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_releasedir");
594 lxcfs_error("%s\n", error
);
598 return __sys_releasedir(path
, fi
);
603 * these just delegate to the /proc and /cgroup ops as
607 static int lxcfs_getattr(const char *path
, struct stat
*sb
)
612 if (strcmp(path
, "/") == 0) {
613 if (clock_gettime(CLOCK_REALTIME
, &now
) < 0)
615 sb
->st_uid
= sb
->st_gid
= 0;
616 sb
->st_atim
= sb
->st_mtim
= sb
->st_ctim
= now
;
618 sb
->st_mode
= S_IFDIR
| 00755;
623 if (strncmp(path
, "/cgroup", 7) == 0) {
625 ret
= do_cg_getattr(path
, sb
);
629 if (strncmp(path
, "/proc", 5) == 0) {
631 ret
= do_proc_getattr(path
, sb
);
635 if (strncmp(path
, "/sys", 4) == 0) {
637 ret
= do_sys_getattr(path
, sb
);
644 static int lxcfs_opendir(const char *path
, struct fuse_file_info
*fi
)
647 if (strcmp(path
, "/") == 0)
650 if (strncmp(path
, "/cgroup", 7) == 0) {
652 ret
= do_cg_opendir(path
, fi
);
656 if (strcmp(path
, "/proc") == 0)
658 if (strncmp(path
, "/sys", 4) == 0)
664 static int lxcfs_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
665 struct fuse_file_info
*fi
)
668 if (strcmp(path
, "/") == 0) {
669 if (filler(buf
, ".", NULL
, 0) != 0 ||
670 filler(buf
, "..", NULL
, 0) != 0 ||
671 filler(buf
, "proc", NULL
, 0) != 0 ||
672 filler(buf
, "sys", NULL
, 0) != 0 ||
673 filler(buf
, "cgroup", NULL
, 0) != 0)
677 if (strncmp(path
, "/cgroup", 7) == 0) {
679 ret
= do_cg_readdir(path
, buf
, filler
, offset
, fi
);
683 if (strcmp(path
, "/proc") == 0) {
685 ret
= do_proc_readdir(path
, buf
, filler
, offset
, fi
);
690 if (strncmp(path
, "/sys", 4) == 0) {
692 ret
= do_sys_readdir(path
, buf
, filler
, offset
, fi
);
700 static int lxcfs_access(const char *path
, int mode
)
704 if (strcmp(path
, "/") == 0 && (mode
& W_OK
) == 0)
707 if (strncmp(path
, "/cgroup", 7) == 0) {
709 ret
= do_cg_access(path
, mode
);
713 if (strncmp(path
, "/proc", 5) == 0) {
715 ret
= do_proc_access(path
, mode
);
719 if (strncmp(path
, "/sys", 4) == 0) {
721 ret
= do_sys_access(path
, mode
);
730 static int lxcfs_releasedir(const char *path
, struct fuse_file_info
*fi
)
733 if (strcmp(path
, "/") == 0)
735 if (strncmp(path
, "/cgroup", 7) == 0) {
737 ret
= do_cg_releasedir(path
, fi
);
741 if (strcmp(path
, "/proc") == 0)
743 if (strncmp(path
, "/sys", 4) == 0){
745 ret
= do_sys_releasedir(path
, fi
);
753 static int lxcfs_open(const char *path
, struct fuse_file_info
*fi
)
756 if (strncmp(path
, "/cgroup", 7) == 0) {
758 ret
= do_cg_open(path
, fi
);
762 if (strncmp(path
, "/proc", 5) == 0) {
764 ret
= do_proc_open(path
, fi
);
768 if (strncmp(path
, "/sys", 4) == 0) {
770 ret
= do_sys_open(path
, fi
);
779 static int lxcfs_read(const char *path
, char *buf
, size_t size
, off_t offset
,
780 struct fuse_file_info
*fi
)
783 if (strncmp(path
, "/cgroup", 7) == 0) {
785 ret
= do_cg_read(path
, buf
, size
, offset
, fi
);
789 if (strncmp(path
, "/proc", 5) == 0) {
791 ret
= do_proc_read(path
, buf
, size
, offset
, fi
);
795 if (strncmp(path
, "/sys", 4) == 0) {
797 ret
= do_sys_read(path
, buf
, size
, offset
, fi
);
806 int lxcfs_write(const char *path
, const char *buf
, size_t size
, off_t offset
,
807 struct fuse_file_info
*fi
)
810 if (strncmp(path
, "/cgroup", 7) == 0) {
812 ret
= do_cg_write(path
, buf
, size
, offset
, fi
);
820 static int lxcfs_flush(const char *path
, struct fuse_file_info
*fi
)
825 static int lxcfs_release(const char *path
, struct fuse_file_info
*fi
)
828 if (strncmp(path
, "/cgroup", 7) == 0) {
830 ret
= do_cg_release(path
, fi
);
834 if (strncmp(path
, "/proc", 5) == 0) {
836 ret
= do_proc_release(path
, fi
);
840 if (strncmp(path
, "/sys", 4) == 0) {
842 ret
= do_sys_release(path
, fi
);
851 static int lxcfs_fsync(const char *path
, int datasync
, struct fuse_file_info
*fi
)
856 int lxcfs_mkdir(const char *path
, mode_t mode
)
859 if (strncmp(path
, "/cgroup", 7) == 0) {
861 ret
= do_cg_mkdir(path
, mode
);
869 int lxcfs_chown(const char *path
, uid_t uid
, gid_t gid
)
872 if (strncmp(path
, "/cgroup", 7) == 0) {
874 ret
= do_cg_chown(path
, uid
, gid
);
879 if (strncmp(path
, "/proc", 5) == 0)
882 if (strncmp(path
, "/sys", 4) == 0)
888 * cat first does a truncate before doing ops->write. This doesn't
889 * really make sense for cgroups. So just return 0 always but do
892 int lxcfs_truncate(const char *path
, off_t newsize
)
894 if (strncmp(path
, "/cgroup", 7) == 0)
899 int lxcfs_rmdir(const char *path
)
902 if (strncmp(path
, "/cgroup", 7) == 0) {
904 ret
= do_cg_rmdir(path
);
911 int lxcfs_chmod(const char *path
, mode_t mode
)
914 if (strncmp(path
, "/cgroup", 7) == 0) {
916 ret
= do_cg_chmod(path
, mode
);
921 if (strncmp(path
, "/proc", 5) == 0)
924 if (strncmp(path
, "/sys", 4) == 0)
930 const struct fuse_operations lxcfs_ops
= {
931 .getattr
= lxcfs_getattr
,
935 .mkdir
= lxcfs_mkdir
,
937 .rmdir
= lxcfs_rmdir
,
941 .chmod
= lxcfs_chmod
,
942 .chown
= lxcfs_chown
,
943 .truncate
= lxcfs_truncate
,
948 .release
= lxcfs_release
,
949 .write
= lxcfs_write
,
952 .flush
= lxcfs_flush
,
953 .fsync
= lxcfs_fsync
,
960 .opendir
= lxcfs_opendir
,
961 .readdir
= lxcfs_readdir
,
962 .releasedir
= lxcfs_releasedir
,
967 .access
= lxcfs_access
,
975 fprintf(stderr
, "Usage:\n");
976 fprintf(stderr
, "\n");
977 fprintf(stderr
, "lxcfs [-f|-d] -u -l -n [-p pidfile] mountpoint\n");
978 fprintf(stderr
, " -f running foreground by default; -d enable debug output \n");
979 fprintf(stderr
, " -l use loadavg \n");
980 fprintf(stderr
, " -u no swap \n");
981 fprintf(stderr
, " Default pidfile is %s/lxcfs.pid\n", RUNTIME_PATH
);
982 fprintf(stderr
, "lxcfs -h\n");
983 fprintf(stderr
, "lxcfs -v\n");
987 static bool is_help(char *w
)
989 if (strcmp(w
, "-h") == 0 ||
990 strcmp(w
, "--help") == 0 ||
991 strcmp(w
, "-help") == 0 ||
992 strcmp(w
, "help") == 0)
997 static bool is_version(char *w
)
999 if (strcmp(w
, "-v") == 0 ||
1000 strcmp(w
, "--version") == 0 ||
1001 strcmp(w
, "-version") == 0 ||
1002 strcmp(w
, "version") == 0)
1007 bool swallow_arg(int *argcp
, char *argv
[], char *which
)
1011 for (i
= 1; argv
[i
]; i
++) {
1012 if (strcmp(argv
[i
], which
) != 0)
1014 for (; argv
[i
]; i
++) {
1015 argv
[i
] = argv
[i
+1];
1023 bool swallow_option(int *argcp
, char *argv
[], char *opt
, char **v
)
1027 for (i
= 1; argv
[i
]; i
++) {
1030 if (strcmp(argv
[i
], opt
) != 0)
1033 *v
= strdup(argv
[i
+1]);
1035 for (; argv
[i
+1]; i
++) {
1036 argv
[i
] = argv
[i
+2];
1044 static int set_pidfile(char *pidfile
)
1050 fl
.l_type
= F_WRLCK
;
1051 fl
.l_whence
= SEEK_SET
;
1055 fd
= open(pidfile
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
1057 fprintf(stderr
, "Could not open pidfile %s: %m\n", pidfile
);
1061 if (fcntl(fd
, F_SETLK
, &fl
) == -1) {
1062 if (errno
== EAGAIN
|| errno
== EACCES
) {
1063 fprintf(stderr
, "PID file '%s' is already locked.\n", pidfile
);
1067 fprintf(stderr
, "Warning; unable to lock PID file, proceeding.\n");
1070 if (ftruncate(fd
, 0) == -1) {
1071 fprintf(stderr
, "Error truncating PID file '%s': %m", pidfile
);
1076 snprintf(buf
, 50, "%ld\n", (long) getpid());
1077 if (write(fd
, buf
, strlen(buf
)) != strlen(buf
)) {
1078 fprintf(stderr
, "Error writing to PID file '%s': %m", pidfile
);
1086 int main(int argc
, char *argv
[])
1088 int ret
= EXIT_FAILURE
;
1090 char *pidfile
= NULL
, *saveptr
= NULL
, *token
= NULL
, *v
= NULL
;
1092 bool debug
= false, nonempty
= false;
1093 bool load_use
= false;
1095 * what we pass to fuse_main is:
1096 * argv[0] -s [-f|-d] -o allow_other,directio argv[1] NULL
1098 int nargs
= 5, cnt
= 0;
1100 struct lxcfs_opts
*opts
;
1102 opts
= malloc(sizeof(struct lxcfs_opts
));
1104 fprintf(stderr
, "Error allocating memory for options.\n");
1107 opts
->swap_off
= false;
1108 opts
->use_pidfd
= false;
1110 /* accomodate older init scripts */
1111 swallow_arg(&argc
, argv
, "-s");
1112 swallow_arg(&argc
, argv
, "-f");
1113 debug
= swallow_arg(&argc
, argv
, "-d");
1114 if (swallow_arg(&argc
, argv
, "-l"))
1116 if (swallow_arg(&argc
, argv
, "-u"))
1117 opts
->swap_off
= true;
1119 if (swallow_arg(&argc
, argv
, "--pidfd"))
1120 opts
->use_pidfd
= true;
1122 if (swallow_option(&argc
, argv
, "-o", &v
)) {
1123 /* Parse multiple values */
1124 for (; (token
= strtok_r(v
, ",", &saveptr
)); v
= NULL
) {
1125 if (strcmp(token
, "allow_other") == 0) {
1126 /* Noop. this is the default. Always enabled. */
1127 } else if (strcmp(token
, "nonempty") == 0) {
1131 fprintf(stderr
, "Warning: unexpected fuse option %s\n", v
);
1138 if (swallow_option(&argc
, argv
, "-p", &v
))
1141 if (argc
== 2 && is_version(argv
[1])) {
1142 fprintf(stderr
, "%s\n", VERSION
);
1146 if (argc
!= 2 || is_help(argv
[1]))
1150 if (signal(SIGUSR1
, reload_handler
) == SIG_ERR
) {
1151 fprintf(stderr
, "Error setting USR1 signal handler: %m\n");
1155 newargv
[cnt
++] = argv
[0];
1157 newargv
[cnt
++] = "-d";
1159 newargv
[cnt
++] = "-f";
1160 newargv
[cnt
++] = "-o";
1162 newargv
[cnt
++] = "allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5,nonempty";
1164 newargv
[cnt
++] = "allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5";
1165 newargv
[cnt
++] = argv
[1];
1166 newargv
[cnt
++] = NULL
;
1169 pidfile_len
= strlen(RUNTIME_PATH
) + strlen("/lxcfs.pid") + 1;
1170 pidfile
= alloca(pidfile_len
);
1171 snprintf(pidfile
, pidfile_len
, "%s/lxcfs.pid", RUNTIME_PATH
);
1173 if ((pidfd
= set_pidfile(pidfile
)) < 0)
1176 if (load_use
&& start_loadavg() != 0)
1179 if (!fuse_main(nargs
, newargv
, &lxcfs_ops
, opts
))
1186 dlclose(dlopen_handle
);