]> git.proxmox.com Git - mirror_lxcfs.git/blob - lxcfs.c
98b5d91d22136b0607f8e1ada9dc7209ecb0a7e8
[mirror_lxcfs.git] / lxcfs.c
1 /* lxcfs
2 *
3 * Copyright © 2014-2016 Canonical, Inc
4 * Author: Serge Hallyn <serge.hallyn@ubuntu.com>
5 *
6 * See COPYING file for details.
7 */
8
9 #define FUSE_USE_VERSION 26
10
11 #include <alloca.h>
12 #include <dirent.h>
13 #include <dlfcn.h>
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <fuse.h>
17 #include <libgen.h>
18 #include <pthread.h>
19 #include <sched.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25 #include <unistd.h>
26 #include <wait.h>
27 #include <linux/sched.h>
28 #include <sys/epoll.h>
29 #include <sys/mount.h>
30 #include <sys/socket.h>
31
32 #include "bindings.h"
33 #include "config.h" // for VERSION
34
35 void *dlopen_handle;
36
37 /* Functions to keep track of number of threads using the library */
38
39 static int users_count;
40 static pthread_mutex_t user_count_mutex = PTHREAD_MUTEX_INITIALIZER;
41 static void lock_mutex(pthread_mutex_t *l)
42 {
43 int ret;
44
45 if ((ret = pthread_mutex_lock(l)) != 0) {
46 fprintf(stderr, "pthread_mutex_lock returned:%d %s\n", ret, strerror(ret));
47 exit(1);
48 }
49 }
50
51 static void unlock_mutex(pthread_mutex_t *l)
52 {
53 int ret;
54
55 if ((ret = pthread_mutex_unlock(l)) != 0) {
56 fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret));
57 exit(1);
58 }
59 }
60
61 static void users_lock(void)
62 {
63 lock_mutex(&user_count_mutex);
64 }
65
66 static void users_unlock(void)
67 {
68 unlock_mutex(&user_count_mutex);
69 }
70
71 static volatile sig_atomic_t need_reload;
72
73 /* do_reload - reload the dynamic library. Done under
74 * lock and when we know the user_count was 0 */
75 static void do_reload(void)
76 {
77 if (dlopen_handle)
78 dlclose(dlopen_handle);
79
80 /* First try loading using ld.so */
81 dlopen_handle = dlopen("liblxcfs.so", RTLD_LAZY);
82 if (dlopen_handle)
83 goto good;
84
85 dlopen_handle = dlopen("/usr/lib/lxcfs/liblxcfs.so", RTLD_LAZY);
86 if (!dlopen_handle) {
87 fprintf(stderr, "Failed to open liblxcfs: %s.\n", dlerror());
88 _exit(1);
89 }
90
91 good:
92 if (need_reload)
93 fprintf(stderr, "lxcfs: reloaded\n");
94 need_reload = 0;
95 }
96
97 static void up_users(void)
98 {
99 users_lock();
100 if (users_count == 0 && need_reload)
101 do_reload();
102 users_count++;
103 users_unlock();
104 }
105
106 static void down_users(void)
107 {
108 users_lock();
109 users_count--;
110 users_unlock();
111 }
112
113 static void reload_handler(int sig)
114 {
115 need_reload = 1;
116 }
117
118 /* Functions to run the library methods */
119 static int do_cg_getattr(const char *path, struct stat *sb)
120 {
121 int (*cg_getattr)(const char *path, struct stat *sb);
122 char *error;
123 dlerror(); /* Clear any existing error */
124 cg_getattr = (int (*)(const char *, struct stat *)) dlsym(dlopen_handle, "cg_getattr");
125 error = dlerror();
126 if (error != NULL) {
127 fprintf(stderr, "cg_getattr: %s\n", error);
128 return -1;
129 }
130
131 return cg_getattr(path, sb);
132 }
133
134 static int do_proc_getattr(const char *path, struct stat *sb)
135 {
136 int (*proc_getattr)(const char *path, struct stat *sb);
137 char *error;
138 dlerror(); /* Clear any existing error */
139 proc_getattr = (int (*)(const char *, struct stat *)) dlsym(dlopen_handle, "proc_getattr");
140 error = dlerror();
141 if (error != NULL) {
142 fprintf(stderr, "proc_getattr: %s\n", error);
143 return -1;
144 }
145
146 return proc_getattr(path, sb);
147 }
148
149 static int do_cg_read(const char *path, char *buf, size_t size, off_t offset,
150 struct fuse_file_info *fi)
151 {
152 int (*cg_read)(const char *path, char *buf, size_t size, off_t offset,
153 struct fuse_file_info *fi);
154 char *error;
155
156 dlerror(); /* Clear any existing error */
157 cg_read = (int (*)(const char *, char *, size_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_read");
158 error = dlerror();
159 if (error != NULL) {
160 fprintf(stderr, "cg_read: %s\n", error);
161 return -1;
162 }
163
164 return cg_read(path, buf, size, offset, fi);
165 }
166
167 static int do_proc_read(const char *path, char *buf, size_t size, off_t offset,
168 struct fuse_file_info *fi)
169 {
170 int (*proc_read)(const char *path, char *buf, size_t size, off_t offset,
171 struct fuse_file_info *fi);
172 char *error;
173
174 dlerror(); /* Clear any existing error */
175 proc_read = (int (*)(const char *, char *, size_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "proc_read");
176 error = dlerror();
177 if (error != NULL) {
178 fprintf(stderr, "proc_read: %s\n", error);
179 return -1;
180 }
181
182 return proc_read(path, buf, size, offset, fi);
183 }
184
185 static int do_cg_write(const char *path, const char *buf, size_t size, off_t offset,
186 struct fuse_file_info *fi)
187 {
188 int (*cg_write)(const char *path, const char *buf, size_t size, off_t offset,
189 struct fuse_file_info *fi);
190 char *error;
191 dlerror(); /* Clear any existing error */
192 cg_write = (int (*)(const char *, const char *, size_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_write");
193 error = dlerror();
194 if (error != NULL) {
195 fprintf(stderr, "cg_write: %s\n", error);
196 return -1;
197 }
198
199 return cg_write(path, buf, size, offset, fi);
200 }
201
202 static int do_cg_mkdir(const char *path, mode_t mode)
203 {
204 int (*cg_mkdir)(const char *path, mode_t mode);
205 char *error;
206 dlerror(); /* Clear any existing error */
207 cg_mkdir = (int (*)(const char *, mode_t)) dlsym(dlopen_handle, "cg_mkdir");
208 error = dlerror();
209 if (error != NULL) {
210 fprintf(stderr, "cg_mkdir: %s\n", error);
211 return -1;
212 }
213
214 return cg_mkdir(path, mode);
215 }
216
217 static int do_cg_chown(const char *path, uid_t uid, gid_t gid)
218 {
219 int (*cg_chown)(const char *path, uid_t uid, gid_t gid);
220 char *error;
221 dlerror(); /* Clear any existing error */
222 cg_chown = (int (*)(const char *, uid_t, gid_t)) dlsym(dlopen_handle, "cg_chown");
223 error = dlerror();
224 if (error != NULL) {
225 fprintf(stderr, "cg_chown: %s\n", error);
226 return -1;
227 }
228
229 return cg_chown(path, uid, gid);
230 }
231
232 static int do_cg_rmdir(const char *path)
233 {
234 int (*cg_rmdir)(const char *path);
235 char *error;
236 dlerror(); /* Clear any existing error */
237 cg_rmdir = (int (*)(const char *path)) dlsym(dlopen_handle, "cg_rmdir");
238 error = dlerror();
239 if (error != NULL) {
240 fprintf(stderr, "cg_rmdir: %s\n", error);
241 return -1;
242 }
243
244 return cg_rmdir(path);
245 }
246
247 static int do_cg_chmod(const char *path, mode_t mode)
248 {
249 int (*cg_chmod)(const char *path, mode_t mode);
250 char *error;
251 dlerror(); /* Clear any existing error */
252 cg_chmod = (int (*)(const char *, mode_t)) dlsym(dlopen_handle, "cg_chmod");
253 error = dlerror();
254 if (error != NULL) {
255 fprintf(stderr, "cg_chmod: %s\n", error);
256 return -1;
257 }
258
259 return cg_chmod(path, mode);
260 }
261
262 static int do_cg_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
263 struct fuse_file_info *fi)
264 {
265 int (*cg_readdir)(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
266 struct fuse_file_info *fi);
267 char *error;
268
269 dlerror(); /* Clear any existing error */
270 cg_readdir = (int (*)(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_readdir");
271 error = dlerror();
272 if (error != NULL) {
273 fprintf(stderr, "cg_readdir: %s\n", error);
274 return -1;
275 }
276
277 return cg_readdir(path, buf, filler, offset, fi);
278 }
279
280 static int do_proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
281 struct fuse_file_info *fi)
282 {
283 int (*proc_readdir)(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
284 struct fuse_file_info *fi);
285 char *error;
286
287 dlerror(); /* Clear any existing error */
288 proc_readdir = (int (*)(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *)) dlsym(dlopen_handle, "proc_readdir");
289 error = dlerror();
290 if (error != NULL) {
291 fprintf(stderr, "proc_readdir: %s\n", error);
292 return -1;
293 }
294
295 return proc_readdir(path, buf, filler, offset, fi);
296 }
297
298 static int do_cg_open(const char *path, struct fuse_file_info *fi)
299 {
300 int (*cg_open)(const char *path, struct fuse_file_info *fi);
301 char *error;
302 dlerror(); /* Clear any existing error */
303 cg_open = (int (*)(const char *, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_open");
304 error = dlerror();
305 if (error != NULL) {
306 fprintf(stderr, "cg_open: %s\n", error);
307 return -1;
308 }
309
310 return cg_open(path, fi);
311 }
312
313 static int do_cg_access(const char *path, int mode)
314 {
315 int (*cg_access)(const char *path, int mode);
316 char *error;
317 dlerror(); /* Clear any existing error */
318 cg_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "cg_access");
319 error = dlerror();
320 if (error != NULL) {
321 fprintf(stderr, "cg_access: %s\n", error);
322 return -1;
323 }
324
325 return cg_access(path, mode);
326 }
327
328 static int do_proc_open(const char *path, struct fuse_file_info *fi)
329 {
330 int (*proc_open)(const char *path, struct fuse_file_info *fi);
331 char *error;
332 dlerror(); /* Clear any existing error */
333 proc_open = (int (*)(const char *path, struct fuse_file_info *fi)) dlsym(dlopen_handle, "proc_open");
334 error = dlerror();
335 if (error != NULL) {
336 fprintf(stderr, "proc_open: %s\n", error);
337 return -1;
338 }
339
340 return proc_open(path, fi);
341 }
342
343 static int do_proc_access(const char *path, int mode)
344 {
345 int (*proc_access)(const char *path, int mode);
346 char *error;
347 dlerror(); /* Clear any existing error */
348 proc_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "proc_access");
349 error = dlerror();
350 if (error != NULL) {
351 fprintf(stderr, "proc_access: %s\n", error);
352 return -1;
353 }
354
355 return proc_access(path, mode);
356 }
357
358 static int do_cg_release(const char *path, struct fuse_file_info *fi)
359 {
360 int (*cg_release)(const char *path, struct fuse_file_info *fi);
361 char *error;
362 dlerror(); /* Clear any existing error */
363 cg_release = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_release");
364 error = dlerror();
365 if (error != NULL) {
366 fprintf(stderr, "cg_release: %s\n", error);
367 return -1;
368 }
369
370 return cg_release(path, fi);
371 }
372
373 static int do_proc_release(const char *path, struct fuse_file_info *fi)
374 {
375 int (*proc_release)(const char *path, struct fuse_file_info *fi);
376 char *error;
377 dlerror(); /* Clear any existing error */
378 proc_release = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "proc_release");
379 error = dlerror();
380 if (error != NULL) {
381 fprintf(stderr, "proc_release: %s\n", error);
382 return -1;
383 }
384
385 return proc_release(path, fi);
386 }
387
388 static int do_cg_opendir(const char *path, struct fuse_file_info *fi)
389 {
390 int (*cg_opendir)(const char *path, struct fuse_file_info *fi);
391 char *error;
392 dlerror(); /* Clear any existing error */
393 cg_opendir = (int (*)(const char *path, struct fuse_file_info *fi)) dlsym(dlopen_handle, "cg_opendir");
394 error = dlerror();
395 if (error != NULL) {
396 fprintf(stderr, "cg_opendir: %s\n", error);
397 return -1;
398 }
399
400 return cg_opendir(path, fi);
401 }
402
403 static int do_cg_releasedir(const char *path, struct fuse_file_info *fi)
404 {
405 int (*cg_releasedir)(const char *path, struct fuse_file_info *fi);
406 char *error;
407 dlerror(); /* Clear any existing error */
408 cg_releasedir = (int (*)(const char *path, struct fuse_file_info *)) dlsym(dlopen_handle, "cg_releasedir");
409 error = dlerror();
410 if (error != NULL) {
411 fprintf(stderr, "cg_releasedir: %s\n", error);
412 return -1;
413 }
414
415 return cg_releasedir(path, fi);
416 }
417
418 /*
419 * FUSE ops for /
420 * these just delegate to the /proc and /cgroup ops as
421 * needed
422 */
423
424 static int lxcfs_getattr(const char *path, struct stat *sb)
425 {
426 int ret;
427 struct timespec now;
428
429 if (strcmp(path, "/") == 0) {
430 if (clock_gettime(CLOCK_REALTIME, &now) < 0)
431 return -EINVAL;
432 sb->st_uid = sb->st_gid = 0;
433 sb->st_atim = sb->st_mtim = sb->st_ctim = now;
434 sb->st_size = 0;
435 sb->st_mode = S_IFDIR | 00755;
436 sb->st_nlink = 2;
437 return 0;
438 }
439
440 if (strncmp(path, "/cgroup", 7) == 0) {
441 up_users();
442 ret = do_cg_getattr(path, sb);
443 down_users();
444 return ret;
445 }
446 if (strncmp(path, "/proc", 5) == 0) {
447 up_users();
448 ret = do_proc_getattr(path, sb);
449 down_users();
450 return ret;
451 }
452 return -EINVAL;
453 }
454
455 static int lxcfs_opendir(const char *path, struct fuse_file_info *fi)
456 {
457 int ret;
458 if (strcmp(path, "/") == 0)
459 return 0;
460
461 if (strncmp(path, "/cgroup", 7) == 0) {
462 up_users();
463 ret = do_cg_opendir(path, fi);
464 down_users();
465 return ret;
466 }
467 if (strcmp(path, "/proc") == 0)
468 return 0;
469 return -ENOENT;
470 }
471
472 static int lxcfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
473 struct fuse_file_info *fi)
474 {
475 int ret;
476 if (strcmp(path, "/") == 0) {
477 if (filler(buf, "proc", NULL, 0) != 0 ||
478 filler(buf, "cgroup", NULL, 0) != 0)
479 return -EINVAL;
480 return 0;
481 }
482 if (strncmp(path, "/cgroup", 7) == 0) {
483 up_users();
484 ret = do_cg_readdir(path, buf, filler, offset, fi);
485 down_users();
486 return ret;
487 }
488 if (strcmp(path, "/proc") == 0) {
489 up_users();
490 ret = do_proc_readdir(path, buf, filler, offset, fi);
491 down_users();
492 return ret;
493 }
494 return -EINVAL;
495 }
496
497 static int lxcfs_access(const char *path, int mode)
498 {
499 int ret;
500
501 if (strcmp(path, "/") == 0 && access(path, R_OK) == 0)
502 return 0;
503
504 if (strncmp(path, "/cgroup", 7) == 0) {
505 up_users();
506 ret = do_cg_access(path, mode);
507 down_users();
508 return ret;
509 }
510 if (strncmp(path, "/proc", 5) == 0) {
511 up_users();
512 ret = do_proc_access(path, mode);
513 down_users();
514 return ret;
515 }
516
517 return -EINVAL;
518 }
519
520 static int lxcfs_releasedir(const char *path, struct fuse_file_info *fi)
521 {
522 int ret;
523 if (strcmp(path, "/") == 0)
524 return 0;
525 if (strncmp(path, "/cgroup", 7) == 0) {
526 up_users();
527 ret = do_cg_releasedir(path, fi);
528 down_users();
529 return ret;
530 }
531 if (strcmp(path, "/proc") == 0)
532 return 0;
533 return -EINVAL;
534 }
535
536 static int lxcfs_open(const char *path, struct fuse_file_info *fi)
537 {
538 int ret;
539 if (strncmp(path, "/cgroup", 7) == 0) {
540 up_users();
541 ret = do_cg_open(path, fi);
542 down_users();
543 return ret;
544 }
545 if (strncmp(path, "/proc", 5) == 0) {
546 up_users();
547 ret = do_proc_open(path, fi);
548 down_users();
549 return ret;
550 }
551
552 return -EINVAL;
553 }
554
555 static int lxcfs_read(const char *path, char *buf, size_t size, off_t offset,
556 struct fuse_file_info *fi)
557 {
558 int ret;
559 if (strncmp(path, "/cgroup", 7) == 0) {
560 up_users();
561 ret = do_cg_read(path, buf, size, offset, fi);
562 down_users();
563 return ret;
564 }
565 if (strncmp(path, "/proc", 5) == 0) {
566 up_users();
567 ret = do_proc_read(path, buf, size, offset, fi);
568 down_users();
569 return ret;
570 }
571
572 return -EINVAL;
573 }
574
575 int lxcfs_write(const char *path, const char *buf, size_t size, off_t offset,
576 struct fuse_file_info *fi)
577 {
578 int ret;
579 if (strncmp(path, "/cgroup", 7) == 0) {
580 up_users();
581 ret = do_cg_write(path, buf, size, offset, fi);
582 down_users();
583 return ret;
584 }
585
586 return -EINVAL;
587 }
588
589 static int lxcfs_flush(const char *path, struct fuse_file_info *fi)
590 {
591 return 0;
592 }
593
594 static int lxcfs_release(const char *path, struct fuse_file_info *fi)
595 {
596 int ret;
597 if (strncmp(path, "/cgroup", 7) == 0) {
598 up_users();
599 ret = do_cg_release(path, fi);
600 down_users();
601 return ret;
602 }
603 if (strncmp(path, "/proc", 5) == 0) {
604 up_users();
605 ret = do_proc_release(path, fi);
606 down_users();
607 return ret;
608 }
609
610 return -EINVAL;
611 }
612
613 static int lxcfs_fsync(const char *path, int datasync, struct fuse_file_info *fi)
614 {
615 return 0;
616 }
617
618 int lxcfs_mkdir(const char *path, mode_t mode)
619 {
620 int ret;
621 if (strncmp(path, "/cgroup", 7) == 0) {
622 up_users();
623 ret = do_cg_mkdir(path, mode);
624 down_users();
625 return ret;
626 }
627
628 return -EINVAL;
629 }
630
631 int lxcfs_chown(const char *path, uid_t uid, gid_t gid)
632 {
633 int ret;
634 if (strncmp(path, "/cgroup", 7) == 0) {
635 up_users();
636 ret = do_cg_chown(path, uid, gid);
637 down_users();
638 return ret;
639 }
640
641 return -EINVAL;
642 }
643
644 /*
645 * cat first does a truncate before doing ops->write. This doesn't
646 * really make sense for cgroups. So just return 0 always but do
647 * nothing.
648 */
649 int lxcfs_truncate(const char *path, off_t newsize)
650 {
651 if (strncmp(path, "/cgroup", 7) == 0)
652 return 0;
653 return -EINVAL;
654 }
655
656 int lxcfs_rmdir(const char *path)
657 {
658 int ret;
659 if (strncmp(path, "/cgroup", 7) == 0) {
660 up_users();
661 ret = do_cg_rmdir(path);
662 down_users();
663 return ret;
664 }
665 return -EINVAL;
666 }
667
668 int lxcfs_chmod(const char *path, mode_t mode)
669 {
670 int ret;
671 if (strncmp(path, "/cgroup", 7) == 0) {
672 up_users();
673 ret = do_cg_chmod(path, mode);
674 down_users();
675 return ret;
676 }
677 return -EINVAL;
678 }
679
680 const struct fuse_operations lxcfs_ops = {
681 .getattr = lxcfs_getattr,
682 .readlink = NULL,
683 .getdir = NULL,
684 .mknod = NULL,
685 .mkdir = lxcfs_mkdir,
686 .unlink = NULL,
687 .rmdir = lxcfs_rmdir,
688 .symlink = NULL,
689 .rename = NULL,
690 .link = NULL,
691 .chmod = lxcfs_chmod,
692 .chown = lxcfs_chown,
693 .truncate = lxcfs_truncate,
694 .utime = NULL,
695
696 .open = lxcfs_open,
697 .read = lxcfs_read,
698 .release = lxcfs_release,
699 .write = lxcfs_write,
700
701 .statfs = NULL,
702 .flush = lxcfs_flush,
703 .fsync = lxcfs_fsync,
704
705 .setxattr = NULL,
706 .getxattr = NULL,
707 .listxattr = NULL,
708 .removexattr = NULL,
709
710 .opendir = lxcfs_opendir,
711 .readdir = lxcfs_readdir,
712 .releasedir = lxcfs_releasedir,
713
714 .fsyncdir = NULL,
715 .init = NULL,
716 .destroy = NULL,
717 .access = lxcfs_access,
718 .create = NULL,
719 .ftruncate = NULL,
720 .fgetattr = NULL,
721 };
722
723 static void usage(const char *me)
724 {
725 fprintf(stderr, "Usage:\n");
726 fprintf(stderr, "\n");
727 fprintf(stderr, "%s [-p pidfile] mountpoint\n", me);
728 fprintf(stderr, " Default pidfile is %s/lxcfs.pid\n", RUNTIME_PATH);
729 fprintf(stderr, "%s -h\n", me);
730 exit(1);
731 }
732
733 static bool is_help(char *w)
734 {
735 if (strcmp(w, "-h") == 0 ||
736 strcmp(w, "--help") == 0 ||
737 strcmp(w, "-help") == 0 ||
738 strcmp(w, "help") == 0)
739 return true;
740 return false;
741 }
742
743 void swallow_arg(int *argcp, char *argv[], char *which)
744 {
745 int i;
746
747 for (i = 1; argv[i]; i++) {
748 if (strcmp(argv[i], which) != 0)
749 continue;
750 for (; argv[i]; i++) {
751 argv[i] = argv[i+1];
752 }
753 (*argcp)--;
754 return;
755 }
756 }
757
758 bool swallow_option(int *argcp, char *argv[], char *opt, char **v)
759 {
760 int i;
761
762 for (i = 1; argv[i]; i++) {
763 if (!argv[i+1])
764 continue;
765 if (strcmp(argv[i], opt) != 0)
766 continue;
767 do {
768 *v = strdup(argv[i+1]);
769 } while (!*v);
770 for (; argv[i+1]; i++) {
771 argv[i] = argv[i+2];
772 }
773 (*argcp) -= 2;
774 return true;
775 }
776 return false;
777 }
778
779 static int set_pidfile(char *pidfile)
780 {
781 int fd;
782 char buf[50];
783 struct flock fl;
784
785 fl.l_type = F_WRLCK;
786 fl.l_whence = SEEK_SET;
787 fl.l_start = 0;
788 fl.l_len = 0;
789
790 fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
791 if (fd == -1) {
792 fprintf(stderr, "Could not open pidfile %s: %m", pidfile);
793 return -1;
794 }
795
796 if (fcntl(fd, F_SETLK, &fl) == -1) {
797 if (errno == EAGAIN || errno == EACCES) {
798 fprintf(stderr, "PID file '%s' is already locked.\n", pidfile);
799 close(fd);
800 return -1;
801 }
802 fprintf(stderr, "Warning; unable to lock PID file, proceeding.\n");
803 }
804
805 if (ftruncate(fd, 0) == -1) {
806 fprintf(stderr, "Error truncating PID file '%s': %m", pidfile);
807 close(fd);
808 return -1;
809 }
810
811 snprintf(buf, 50, "%ld\n", (long) getpid());
812 if (write(fd, buf, strlen(buf)) != strlen(buf)) {
813 fprintf(stderr, "Error writing to PID file '%s': %m", pidfile);
814 close(fd);
815 return -1;
816 }
817
818 return fd;
819 }
820
821 int main(int argc, char *argv[])
822 {
823 int ret = EXIT_FAILURE;
824 int pidfd = -1;
825 char *pidfile = NULL, *v = NULL;
826 size_t pidfile_len;
827 /*
828 * what we pass to fuse_main is:
829 * argv[0] -s -f -o allow_other,directio argv[1] NULL
830 */
831 int nargs = 5, cnt = 0;
832 char *newargv[6];
833
834 /* accomodate older init scripts */
835 swallow_arg(&argc, argv, "-s");
836 swallow_arg(&argc, argv, "-f");
837 if (swallow_option(&argc, argv, "-o", &v)) {
838 if (strcmp(v, "allow_other") != 0) {
839 fprintf(stderr, "Warning: unexpected fuse option %s\n", v);
840 exit(EXIT_FAILURE);
841 }
842 free(v);
843 v = NULL;
844 }
845 if (swallow_option(&argc, argv, "-p", &v))
846 pidfile = v;
847
848 if (argc == 2 && strcmp(argv[1], "--version") == 0) {
849 fprintf(stderr, "%s\n", VERSION);
850 exit(EXIT_SUCCESS);
851 }
852 if (argc != 2 || is_help(argv[1]))
853 usage(argv[0]);
854
855 do_reload();
856 if (signal(SIGUSR1, reload_handler) == SIG_ERR) {
857 fprintf(stderr, "Error setting USR1 signal handler: %m\n");
858 goto out;
859 }
860
861 newargv[cnt++] = argv[0];
862 newargv[cnt++] = "-f";
863 newargv[cnt++] = "-o";
864 newargv[cnt++] = "allow_other,direct_io,entry_timeout=0.5,attr_timeout=0.5";
865 newargv[cnt++] = argv[1];
866 newargv[cnt++] = NULL;
867
868 if (!pidfile) {
869 pidfile_len = strlen(RUNTIME_PATH) + strlen("/lxcfs.pid") + 1;
870 pidfile = alloca(pidfile_len);
871 snprintf(pidfile, pidfile_len, "%s/lxcfs.pid", RUNTIME_PATH);
872 }
873 if ((pidfd = set_pidfile(pidfile)) < 0)
874 goto out;
875
876 if (!fuse_main(nargs, newargv, &lxcfs_ops, NULL))
877 ret = EXIT_SUCCESS;
878
879 out:
880 if (dlopen_handle)
881 dlclose(dlopen_handle);
882 if (pidfile)
883 unlink(pidfile);
884 if (pidfd > 0)
885 close(pidfd);
886 exit(ret);
887 }