5
5
6
6
#include <assert.h>
7
7
#include <fcntl.h>
8
+ #include <libgen.h>
8
9
#include <stdbool.h>
9
10
#include <stdio.h>
10
11
#include <stdlib.h>
11
12
#include <string.h>
13
+ #include <sys/ioctl.h>
12
14
#include <sys/mman.h>
13
15
#include <sys/stat.h>
14
16
#include <unistd.h>
15
17
18
+ #if defined(__APPLE__ )
19
+ #include <sys/disk.h> /* DKIOCGETBLOCKCOUNT and DKIOCGETBLOCKSIZE */
20
+ #else
21
+ #include <linux/fs.h> /* BLKGETSIZE64 */
22
+ #endif
23
+
16
24
#include "virtio.h"
17
25
18
26
#define DISK_BLK_SIZE 512
@@ -394,25 +402,57 @@ uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, char *disk_file)
394
402
int disk_fd = open (disk_file , O_RDWR );
395
403
if (disk_fd < 0 ) {
396
404
rv_log_error ("Could not open %s" , disk_file );
397
- exit ( EXIT_FAILURE ) ;
405
+ goto fail ;
398
406
}
399
407
400
- /* Get the disk image size */
401
- struct stat st ;
402
- fstat (disk_fd , & st );
403
- VBLK_PRIV (vblk )-> disk_size = st .st_size ;
408
+ const char * disk_file_dirname = dirname (disk_file );
409
+ if (!disk_file_dirname ) {
410
+ rv_log_error ("Fail dirname disk_file: %s" , disk_file );
411
+ goto disk_size_fail ;
412
+ }
413
+ /* Get the disk size */
414
+ uint64_t disk_size ;
415
+ if (strcmp (disk_file_dirname , "/dev" ) ==
416
+ 0 ) { /* from /dev/, leverage ioctl */
417
+ #if defined(__APPLE__ )
418
+ uint32_t block_size ;
419
+ uint64_t block_count ;
420
+ if (ioctl (disk_fd , DKIOCGETBLOCKCOUNT , & block_count ) == -1 ) {
421
+ rv_log_error ("DKIOCGETBLOCKCOUNT failed" );
422
+ goto disk_size_fail ;
423
+ }
424
+ if (ioctl (disk_fd , DKIOCGETBLOCKSIZE , & block_size ) == -1 ) {
425
+ rv_log_error ("DKIOCGETBLOCKSIZE failed" );
426
+ goto disk_size_fail ;
427
+ }
428
+ disk_size = block_count * block_size ;
429
+ #else /* Linux */
430
+ if (ioctl (disk_fd , BLKGETSIZE64 , & disk_size ) == -1 ) {
431
+ rv_log_error ("BLKGETSIZE64 failed" );
432
+ goto disk_size_fail ;
433
+ }
434
+ #endif
435
+ } else { /* other path, stat it as normal file */
436
+ struct stat st ;
437
+ if (fstat (disk_fd , & st ) == -1 ) {
438
+ rv_log_error ("fstat failed" );
439
+ goto disk_size_fail ;
440
+ }
441
+ disk_size = st .st_size ;
442
+ }
443
+ VBLK_PRIV (vblk )-> disk_size = disk_size ;
404
444
405
445
/* Set up the disk memory */
406
446
uint32_t * disk_mem ;
407
447
#if HAVE_MMAP
408
448
disk_mem = mmap (NULL , VBLK_PRIV (vblk )-> disk_size , PROT_READ | PROT_WRITE ,
409
449
MAP_SHARED , disk_fd , 0 );
410
450
if (disk_mem == MAP_FAILED )
411
- goto err ;
451
+ goto disk_mem_err ;
412
452
#else
413
453
disk_mem = malloc (VBLK_PRIV (vblk )-> disk_size );
414
454
if (!disk_mem )
415
- goto err ;
455
+ goto disk_mem_err ;
416
456
#endif
417
457
assert (!(((uintptr_t ) disk_mem ) & 0b11 ));
418
458
close (disk_fd );
@@ -423,9 +463,14 @@ uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, char *disk_file)
423
463
424
464
return disk_mem ;
425
465
426
- err :
466
+ disk_mem_err :
427
467
rv_log_error ("Could not map disk %s" , disk_file );
428
- return NULL ;
468
+
469
+ disk_size_fail :
470
+ close (disk_fd );
471
+
472
+ fail :
473
+ exit (EXIT_FAILURE );
429
474
}
430
475
431
476
virtio_blk_state_t * vblk_new ()
0 commit comments