7
7
#include <string.h>
8
8
#include <errno.h>
9
9
#include <unistd.h>
10
- #define FUSE_USE_VERSION 26
11
- #include <fuse.h>
12
- #include <fuse /fuse_opt.h>
13
- #include <fuse /fuse_lowlevel.h>
10
+ #define FUSE_USE_VERSION 35
11
+ #include <fuse3/ fuse.h>
12
+ #include <fuse3 /fuse_opt.h>
13
+ #include <fuse3 /fuse_lowlevel.h>
14
14
#include <lkl.h>
15
15
#include <lkl_host.h>
16
16
17
- #define LKLFUSE_VERSION "0.1 "
17
+ #define LKLFUSE_VERSION "0.3 "
18
18
19
19
struct lklfuse {
20
20
const char * file ;
@@ -63,7 +63,7 @@ static void usage(void)
63
63
"lklfuse options:\n"
64
64
" -o log=FILE log file\n"
65
65
" -o type=fstype filesystem type\n"
66
- " -o mb=memory in mb ammount of memory to allocate\n"
66
+ " -o mb=memory amount of memory to allocate in MB (default: 64) \n"
67
67
" -o part=parition partition to mount\n"
68
68
" -o ro open file read-only\n"
69
69
" -o opts=options mount options (use \\ to escape , and =)\n"
@@ -88,7 +88,9 @@ static int lklfuse_opt_proc(void *data, const char *arg, int key,
88
88
89
89
case KEY_HELP :
90
90
usage ();
91
- fuse_opt_add_arg (args , "-ho" );
91
+ /* suppress fuse usage */
92
+ args -> argv [0 ] = "" ;
93
+ fuse_opt_add_arg (args , "-h" );
92
94
fuse_main (args -> argc , args -> argv , NULL , NULL );
93
95
exit (1 );
94
96
@@ -124,31 +126,24 @@ static void lklfuse_xlat_stat(const struct lkl_stat *in, struct stat *st)
124
126
st -> st_ctim .tv_nsec = in -> st_ctime_nsec ;
125
127
}
126
128
127
- static int lklfuse_fgetattr (const char * path , struct stat * st ,
128
- struct fuse_file_info * fi )
129
+ static int lklfuse_getattr (const char * path , struct stat * st ,
130
+ struct fuse_file_info * fi )
129
131
{
130
132
long ret ;
131
133
struct lkl_stat lkl_stat ;
132
134
133
- ret = lkl_sys_fstat (fi -> fh , & lkl_stat );
134
- if (ret )
135
- return ret ;
136
-
137
- lklfuse_xlat_stat (& lkl_stat , st );
138
- return 0 ;
139
- }
140
-
141
- static int lklfuse_getattr (const char * path , struct stat * st )
142
- {
143
- long ret ;
144
- struct lkl_stat lkl_stat ;
145
-
146
- ret = lkl_sys_lstat (path , & lkl_stat );
147
- if (ret )
148
- return ret ;
135
+ /*
136
+ * With nullpath_ok, path will be provided only if the struct
137
+ * fuse_file_info argument is NULL.
138
+ */
139
+ if (fi )
140
+ ret = lkl_sys_fstat (fi -> fh , & lkl_stat );
141
+ else
142
+ ret = lkl_sys_lstat (path , & lkl_stat );
143
+ if (!ret )
144
+ lklfuse_xlat_stat (& lkl_stat , st );
149
145
150
- lklfuse_xlat_stat (& lkl_stat , st );
151
- return 0 ;
146
+ return ret ;
152
147
}
153
148
154
149
static int lklfuse_readlink (const char * path , char * buf , size_t len )
@@ -193,31 +188,56 @@ static int lklfuse_symlink(const char *oldname, const char *newname)
193
188
}
194
189
195
190
196
- static int lklfuse_rename (const char * oldname , const char * newname )
191
+ static int lklfuse_rename (const char * oldname , const char * newname ,
192
+ unsigned int flags )
197
193
{
198
- return lkl_sys_rename (oldname , newname );
194
+ /* libfuse: *flags* may be `RENAME_EXCHANGE` or `RENAME_NOREPLACE` */
195
+ return lkl_sys_renameat2 (LKL_AT_FDCWD , oldname , LKL_AT_FDCWD , newname ,
196
+ flags );
199
197
}
200
198
201
199
static int lklfuse_link (const char * oldname , const char * newname )
202
200
{
203
201
return lkl_sys_link (oldname , newname );
204
202
}
205
203
206
- static int lklfuse_chmod (const char * path , mode_t mode )
204
+ static int lklfuse_chmod (const char * path , mode_t mode ,
205
+ struct fuse_file_info * fi )
207
206
{
208
- return lkl_sys_chmod (path , mode );
209
- }
207
+ int ret ;
210
208
209
+ if (fi )
210
+ ret = lkl_sys_fchmod (fi -> fh , mode );
211
+ else
212
+ ret = lkl_sys_fchmodat (LKL_AT_FDCWD , path , mode );
211
213
212
- static int lklfuse_chown (const char * path , uid_t uid , gid_t gid )
214
+ return ret ;
215
+ }
216
+
217
+ static int lklfuse_chown (const char * path , uid_t uid , gid_t gid ,
218
+ struct fuse_file_info * fi )
213
219
{
214
- return lkl_sys_fchownat (LKL_AT_FDCWD , path , uid , gid ,
220
+ int ret ;
221
+
222
+ if (fi )
223
+ ret = lkl_sys_fchown (fi -> fh , uid , gid );
224
+ else
225
+ ret = lkl_sys_fchownat (LKL_AT_FDCWD , path , uid , gid ,
215
226
LKL_AT_SYMLINK_NOFOLLOW );
227
+ return ret ;
216
228
}
217
229
218
- static int lklfuse_truncate (const char * path , off_t off )
230
+ static int lklfuse_truncate (const char * path , off_t off ,
231
+ struct fuse_file_info * fi )
219
232
{
220
- return lkl_sys_truncate (path , off );
233
+ int ret ;
234
+
235
+ if (fi )
236
+ ret = lkl_sys_ftruncate (fi -> fh , off );
237
+ else
238
+ ret = lkl_sys_truncate (path , off );
239
+
240
+ return ret ;
221
241
}
222
242
223
243
static int lklfuse_open3 (const char * path , bool create , mode_t mode ,
@@ -397,7 +417,8 @@ static int lklfuse_opendir(const char *path, struct fuse_file_info *fi)
397
417
* Introduced in version 2.3
398
418
*/
399
419
static int lklfuse_readdir (const char * path , void * buf , fuse_fill_dir_t fill ,
400
- off_t off , struct fuse_file_info * fi )
420
+ off_t off , struct fuse_file_info * fi ,
421
+ enum fuse_readdir_flags flags )
401
422
{
402
423
struct lkl_dir * dir = (struct lkl_dir * )(uintptr_t )fi -> fh ;
403
424
struct lkl_linux_dirent64 * de ;
@@ -408,7 +429,7 @@ static int lklfuse_readdir(const char *path, void *buf, fuse_fill_dir_t fill,
408
429
st .st_ino = de -> d_ino ;
409
430
st .st_mode = de -> d_type << 12 ;
410
431
411
- if (fill (buf , de -> d_name , & st , 0 ))
432
+ if (fill (buf , de -> d_name , & st , 0 , 0 ))
412
433
break ;
413
434
}
414
435
@@ -442,17 +463,24 @@ static int lklfuse_access(const char *path, int mode)
442
463
return lkl_sys_access (path , mode );
443
464
}
444
465
445
- static int lklfuse_utimens (const char * path , const struct timespec tv [2 ])
466
+ static int lklfuse_utimens (const char * path , const struct timespec tv [2 ],
467
+ struct fuse_file_info * fi )
446
468
{
447
- struct lkl_timespec ts [2 ];
448
-
449
- ts [0 ].tv_sec = tv [0 ].tv_sec ;
450
- ts [0 ].tv_nsec = tv [0 ].tv_nsec ;
451
- ts [1 ].tv_sec = tv [0 ].tv_sec ;
452
- ts [1 ].tv_nsec = tv [0 ].tv_nsec ;
453
-
454
- return lkl_sys_utimensat (-1 , path , (struct __lkl__kernel_timespec * )ts ,
455
- LKL_AT_SYMLINK_NOFOLLOW );
469
+ int ret ;
470
+ struct lkl_timespec ts [2 ] = {
471
+ { .tv_sec = tv [0 ].tv_sec , .tv_nsec = tv [0 ].tv_nsec },
472
+ { .tv_sec = tv [1 ].tv_sec , .tv_nsec = tv [1 ].tv_nsec },
473
+ };
474
+
475
+ if (fi )
476
+ ret = lkl_sys_utimensat (fi -> fh , NULL ,
477
+ (struct __lkl__kernel_timespec * )ts ,
478
+ 0 );
479
+ else
480
+ ret = lkl_sys_utimensat (-1 , path ,
481
+ (struct __lkl__kernel_timespec * )ts ,
482
+ LKL_AT_SYMLINK_NOFOLLOW );
483
+ return ret ;
456
484
}
457
485
458
486
static int lklfuse_fallocate (const char * path , int mode , off_t offset ,
@@ -461,10 +489,14 @@ static int lklfuse_fallocate(const char *path, int mode, off_t offset,
461
489
return lkl_sys_fallocate (fi -> fh , mode , offset , len );
462
490
}
463
491
492
+ static void * lklfuse_init (struct fuse_conn_info * conn , struct fuse_config * cfg )
493
+ {
494
+ cfg -> nullpath_ok = 1 ;
495
+ return NULL ;
496
+ }
497
+
464
498
const struct fuse_operations lklfuse_ops = {
465
- .flag_nullpath_ok = 1 ,
466
- .flag_nopath = 1 ,
467
- .flag_utime_omit_ok = 1 ,
499
+ .init = lklfuse_init ,
468
500
469
501
.getattr = lklfuse_getattr ,
470
502
.readlink = lklfuse_readlink ,
@@ -495,7 +527,6 @@ const struct fuse_operations lklfuse_ops = {
495
527
.fsyncdir = lklfuse_fsyncdir ,
496
528
.access = lklfuse_access ,
497
529
.create = lklfuse_create ,
498
- .fgetattr = lklfuse_fgetattr ,
499
530
/* .lock, */
500
531
.utimens = lklfuse_utimens ,
501
532
/* .bmap, */
@@ -511,13 +542,30 @@ static int start_lkl(void)
511
542
{
512
543
long ret ;
513
544
char mpoint [32 ];
545
+ struct timespec walltime ;
546
+ struct lkl_timespec ts ;
514
547
515
548
ret = lkl_start_kernel ("mem=%dM" , lklfuse .mb );
516
549
if (ret ) {
517
550
fprintf (stderr , "can't start kernel: %s\n" , lkl_strerror (ret ));
518
551
goto out ;
519
552
}
520
553
554
+ /* forward host walltime to lkl */
555
+ ret = clock_gettime (CLOCK_REALTIME , & walltime );
556
+ if (ret < 0 )
557
+ goto out_halt ;
558
+
559
+ ts = (struct lkl_timespec ){ .tv_sec = walltime .tv_sec ,
560
+ .tv_nsec = walltime .tv_nsec };
561
+ ret = lkl_sys_clock_settime (LKL_CLOCK_REALTIME ,
562
+ (struct __lkl__kernel_timespec * )& ts );
563
+ if (ret < 0 ) {
564
+ fprintf (stderr , "lkl_sys_clock_settime() failed: %s\n" ,
565
+ lkl_strerror (ret ));
566
+ goto out_halt ;
567
+ }
568
+
521
569
ret = lkl_mount_dev (lklfuse .disk_id , lklfuse .part , lklfuse .type ,
522
570
lklfuse .ro ? LKL_MS_RDONLY : 0 , lklfuse .opts ,
523
571
mpoint , sizeof (mpoint ));
@@ -563,11 +611,10 @@ static void stop_lkl(void)
563
611
int main (int argc , char * * argv )
564
612
{
565
613
struct fuse_args args = FUSE_ARGS_INIT (argc , argv );
566
- struct fuse_chan * ch ;
614
+ struct fuse_cmdline_opts cli_opts ;
567
615
struct fuse * fuse ;
568
616
struct stat st ;
569
- char * mnt ;
570
- int fg , mt , ret ;
617
+ int ret ;
571
618
572
619
if (fuse_opt_parse (& args , & lklfuse , lklfuse_opts , lklfuse_opt_proc ))
573
620
return 1 ;
@@ -577,12 +624,12 @@ int main(int argc, char **argv)
577
624
return 1 ;
578
625
}
579
626
580
- if (fuse_parse_cmdline (& args , & mnt , & mt , & fg ))
627
+ if (fuse_parse_cmdline (& args , & cli_opts ))
581
628
return 1 ;
582
629
583
- ret = stat (mnt , & st );
630
+ ret = stat (cli_opts . mountpoint , & st );
584
631
if (ret ) {
585
- perror (mnt );
632
+ perror (cli_opts . mountpoint );
586
633
goto out_free ;
587
634
}
588
635
@@ -608,49 +655,47 @@ int main(int argc, char **argv)
608
655
609
656
lklfuse .disk_id = ret ;
610
657
611
- ch = fuse_mount ( mnt , & args );
612
- if (!ch ) {
658
+ fuse = fuse_new ( & args , & lklfuse_ops , sizeof ( lklfuse_ops ), NULL );
659
+ if (!fuse ) {
613
660
ret = -1 ;
614
661
goto out_close_disk ;
615
662
}
616
663
617
- fuse = fuse_new (ch , & args , & lklfuse_ops , sizeof (lklfuse_ops ), NULL );
618
- if (!fuse ) {
619
- ret = -1 ;
620
- goto out_fuse_unmount ;
621
- }
664
+ ret = fuse_set_signal_handlers (fuse_get_session (fuse ));
665
+ if (ret < 0 )
666
+ goto out_fuse_destroy ;
667
+
668
+ ret = fuse_mount (fuse , cli_opts .mountpoint );
669
+ if (ret < 0 )
670
+ goto out_remove_signals ;
622
671
623
672
fuse_opt_free_args (& args );
624
673
625
- if (fuse_daemonize (fg ) ||
626
- fuse_set_signal_handlers (fuse_get_session (fuse ))) {
627
- ret = -1 ;
628
- goto out_fuse_destroy ;
629
- }
674
+ ret = fuse_daemonize (cli_opts .foreground );
675
+ if (ret < 0 )
676
+ goto out_fuse_unmount ;
630
677
631
678
ret = start_lkl ();
632
679
if (ret ) {
633
680
ret = -1 ;
634
- goto out_remove_signals ;
681
+ goto out_fuse_unmount ;
635
682
}
636
683
637
- if (mt )
684
+ if (! cli_opts . singlethread )
638
685
fprintf (stderr , "warning: multithreaded mode not supported\n" );
639
686
640
687
ret = fuse_loop (fuse );
641
688
642
689
stop_lkl ();
643
690
691
+ out_fuse_unmount :
692
+ fuse_unmount (fuse );
693
+
644
694
out_remove_signals :
645
695
fuse_remove_signal_handlers (fuse_get_session (fuse ));
646
696
647
- out_fuse_unmount :
648
- if (ch )
649
- fuse_unmount (mnt , ch );
650
-
651
697
out_fuse_destroy :
652
- if (fuse )
653
- fuse_destroy (fuse );
698
+ fuse_destroy (fuse );
654
699
655
700
out_lkl_cleanup :
656
701
lkl_cleanup ();
@@ -659,7 +704,7 @@ int main(int argc, char **argv)
659
704
close (lklfuse .disk .fd );
660
705
661
706
out_free :
662
- free (mnt );
707
+ free (cli_opts . mountpoint );
663
708
664
709
return ret < 0 ? 1 : 0 ;
665
710
}
0 commit comments