1 /******************************************************************************
2 * vtoydm.c ---- ventoy device mapper tool
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 #include <sys/types.h>
29 #include <sys/ioctl.h>
31 #include <sys/types.h>
34 #include "biso_list.h"
35 #include "biso_util.h"
36 #include "biso_plat.h"
37 #include "biso_9660.h"
45 typedef unsigned long long uint64_t;
47 typedef unsigned int uint32_t;
51 typedef struct ventoy_img_chunk
53 uint32_t img_start_sector
; // sector size: 2KB
54 uint32_t img_end_sector
; // included
56 uint64_t disk_start_sector
; // in disk_sector_size
57 uint64_t disk_end_sector
; // included
61 static int verbose
= 0;
62 #define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__)
64 #define CMD_PRINT_TABLE 1
65 #define CMD_CREATE_DM 2
66 #define CMD_DUMP_ISO_INFO 3
67 #define CMD_EXTRACT_ISO_FILE 4
68 #define CMD_PRINT_EXTRACT_ISO_FILE 5
70 static uint64_t g_iso_file_size
;
71 static char g_disk_name
[128];
72 static int g_img_chunk_num
= 0;
73 static ventoy_img_chunk
*g_img_chunk
= NULL
;
74 static unsigned char g_iso_sector_buf
[2048];
76 ventoy_img_chunk
* vtoydm_get_img_map_data(const char *img_map_file
, int *plen
)
81 ventoy_img_chunk
*chunk
= NULL
;
83 fp
= fopen(img_map_file
, "rb");
86 fprintf(stderr
, "Failed to open file %s err:%d\n", img_map_file
, errno
);
90 fseek(fp
, 0, SEEK_END
);
92 fseek(fp
, 0, SEEK_SET
);
94 debug("File <%s> len:%d\n", img_map_file
, len
);
96 chunk
= (ventoy_img_chunk
*)malloc(len
);
99 fprintf(stderr
, "Failed to malloc memory len:%d err:%d\n", len
, errno
);
103 if (fread(chunk
, 1, len
, fp
) != len
)
105 fprintf(stderr
, "Failed to read file err:%d\n", errno
);
109 if (len
% sizeof(ventoy_img_chunk
))
111 fprintf(stderr
, "image map file size %d is not aligned with %d\n",
112 len
, (int)sizeof(ventoy_img_chunk
));
134 UINT64
vtoydm_get_file_size(const char *pcFileName
)
138 debug("vtoydm_get_file_size %s %lu\n", pcFileName
, (unsigned long)g_iso_file_size
);
140 return g_iso_file_size
;
143 BISO_FILE_S
* vtoydm_open_file(const char *pcFileName
)
147 debug("vtoydm_open_file %s\n", pcFileName
);
149 file
= malloc(sizeof(BISO_FILE_S
));
152 memset(file
, 0, sizeof(BISO_FILE_S
));
154 file
->FileSize
= g_iso_file_size
;
161 void vtoydm_close_file(BISO_FILE_S
*pstFile
)
163 debug("vtoydm_close_file\n");
171 INT64
vtoydm_seek_file(BISO_FILE_S
*pstFile
, INT64 i64Offset
, INT iFromWhere
)
173 debug("vtoydm_seek_file %d\n", (int)i64Offset
);
175 if (iFromWhere
== SEEK_SET
)
177 pstFile
->CurPos
= (UINT64
)i64Offset
;
183 UINT64
vtoydm_map_iso_sector(UINT64 sector
)
186 UINT64 disk_sector
= 0;
188 for (i
= 0; i
< g_img_chunk_num
; i
++)
190 if (sector
>= g_img_chunk
[i
].img_start_sector
&& sector
<= g_img_chunk
[i
].img_end_sector
)
192 disk_sector
= ((sector
- g_img_chunk
[i
].img_start_sector
) << 2) + g_img_chunk
[i
].disk_start_sector
;
200 int vtoydm_read_iso_sector(UINT64 sector
, void *buf
)
204 UINT64 disk_sector
= 0;
206 for (i
= 0; i
< g_img_chunk_num
; i
++)
208 if (sector
>= g_img_chunk
[i
].img_start_sector
&& sector
<= g_img_chunk
[i
].img_end_sector
)
210 disk_sector
= ((sector
- g_img_chunk
[i
].img_start_sector
) << 2) + g_img_chunk
[i
].disk_start_sector
;
215 fd
= open(g_disk_name
, O_RDONLY
| O_BINARY
);
218 debug("Failed to open %s\n", g_disk_name
);
222 lseek(fd
, disk_sector
* 512, SEEK_SET
);
230 UINT64 vtoydm_read_file
232 BISO_FILE_S
*pstFile
,
240 UINT64 readlen
= uiBlkSize
* uiBlkNum
;
241 char *curbuf
= (char *)pBuf
;
243 debug("vtoydm_read_file length:%u\n", uiBlkSize
* uiBlkNum
);
245 pos
= (int)(pstFile
->CurPos
% 2048);
250 vtoydm_read_iso_sector(pstFile
->CurPos
/ 2048, g_iso_sector_buf
);
253 memcpy(curbuf
, g_iso_sector_buf
+ pos
, align
);
256 pstFile
->CurPos
+= align
;
260 memcpy(curbuf
, g_iso_sector_buf
+ pos
, readlen
);
261 pstFile
->CurPos
+= readlen
;
266 while (readlen
> 2048)
268 vtoydm_read_iso_sector(pstFile
->CurPos
/ 2048, curbuf
);
269 pstFile
->CurPos
+= 2048;
277 vtoydm_read_iso_sector(pstFile
->CurPos
/ 2048, g_iso_sector_buf
);
278 memcpy(curbuf
, g_iso_sector_buf
, readlen
);
279 pstFile
->CurPos
+= readlen
;
282 return uiBlkSize
* uiBlkNum
;
285 int vtoydm_dump_iso(const char *img_map_file
, const char *diskname
)
291 ventoy_img_chunk
*chunk
= NULL
;
293 BISO_PARSER_S
*parser
= NULL
;
294 char label
[64] = {0};
296 chunk
= vtoydm_get_img_map_data(img_map_file
, &len
);
302 for (i
= 0; i
< len
/ sizeof(ventoy_img_chunk
); i
++)
304 sector_num
= chunk
[i
].img_end_sector
- chunk
[i
].img_start_sector
+ 1;
305 g_iso_file_size
+= sector_num
* 2048;
308 strncpy(g_disk_name
, diskname
, sizeof(g_disk_name
) - 1);
310 g_img_chunk_num
= len
/ sizeof(ventoy_img_chunk
);
312 debug("iso file size : %llu\n", (unsigned long long)g_iso_file_size
);
314 iso
= BISO_AllocReadHandle();
321 ret
= BISO_OpenImage("XXX", iso
);
322 debug("open iso image ret=0x%lx\n", ret
);
324 parser
= (BISO_PARSER_S
*)iso
;
325 memcpy(label
, parser
->pstPVD
->szVolumeId
, 32);
326 for (i
= 32; i
>=0; i
--)
328 if (label
[i
] != 0 && label
[i
] != ' ')
340 printf("VENTOY_ISO_LABEL %s\n", label
);
343 BISO_DumpFileTree(iso
);
345 BISO_FreeReadHandle(iso
);
351 static int vtoydm_extract_iso
353 const char *img_map_file
,
354 const char *diskname
,
355 unsigned long first_sector
,
356 unsigned long long file_size
,
363 g_img_chunk
= vtoydm_get_img_map_data(img_map_file
, &len
);
364 if (NULL
== g_img_chunk
)
369 strncpy(g_disk_name
, diskname
, sizeof(g_disk_name
) - 1);
370 g_img_chunk_num
= len
/ sizeof(ventoy_img_chunk
);
372 fp
= fopen(outfile
, "wb");
375 fprintf(stderr
, "Failed to create file %s err:%d\n", outfile
, errno
);
380 while (file_size
> 0)
382 vtoydm_read_iso_sector(first_sector
++, g_iso_sector_buf
);
383 if (file_size
> 2048)
385 fwrite(g_iso_sector_buf
, 2048, 1, fp
);
390 fwrite(g_iso_sector_buf
, 1, file_size
, fp
);
401 static int vtoydm_print_extract_iso
403 const char *img_map_file
,
404 const char *diskname
,
405 unsigned long first_sector
,
406 unsigned long long file_size
,
413 uint32_t disk_first
= 0;
416 uint64_t size
= file_size
;
419 g_img_chunk
= vtoydm_get_img_map_data(img_map_file
, &len
);
420 if (NULL
== g_img_chunk
)
425 strncpy(g_disk_name
, diskname
, sizeof(g_disk_name
) - 1);
426 g_img_chunk_num
= len
/ sizeof(ventoy_img_chunk
);
428 fp
= fopen(outfile
, "wb");
431 fprintf(stderr
, "Failed to create file %s err:%d\n", outfile
, errno
);
436 fwrite(g_disk_name
, 1, 32, fp
);
437 fwrite(&size
, 1, 8, fp
);
439 while (file_size
> 0)
441 sector
= vtoydm_map_iso_sector(first_sector
++);
443 if (count
> 0 && sector
== last
+ 4)
454 fwrite(buf
, 1, sizeof(buf
), fp
);
462 if (file_size
> 2048)
476 fwrite(buf
, 1, sizeof(buf
), fp
);
487 static int vtoydm_print_linear_table(const char *img_map_file
, const char *diskname
)
491 uint32_t disk_sector_num
;
492 uint32_t sector_start
;
493 ventoy_img_chunk
*chunk
= NULL
;
495 chunk
= vtoydm_get_img_map_data(img_map_file
, &len
);
501 for (i
= 0; i
< len
/ sizeof(ventoy_img_chunk
); i
++)
503 sector_start
= chunk
[i
].img_start_sector
;
504 disk_sector_num
= (uint32_t)(chunk
[i
].disk_end_sector
+ 1 - chunk
[i
].disk_start_sector
);
506 /* TBD: to be more flexible */
508 printf("%u %u linear %s %llu\n",
509 (sector_start
<< 2), disk_sector_num
,
510 diskname
, (unsigned long long)chunk
[i
].disk_start_sector
);
512 if (strstr(diskname
, "nvme") || strstr(diskname
, "mmc") || strstr(diskname
, "nbd"))
514 printf("%u %u linear %sp1 %llu\n",
515 (sector_start
<< 2), disk_sector_num
,
516 diskname
, (unsigned long long)chunk
[i
].disk_start_sector
- 2048);
520 printf("%u %u linear %s1 %llu\n",
521 (sector_start
<< 2), disk_sector_num
,
522 diskname
, (unsigned long long)chunk
[i
].disk_start_sector
- 2048);
531 static int vtoydm_print_help(FILE *fp
)
533 fprintf(fp
, "Usage: \n"
534 " vtoydm -p -f img_map_file -d diskname [ -v ] \n"
535 " vtoydm -c -f img_map_file -d diskname [ -v ] \n"
536 " vtoydm -i -f img_map_file -d diskname [ -v ] \n"
537 " vtoydm -e -f img_map_file -d diskname -s sector -l len -o file [ -v ] \n"
542 int vtoydm_main(int argc
, char **argv
)
546 unsigned long first_sector
= 0;
547 unsigned long long file_size
= 0;
548 char diskname
[128] = {0};
549 char filepath
[300] = {0};
550 char outfile
[300] = {0};
552 while ((ch
= getopt(argc
, argv
, "s:l:o:d:f:v::i::p::c::h::e::E::")) != -1)
556 strncpy(diskname
, optarg
, sizeof(diskname
) - 1);
560 strncpy(filepath
, optarg
, sizeof(filepath
) - 1);
564 cmd
= CMD_PRINT_TABLE
;
572 cmd
= CMD_DUMP_ISO_INFO
;
576 cmd
= CMD_EXTRACT_ISO_FILE
;
580 cmd
= CMD_PRINT_EXTRACT_ISO_FILE
;
584 first_sector
= strtoul(optarg
, NULL
, 10);
588 file_size
= strtoull(optarg
, NULL
, 10);
592 strncpy(outfile
, optarg
, sizeof(outfile
) - 1);
600 return vtoydm_print_help(stdout
);
604 vtoydm_print_help(stderr
);
609 if (filepath
[0] == 0 || diskname
[0] == 0)
611 fprintf(stderr
, "Must input file and disk\n");
615 debug("cmd=%d file=<%s> disk=<%s> first_sector=%lu file_size=%llu\n",
616 cmd
, filepath
, diskname
, first_sector
, file_size
);
620 case CMD_PRINT_TABLE
:
622 return vtoydm_print_linear_table(filepath
, diskname
);
628 case CMD_DUMP_ISO_INFO
:
630 return vtoydm_dump_iso(filepath
, diskname
);
632 case CMD_EXTRACT_ISO_FILE
:
634 return vtoydm_extract_iso(filepath
, diskname
, first_sector
, file_size
, outfile
);
636 case CMD_PRINT_EXTRACT_ISO_FILE
:
638 return vtoydm_print_extract_iso(filepath
, diskname
, first_sector
, file_size
, outfile
);
642 fprintf(stderr
, "Invalid cmd \n");
651 #ifndef BUILD_VTOY_TOOL
652 int main(int argc
, char **argv
)
654 return vtoydm_main(argc
, argv
);