3 * Copyright © 2014-2016 Canonical, Inc
4 * Author: Serge Hallyn <serge.hallyn@ubuntu.com>
6 * See COPYING file for details.
9 #define FUSE_USE_VERSION 26
27 #include <linux/sched.h>
28 #include <sys/epoll.h>
29 #include <sys/mount.h>
30 #include <sys/socket.h>
31 #include <linux/limits.h>
34 #include "config.h" // for VERSION
38 /* Functions to keep track of number of threads using the library */
40 static int users_count
;
41 static pthread_mutex_t user_count_mutex
= PTHREAD_MUTEX_INITIALIZER
;
42 static void lock_mutex(pthread_mutex_t
*l
)
46 if ((ret
= pthread_mutex_lock(l
)) != 0) {
47 lxcfs_error("returned:%d %s\n", ret
, strerror(ret
));
52 static void unlock_mutex(pthread_mutex_t
*l
)
56 if ((ret
= pthread_mutex_unlock(l
)) != 0) {
57 lxcfs_error("returned:%d %s\n", ret
, strerror(ret
));
62 static void users_lock(void)
64 lock_mutex(&user_count_mutex
);
67 static void users_unlock(void)
69 unlock_mutex(&user_count_mutex
);
72 static pthread_t loadavg_pid
= 0;
74 /* Returns zero on success */
75 static int start_loadavg(void) {
77 pthread_t (*load_daemon
)(int);
79 dlerror(); /* Clear any existing error */
81 load_daemon
= (pthread_t (*)(int)) dlsym(dlopen_handle
, "load_daemon");
84 lxcfs_error("load_daemon fails:%s\n", error
);
87 loadavg_pid
= load_daemon(1);
94 /* Returns zero on success */
95 static int stop_loadavg(void) {
97 int (*stop_load_daemon
)(pthread_t
);
99 stop_load_daemon
= (int (*)(pthread_t
)) dlsym(dlopen_handle
, "stop_load_daemon");
102 lxcfs_error("stop_load_daemon error: %s\n", error
);
106 if (stop_load_daemon(loadavg_pid
) != 0)
112 static volatile sig_atomic_t need_reload
;
114 /* do_reload - reload the dynamic library. Done under
115 * lock and when we know the user_count was 0 */
116 static void do_reload(void)
118 char lxcfs_lib_path
[PATH_MAX
];
124 lxcfs_debug("%s\n", "Closing liblxcfs.so handle.");
125 dlclose(dlopen_handle
);
128 /* First try loading using ld.so */
129 dlopen_handle
= dlopen("liblxcfs.so", RTLD_LAZY
);
131 lxcfs_debug("%s\n", "Successfully called dlopen() on liblxcfs.so.");
136 /* LIBDIR: autoconf will setup this MACRO. Default value is $PREFIX/lib */
137 snprintf(lxcfs_lib_path
, PATH_MAX
, "%s/lxcfs/liblxcfs.so", LIBDIR
);
139 snprintf(lxcfs_lib_path
, PATH_MAX
, "/usr/local/lib/lxcfs/liblxcfs.so");
141 dlopen_handle
= dlopen(lxcfs_lib_path
, RTLD_LAZY
);
142 if (!dlopen_handle
) {
143 lxcfs_error("Failed to open liblxcfs.so: %s.\n", dlerror());
152 lxcfs_error("%s\n", "lxcfs: reloaded");
156 static void up_users(void)
159 if (users_count
== 0 && need_reload
)
165 static void down_users(void)
172 static void reload_handler(int sig
)
177 /* Functions to run the library methods */
178 static int do_cg_getattr(const char *path
, struct stat
*sb
)
180 int (*cg_getattr
)(const char *path
, struct stat
*sb
);
182 dlerror(); /* Clear any existing error */
183 cg_getattr
= (int (*)(const char *, struct stat
*)) dlsym(dlopen_handle
, "cg_getattr");
186 lxcfs_error("%s\n", error
);
190 return cg_getattr(path
, sb
);
193 static int do_proc_getattr(const char *path
, struct stat
*sb
)
195 int (*proc_getattr
)(const char *path
, struct stat
*sb
);
197 dlerror(); /* Clear any existing error */
198 proc_getattr
= (int (*)(const char *, struct stat
*)) dlsym(dlopen_handle
, "proc_getattr");
201 lxcfs_error("%s\n", error
);
205 return proc_getattr(path
, sb
);
208 static int do_sys_getattr(const char *path
, struct stat
*sb
)
210 int (*sys_getattr
)(const char *path
, struct stat
*sb
);
212 dlerror(); /* Clear any existing error */
213 sys_getattr
= (int (*)(const char *, struct stat
*)) dlsym(dlopen_handle
, "sys_getattr");
216 lxcfs_error("%s\n", error
);
220 return sys_getattr(path
, sb
);
223 static int do_cg_read(const char *path
, char *buf
, size_t size
, off_t offset
,
224 struct fuse_file_info
*fi
)
226 int (*cg_read
)(const char *path
, char *buf
, size_t size
, off_t offset
,
227 struct fuse_file_info
*fi
);
230 dlerror(); /* Clear any existing error */
231 cg_read
= (int (*)(const char *, char *, size_t, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_read");
234 lxcfs_error("%s\n", error
);
238 return cg_read(path
, buf
, size
, offset
, fi
);
241 static int do_proc_read(const char *path
, char *buf
, size_t size
, off_t offset
,
242 struct fuse_file_info
*fi
)
244 int (*proc_read
)(const char *path
, char *buf
, size_t size
, off_t offset
,
245 struct fuse_file_info
*fi
);
248 dlerror(); /* Clear any existing error */
249 proc_read
= (int (*)(const char *, char *, size_t, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "proc_read");
252 lxcfs_error("%s\n", error
);
256 return proc_read(path
, buf
, size
, offset
, fi
);
259 static int do_sys_read(const char *path
, char *buf
, size_t size
, off_t offset
,
260 struct fuse_file_info
*fi
)
262 int (*sys_read
)(const char *path
, char *buf
, size_t size
, off_t offset
,
263 struct fuse_file_info
*fi
);
266 dlerror(); /* Clear any existing error */
267 sys_read
= (int (*)(const char *, char *, size_t, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_read");
270 lxcfs_error("%s\n", error
);
274 return sys_read(path
, buf
, size
, offset
, fi
);
277 static int do_cg_write(const char *path
, const char *buf
, size_t size
, off_t offset
,
278 struct fuse_file_info
*fi
)
280 int (*cg_write
)(const char *path
, const char *buf
, size_t size
, off_t offset
,
281 struct fuse_file_info
*fi
);
283 dlerror(); /* Clear any existing error */
284 cg_write
= (int (*)(const char *, const char *, size_t, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_write");
287 lxcfs_error("%s\n", error
);
291 return cg_write(path
, buf
, size
, offset
, fi
);
294 static int do_cg_mkdir(const char *path
, mode_t mode
)
296 int (*cg_mkdir
)(const char *path
, mode_t mode
);
298 dlerror(); /* Clear any existing error */
299 cg_mkdir
= (int (*)(const char *, mode_t
)) dlsym(dlopen_handle
, "cg_mkdir");
302 lxcfs_error("%s\n", error
);
306 return cg_mkdir(path
, mode
);
309 static int do_cg_chown(const char *path
, uid_t uid
, gid_t gid
)
311 int (*cg_chown
)(const char *path
, uid_t uid
, gid_t gid
);
313 dlerror(); /* Clear any existing error */
314 cg_chown
= (int (*)(const char *, uid_t
, gid_t
)) dlsym(dlopen_handle
, "cg_chown");
317 lxcfs_error("%s\n", error
);
321 return cg_chown(path
, uid
, gid
);
324 static int do_cg_rmdir(const char *path
)
326 int (*cg_rmdir
)(const char *path
);
328 dlerror(); /* Clear any existing error */
329 cg_rmdir
= (int (*)(const char *path
)) dlsym(dlopen_handle
, "cg_rmdir");
332 lxcfs_error("%s\n", error
);
336 return cg_rmdir(path
);
339 static int do_cg_chmod(const char *path
, mode_t mode
)
341 int (*cg_chmod
)(const char *path
, mode_t mode
);
343 dlerror(); /* Clear any existing error */
344 cg_chmod
= (int (*)(const char *, mode_t
)) dlsym(dlopen_handle
, "cg_chmod");
347 lxcfs_error("%s\n", error
);
351 return cg_chmod(path
, mode
);
354 static int do_cg_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
355 struct fuse_file_info
*fi
)
357 int (*cg_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
358 struct fuse_file_info
*fi
);
361 dlerror(); /* Clear any existing error */
362 cg_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_readdir");
365 lxcfs_error("%s\n", error
);
369 return cg_readdir(path
, buf
, filler
, offset
, fi
);
372 static int do_proc_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
373 struct fuse_file_info
*fi
)
375 int (*proc_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
376 struct fuse_file_info
*fi
);
379 dlerror(); /* Clear any existing error */
380 proc_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "proc_readdir");
383 lxcfs_error("%s\n", error
);
387 return proc_readdir(path
, buf
, filler
, offset
, fi
);
390 static int do_sys_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
391 struct fuse_file_info
*fi
)
393 int (*sys_readdir
)(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
394 struct fuse_file_info
*fi
);
397 dlerror(); /* Clear any existing error */
398 sys_readdir
= (int (*)(const char *, void *, fuse_fill_dir_t
, off_t
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_readdir");
401 lxcfs_error("%s\n", error
);
405 return sys_readdir(path
, buf
, filler
, offset
, fi
);
409 static int do_cg_open(const char *path
, struct fuse_file_info
*fi
)
411 int (*cg_open
)(const char *path
, struct fuse_file_info
*fi
);
413 dlerror(); /* Clear any existing error */
414 cg_open
= (int (*)(const char *, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_open");
417 lxcfs_error("%s\n", error
);
421 return cg_open(path
, fi
);
424 static int do_cg_access(const char *path
, int mode
)
426 int (*cg_access
)(const char *path
, int mode
);
428 dlerror(); /* Clear any existing error */
429 cg_access
= (int (*)(const char *, int mode
)) dlsym(dlopen_handle
, "cg_access");
432 lxcfs_error("%s\n", error
);
436 return cg_access(path
, mode
);
439 static int do_proc_open(const char *path
, struct fuse_file_info
*fi
)
441 int (*proc_open
)(const char *path
, struct fuse_file_info
*fi
);
443 dlerror(); /* Clear any existing error */
444 proc_open
= (int (*)(const char *path
, struct fuse_file_info
*fi
)) dlsym(dlopen_handle
, "proc_open");
447 lxcfs_error("%s\n", error
);
451 return proc_open(path
, fi
);
454 static int do_proc_access(const char *path
, int mode
)
456 int (*proc_access
)(const char *path
, int mode
);
458 dlerror(); /* Clear any existing error */
459 proc_access
= (int (*)(const char *, int mode
)) dlsym(dlopen_handle
, "proc_access");
462 lxcfs_error("%s\n", error
);
466 return proc_access(path
, mode
);
469 static int do_sys_open(const char *path
, struct fuse_file_info
*fi
)
471 int (*sys_open
)(const char *path
, struct fuse_file_info
*fi
);
473 dlerror(); /* Clear any existing error */
474 sys_open
= (int (*)(const char *path
, struct fuse_file_info
*fi
)) dlsym(dlopen_handle
, "sys_open");
477 lxcfs_error("%s\n", error
);
481 return sys_open(path
, fi
);
484 static int do_sys_access(const char *path
, int mode
)
486 int (*sys_access
)(const char *path
, int mode
);
488 dlerror(); /* Clear any existing error */
489 sys_access
= (int (*)(const char *, int mode
)) dlsym(dlopen_handle
, "sys_access");
492 lxcfs_error("%s\n", error
);
496 return sys_access(path
, mode
);
500 static int do_cg_release(const char *path
, struct fuse_file_info
*fi
)
502 int (*cg_release
)(const char *path
, struct fuse_file_info
*fi
);
504 dlerror(); /* Clear any existing error */
505 cg_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_release");
508 lxcfs_error("%s\n", error
);
512 return cg_release(path
, fi
);
515 static int do_proc_release(const char *path
, struct fuse_file_info
*fi
)
517 int (*proc_release
)(const char *path
, struct fuse_file_info
*fi
);
519 dlerror(); /* Clear any existing error */
520 proc_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "proc_release");
523 lxcfs_error("%s\n", error
);
527 return proc_release(path
, fi
);
530 static int do_sys_release(const char *path
, struct fuse_file_info
*fi
)
532 int (*sys_release
)(const char *path
, struct fuse_file_info
*fi
);
534 dlerror(); /* Clear any existing error */
535 sys_release
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_release");
538 lxcfs_error("%s\n", error
);
542 return sys_release(path
, fi
);
545 static int do_cg_opendir(const char *path
, struct fuse_file_info
*fi
)
547 int (*cg_opendir
)(const char *path
, struct fuse_file_info
*fi
);
549 dlerror(); /* Clear any existing error */
550 cg_opendir
= (int (*)(const char *path
, struct fuse_file_info
*fi
)) dlsym(dlopen_handle
, "cg_opendir");
553 lxcfs_error("%s\n", error
);
557 return cg_opendir(path
, fi
);
560 static int do_cg_releasedir(const char *path
, struct fuse_file_info
*fi
)
562 int (*cg_releasedir
)(const char *path
, struct fuse_file_info
*fi
);
564 dlerror(); /* Clear any existing error */
565 cg_releasedir
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "cg_releasedir");
568 lxcfs_error("%s\n", error
);
572 return cg_releasedir(path
, fi
);
575 static int do_sys_releasedir(const char *path
, struct fuse_file_info
*fi
)
577 int (*sys_releasedir
)(const char *path
, struct fuse_file_info
*fi
);
579 dlerror(); /* Clear any existing error */
580 sys_releasedir
= (int (*)(const char *path
, struct fuse_file_info
*)) dlsym(dlopen_handle
, "sys_releasedir");
583 lxcfs_error("%s\n", error
);
587 return sys_releasedir(path
, fi
);
592 * these just delegate to the /proc and /cgroup ops as
596 static int lxcfs_getattr(const char *path
, struct stat
*sb
)
601 if (strcmp(path
, "/") == 0) {
602 if (clock_gettime(CLOCK_REALTIME
, &now
) < 0)
604 sb
->st_uid
= sb
->st_gid
= 0;
605 sb
->st_atim
= sb
->st_mtim
= sb
->st_ctim
= now
;
607 sb
->st_mode
= S_IFDIR
| 00755;
612 if (strncmp(path
, "/cgroup", 7) == 0) {
614 ret
= do_cg_getattr(path
, sb
);
618 if (strncmp(path
, "/proc", 5) == 0) {
620 ret
= do_proc_getattr(path
, sb
);
624 if (strncmp(path
, "/sys", 4) == 0) {
626 ret
= do_sys_getattr(path
, sb
);
633 static int lxcfs_opendir(const char *path
, struct fuse_file_info
*fi
)
636 if (strcmp(path
, "/") == 0)
639 if (strncmp(path
, "/cgroup", 7) == 0) {
641 ret
= do_cg_opendir(path
, fi
);
645 if (strcmp(path
, "/proc") == 0)
647 if (strncmp(path
, "/sys", 4) == 0)
653 static int lxcfs_readdir(const char *path
, void *buf
, fuse_fill_dir_t filler
, off_t offset
,
654 struct fuse_file_info
*fi
)
657 if (strcmp(path
, "/") == 0) {
658 if (filler(buf
, ".", NULL
, 0) != 0 ||
659 filler(buf
, "..", NULL
, 0) != 0 ||
660 filler(buf
, "proc", NULL
, 0) != 0 ||
661 filler(buf
, "sys", NULL
, 0) != 0 ||
662 filler(buf
, "cgroup", NULL
, 0) != 0)
666 if (strncmp(path
, "/cgroup", 7) == 0) {
668 ret
= do_cg_readdir(path
, buf
, filler
, offset
, fi
);
672 if (strcmp(path
, "/proc") == 0) {
674 ret
= do_proc_readdir(path
, buf
, filler
, offset
, fi
);
679 if (strncmp(path
, "/sys", 4) == 0) {
681 ret
= do_sys_readdir(path
, buf
, filler
, offset
, fi
);
689 static int lxcfs_access(const char *path
, int mode
)
693 if (strcmp(path
, "/") == 0 && (mode
& W_OK
) == 0)
696 if (strncmp(path
, "/cgroup", 7) == 0) {
698 ret
= do_cg_access(path
, mode
);
702 if (strncmp(path
, "/proc", 5) == 0) {
704 ret
= do_proc_access(path
, mode
);
708 if (strncmp(path
, "/sys", 4) == 0) {
710 ret
= do_sys_access(path
, mode
);
719 static int lxcfs_releasedir(const char *path
, struct fuse_file_info
*fi
)
722 if (strcmp(path
, "/") == 0)
724 if (strncmp(path
, "/cgroup", 7) == 0) {
726 ret
= do_cg_releasedir(path
, fi
);
730 if (strcmp(path
, "/proc") == 0)
732 if (strncmp(path
, "/sys", 4) == 0){
734 ret
= do_sys_releasedir(path
, fi
);
742 static int lxcfs_open(const char *path
, struct fuse_file_info
*fi
)
745 if (strncmp(path
, "/cgroup", 7) == 0) {
747 ret
= do_cg_open(path
, fi
);
751 if (strncmp(path
, "/proc", 5) == 0) {
753 ret
= do_proc_open(path
, fi
);
757 if (strncmp(path
, "/sys", 4) == 0) {
759 ret
= do_sys_open(path
, fi
);
768 static int lxcfs_read(const char *path
, char *buf
, size_t size
, off_t offset
,
769 struct fuse_file_info
*fi
)
772 if (strncmp(path
, "/cgroup", 7) == 0) {
774 ret
= do_cg_read(path
, buf
, size
, offset
, fi
);
778 if (strncmp(path
, "/proc", 5) == 0) {
780 ret
= do_proc_read(path
, buf
, size
, offset
, fi
);
784 if (strncmp(path
, "/sys", 4) == 0) {
786 ret
= do_sys_read(path
, buf
, size
, offset
, fi
);
795 int lxcfs_write(const char *path
, const char *buf
, size_t size
, off_t offset
,
796 struct fuse_file_info
*fi
)
799 if (strncmp(path
, "/cgroup", 7) == 0) {
801 ret
= do_cg_write(path
, buf
, size
, offset
, fi
);
809 static int lxcfs_flush(const char *path
, struct fuse_file_info
*fi
)
814 static int lxcfs_release(const char *path
, struct fuse_file_info
*fi
)
817 if (strncmp(path
, "/cgroup", 7) == 0) {
819 ret
= do_cg_release(path
, fi
);
823 if (strncmp(path
, "/proc", 5) == 0) {
825 ret
= do_proc_release(path
, fi
);
829 if (strncmp(path
, "/sys", 4) == 0) {
831 ret
= do_sys_release(path
, fi
);
840 static int lxcfs_fsync(const char *path
, int datasync
, struct fuse_file_info
*fi
)
845 int lxcfs_mkdir(const char *path
, mode_t mode
)
848 if (strncmp(path
, "/cgroup", 7) == 0) {
850 ret
= do_cg_mkdir(path
, mode
);
858 int lxcfs_chown(const char *path
, uid_t uid
, gid_t gid
)
861 if (strncmp(path
, "/cgroup", 7) == 0) {
863 ret
= do_cg_chown(path
, uid
, gid
);
868 if (strncmp(path
, "/proc", 5) == 0)
871 if (strncmp(path
, "/sys", 4) == 0)
877 * cat first does a truncate before doing ops->write. This doesn't
878 * really make sense for cgroups. So just return 0 always but do
881 int lxcfs_truncate(const char *path
, off_t newsize
)
883 if (strncmp(path
, "/cgroup", 7) == 0)
888 int lxcfs_rmdir(const char *path
)
891 if (strncmp(path
, "/cgroup", 7) == 0) {
893 ret
= do_cg_rmdir(path
);
900 int lxcfs_chmod(const char *path
, mode_t mode
)
903 if (strncmp(path
, "/cgroup", 7) == 0) {
905 ret
= do_cg_chmod(path
, mode
);
910 if (strncmp(path
, "/proc", 5) == 0)
913 if (strncmp(path
, "/sys", 4) == 0)
919 const struct fuse_operations lxcfs_ops
= {
920 .getattr
= lxcfs_getattr
,
924 .mkdir
= lxcfs_mkdir
,
926 .rmdir
= lxcfs_rmdir
,
930 .chmod
= lxcfs_chmod
,
931 .chown
= lxcfs_chown
,
932 .truncate
= lxcfs_truncate
,
937 .release
= lxcfs_release
,
938 .write
= lxcfs_write
,
941 .flush
= lxcfs_flush
,
942 .fsync
= lxcfs_fsync
,
949 .opendir
= lxcfs_opendir
,
950 .readdir
= lxcfs_readdir
,
951 .releasedir
= lxcfs_releasedir
,
956 .access
= lxcfs_access
,
964 fprintf(stderr
, "Usage:\n");
965 fprintf(stderr
, "\n");
966 fprintf(stderr
, "lxcfs [-f|-d] -u -l -n [-p pidfile] mountpoint\n");
967 fprintf(stderr
, " -f running foreground by default; -d enable debug output \n");
968 fprintf(stderr
, " -l use loadavg \n");
969 fprintf(stderr
, " -u no swap \n");
970 fprintf(stderr
, " Default pidfile is %s/lxcfs.pid\n", RUNTIME_PATH
);
971 fprintf(stderr
, "lxcfs -h\n");
972 fprintf(stderr
, "lxcfs -v\n");
976 static bool is_help(char *w
)
978 if (strcmp(w
, "-h") == 0 ||
979 strcmp(w
, "--help") == 0 ||
980 strcmp(w
, "-help") == 0 ||
981 strcmp(w
, "help") == 0)
986 static bool is_version(char *w
)
988 if (strcmp(w
, "-v") == 0 ||
989 strcmp(w
, "--version") == 0 ||
990 strcmp(w
, "-version") == 0 ||
991 strcmp(w
, "version") == 0)
996 bool swallow_arg(int *argcp
, char *argv
[], char *which
)
1000 for (i
= 1; argv
[i
]; i
++) {
1001 if (strcmp(argv
[i
], which
) != 0)
1003 for (; argv
[i
]; i
++) {
1004 argv
[i
] = argv
[i
+1];
1012 bool swallow_option(int *argcp
, char *argv
[], char *opt
, char **v
)
1016 for (i
= 1; argv
[i
]; i
++) {
1019 if (strcmp(argv
[i
], opt
) != 0)
1022 *v
= strdup(argv
[i
+1]);
1024 for (; argv
[i
+1]; i
++) {
1025 argv
[i
] = argv
[i
+2];
1033 static int set_pidfile(char *pidfile
)
1039 fl
.l_type
= F_WRLCK
;
1040 fl
.l_whence
= SEEK_SET
;
1044 fd
= open(pidfile
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
1046 fprintf(stderr
, "Could not open pidfile %s: %m\n", pidfile
);
1050 if (fcntl(fd
, F_SETLK
, &fl
) == -1) {
1051 if (errno
== EAGAIN
|| errno
== EACCES
) {
1052 fprintf(stderr
, "PID file '%s' is already locked.\n", pidfile
);
1056 fprintf(stderr
, "Warning; unable to lock PID file, proceeding.\n");
1059 if (ftruncate(fd
, 0) == -1) {
1060 fprintf(stderr
, "Error truncating PID file '%s': %m", pidfile
);
1065 snprintf(buf
, 50, "%ld\n", (long) getpid());
1066 if (write(fd
, buf
, strlen(buf
)) != strlen(buf
)) {
1067 fprintf(stderr
, "Error writing to PID file '%s': %m", pidfile
);
1075 int main(int argc
, char *argv
[])
1077 int ret
= EXIT_FAILURE
;
1079 char *pidfile
= NULL
, *saveptr
= NULL
, *token
= NULL
, *v
= NULL
;
1081 bool debug
= false, nonempty
= false;
1082 bool load_use
= false;
1084 * what we pass to fuse_main is:
1085 * argv[0] -s [-f|-d] -o allow_other,directio argv[1] NULL
1087 int nargs
= 5, cnt
= 0;
1090 struct lxcfs_opts
*opts
;
1091 opts
= malloc(sizeof(struct lxcfs_opts
));
1093 fprintf(stderr
, "Error allocating memory for options.\n");
1096 opts
->swap_off
= false;
1098 /* accomodate older init scripts */
1099 swallow_arg(&argc
, argv
, "-s");
1100 swallow_arg(&argc
, argv
, "-f");
1101 debug
= swallow_arg(&argc
, argv
, "-d");
1102 if (swallow_arg(&argc
, argv
, "-l")) {
1105 if (swallow_arg(&argc
, argv
, "-u")) {
1106 opts
->swap_off
= true;
1108 if (swallow_option(&argc
, argv
, "-o", &v
)) {
1109 /* Parse multiple values */
1110 for (; (token
= strtok_r(v
, ",", &saveptr
)); v
= NULL
) {
1111 if (strcmp(token
, "allow_other") == 0) {
1112 /* Noop. this is the default. Always enabled. */
1113 } else if (strcmp(token
, "nonempty") == 0) {
1117 fprintf(stderr
, "Warning: unexpected fuse option %s\n", v
);
1124 if (swallow_option(&argc
, argv
, "-p", &v
))
1127 if (argc
== 2 && is_version(argv
[1])) {
1128 fprintf(stderr
, "%s\n", VERSION
);
1132 if (argc
!= 2 || is_help(argv
[1]))
1136 if (signal(SIGUSR1
, reload_handler
) == SIG_ERR
) {
1137 fprintf(stderr
, "Error setting USR1 signal handler: %m\n");
1141 newargv
[cnt
++] = argv
[0];
1143 newargv
[cnt
++] = "-d";
1145 newargv
[cnt
++] = "-f";
1146 newargv
[cnt
++] = "-o";
1148 newargv
[cnt
++] = "allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5,nonempty";
1150 newargv
[cnt
++] = "allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5";
1151 newargv
[cnt
++] = argv
[1];
1152 newargv
[cnt
++] = NULL
;
1155 pidfile_len
= strlen(RUNTIME_PATH
) + strlen("/lxcfs.pid") + 1;
1156 pidfile
= alloca(pidfile_len
);
1157 snprintf(pidfile
, pidfile_len
, "%s/lxcfs.pid", RUNTIME_PATH
);
1159 if ((pidfd
= set_pidfile(pidfile
)) < 0)
1162 if (load_use
&& start_loadavg() != 0)
1165 if (!fuse_main(nargs
, newargv
, &lxcfs_ops
, opts
))
1172 dlclose(dlopen_handle
);