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