]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Vlnk/src/main_linux.c
update for scroll menu text
[Ventoy.git] / Vlnk / src / main_linux.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <sys/stat.h>
8 #include <sys/mount.h>
9 #include <sys/statfs.h>
10 #include <dirent.h>
11 #include <unistd.h>
12
13 #include "vlnk.h"
14
15 #ifndef PATH_MAX
16 #define PATH_MAX 4096
17 #endif
18
19 #define IS_DIGIT(x) ((x) >= '0' && (x) <= '9')
20
21 static int verbose = 0;
22 #define debug(fmt, args...) if(verbose) printf(fmt, ##args)
23
24 static uint8_t g_vlnk_buf[VLNK_FILE_LEN];
25
26 static int64_t get_file_size(char *file)
27 {
28 struct stat stStat;
29
30 if (stat(file, &stStat) < 0)
31 {
32 return -1;
33 }
34
35 return (int64_t)(stStat.st_size);
36 }
37
38 static int get_disk_sig(char *diskname, uint32_t *sig)
39 {
40 int fd;
41 uint8_t buf[512] = {0};
42
43 fd = open(diskname, O_RDONLY);
44 if (fd < 0)
45 {
46 printf("Failed to open %s\n", diskname);
47 return 1;
48 }
49
50 read(fd, buf, 512);
51 close(fd);
52
53 memcpy(sig, buf + 0x1b8, 4);
54 return 0;
55 }
56
57 static int vtoy_get_disk_guid(const char *diskname, uint8_t *vtguid, uint8_t *vtsig)
58 {
59 int i = 0;
60 int fd = 0;
61 char devdisk[128] = {0};
62
63 snprintf(devdisk, sizeof(devdisk) - 1, "/dev/%s", diskname);
64
65 fd = open(devdisk, O_RDONLY);
66 if (fd >= 0)
67 {
68 lseek(fd, 0x180, SEEK_SET);
69 read(fd, vtguid, 16);
70
71 lseek(fd, 0x1b8, SEEK_SET);
72 read(fd, vtsig, 4);
73 close(fd);
74 return 0;
75 }
76 else
77 {
78 debug("failed to open %s %d\n", devdisk, errno);
79 return errno;
80 }
81 }
82
83 static int vtoy_is_possible_blkdev(const char *name)
84 {
85 if (name[0] == '.')
86 {
87 return 0;
88 }
89
90 /* /dev/ramX */
91 if (name[0] == 'r' && name[1] == 'a' && name[2] == 'm')
92 {
93 return 0;
94 }
95
96 /* /dev/loopX */
97 if (name[0] == 'l' && name[1] == 'o' && name[2] == 'o' && name[3] == 'p')
98 {
99 return 0;
100 }
101
102 /* /dev/dm-X */
103 if (name[0] == 'd' && name[1] == 'm' && name[2] == '-' && IS_DIGIT(name[3]))
104 {
105 return 0;
106 }
107
108 /* /dev/srX */
109 if (name[0] == 's' && name[1] == 'r' && IS_DIGIT(name[2]))
110 {
111 return 0;
112 }
113
114 return 1;
115 }
116
117
118 static int find_disk_by_sig(uint8_t *sig, char *diskname)
119 {
120 int rc = 0;
121 int count = 0;
122 DIR* dir = NULL;
123 struct dirent* p = NULL;
124 uint8_t vtguid[16];
125 uint8_t vtsig[16];
126
127 dir = opendir("/sys/block");
128 if (!dir)
129 {
130 return 0;
131 }
132
133 while ((p = readdir(dir)) != NULL)
134 {
135 if (!vtoy_is_possible_blkdev(p->d_name))
136 {
137 continue;
138 }
139
140 rc = vtoy_get_disk_guid(p->d_name, vtguid, vtsig);
141 if (rc == 0 && memcmp(vtsig, sig, 4) == 0)
142 {
143 sprintf(diskname, "%s", p->d_name);
144 count++;
145 }
146 }
147 closedir(dir);
148
149 return count;
150 }
151
152 static uint64_t get_part_offset(char *partname)
153 {
154 int fd;
155 uint64_t offset;
156 char buf[32] = {0};
157 char path[PATH_MAX];
158
159 snprintf(path, PATH_MAX - 1, "/sys/class/block/%s/start", partname);
160
161 fd = open(path, O_RDONLY);
162 if (fd < 0)
163 {
164 return 0;
165 }
166
167 read(fd, buf, sizeof(buf));
168 close(fd);
169
170 offset = (uint64_t)strtoull(buf, NULL, 10);
171 offset *= 512;
172
173 return offset;
174 }
175
176 static int create_vlnk(char *infile, char *diskname, uint64_t partoff, char *outfile)
177 {
178 FILE *fp;
179 int len;
180 uint32_t sig = 0;
181
182 debug("create vlnk\n");
183
184 if (infile[0] == 0 || outfile[0] == 0 || diskname[0] == 0 || partoff == 0)
185 {
186 debug("Invalid parameters: %d %d %d %llu\n", infile[0], outfile[0], diskname[0], (unsigned long long)partoff);
187 return 1;
188 }
189
190 len = (int)strlen(infile);
191 if (len >= VLNK_NAME_MAX)
192 {
193 printf("File name length %d is too long for vlnk!\n", len);
194 return 1;
195 }
196
197 if (get_disk_sig(diskname, &sig))
198 {
199 printf("Failed to read disk sig\n");
200 return 1;
201 }
202
203 fp = fopen(outfile, "wb+");
204 if (!fp)
205 {
206 printf("Failed to create file %s\n", outfile);
207 return 1;
208 }
209
210 memset(g_vlnk_buf, 0, sizeof(g_vlnk_buf));
211 ventoy_create_vlnk(sig, partoff, infile, (ventoy_vlnk *)g_vlnk_buf);
212 fwrite(g_vlnk_buf, 1, VLNK_FILE_LEN, fp);
213 fclose(fp);
214
215 return 0;
216 }
217
218 static int get_mount_point(char *partname, char *mntpoint)
219 {
220 int i;
221 int len;
222 int rc = 1;
223 FILE *fp = NULL;
224 char line[PATH_MAX];
225
226 fp = fopen("/proc/mounts", "r");
227 if (!fp)
228 {
229 return 1;
230 }
231
232 len = (int)strlen(partname);
233 while (fgets(line, sizeof(line), fp))
234 {
235 if (strncmp(line, partname, len) == 0)
236 {
237 for (i = len; i < PATH_MAX && line[i]; i++)
238 {
239 if (line[i] == ' ')
240 {
241 line[i] = 0;
242 rc = 0;
243 strncpy(mntpoint, line + len, PATH_MAX - 1);
244 break;
245 }
246 }
247 break;
248 }
249 }
250
251 fclose(fp);
252 return rc;
253 }
254
255 static int parse_vlnk(char *infile)
256 {
257 int i;
258 int fd;
259 int cnt;
260 int pflag = 0;
261 char diskname[128] = {0};
262 char partname[128] = {0};
263 char partpath[256] = {0};
264 char mntpoint[PATH_MAX];
265 ventoy_vlnk vlnk;
266
267 debug("parse vlnk\n");
268
269 if (infile[0] == 0)
270 {
271 debug("input file null\n");
272 return 1;
273 }
274
275 fd = open(infile, O_RDONLY);
276 if (fd < 0)
277 {
278 printf("Failed to open file %s error %d\n", infile, errno);
279 return 1;
280 }
281
282 memset(&vlnk, 0, sizeof(vlnk));
283 read(fd, &vlnk, sizeof(vlnk));
284 close(fd);
285
286 debug("disk_signature:%08X\n", vlnk.disk_signature);
287 debug("file path:<%s>\n", vlnk.filepath);
288 debug("part offset: %llu\n", (unsigned long long)vlnk.part_offset);
289
290 cnt = find_disk_by_sig((uint8_t *)&(vlnk.disk_signature), diskname);
291 if (cnt != 1)
292 {
293 printf("Disk in vlnk not found!\n");
294 return 1;
295 }
296
297 debug("Disk is <%s>\n", diskname);
298
299 if (strstr(diskname, "nvme") || strstr(diskname, "mmc") || strstr(diskname, "nbd"))
300 {
301 pflag = 1;
302 }
303
304 for (i = 1; i <= 128; i++)
305 {
306 if (pflag)
307 {
308 snprintf(partname, sizeof(partname) - 1, "%sp%d", diskname, i);
309 }
310 else
311 {
312 snprintf(partname, sizeof(partname) - 1, "%s%d", diskname, i);
313 }
314
315 if (get_part_offset(partname) == vlnk.part_offset)
316 {
317 debug("Find correct partition </dev/%s>\n", partname);
318 break;
319 }
320 }
321
322 if (i > 128)
323 {
324 printf("Partition in vlnk not found!");
325 return 1;
326 }
327
328 snprintf(partpath, sizeof(partpath), "/dev/%s ", partname);
329 if (get_mount_point(partpath, mntpoint))
330 {
331 printf("Mountpoint of %s is not found!\n", partpath);
332 return 1;
333 }
334 debug("moutpoint of %s is <%s>\n", partpath, mntpoint);
335
336 strcat(mntpoint, vlnk.filepath);
337 printf("Vlnk Point: %s\n", mntpoint);
338 if (access(mntpoint, F_OK) >= 0)
339 {
340 printf("File Exist: YES\n");
341 }
342 else
343 {
344 printf("File Exist: NO\n");
345 }
346
347 return 0;
348 }
349
350 static int check_vlnk(char *infile)
351 {
352 int fd;
353 int64_t size;
354 ventoy_vlnk vlnk;
355
356 debug("check vlnk\n");
357
358 if (infile[0] == 0)
359 {
360 debug("input file null\n");
361 return 1;
362 }
363
364 size = get_file_size(infile);
365 if (size != VLNK_FILE_LEN)
366 {
367 debug("file size %lld is not a vlnk file size\n", (long long)size);
368 return 1;
369 }
370
371 fd = open(infile, O_RDONLY);
372 if (fd < 0)
373 {
374 debug("Failed to open file %s error %d\n", infile, errno);
375 return 1;
376 }
377
378 memset(&vlnk, 0, sizeof(vlnk));
379 read(fd, &vlnk, sizeof(vlnk));
380 close(fd);
381
382 if (CheckVlnkData(&vlnk))
383 {
384 return 0;
385 }
386
387 return 1;
388 }
389
390 int main(int argc, char **argv)
391 {
392 int ch = 0;
393 int cmd = 0;
394 uint64_t partoff = 0;
395 char infile[PATH_MAX] = {0};
396 char outfile[PATH_MAX] = {0};
397 char diskname[256] = {0};
398
399 while ((ch = getopt(argc, argv, "c:t:l:d:p:o:v::")) != -1)
400 {
401 if (ch == 'c')
402 {
403 cmd = 1;
404 strncpy(infile, optarg, sizeof(infile) - 1);
405 }
406 else if (ch == 'o')
407 {
408 strncpy(outfile, optarg, sizeof(outfile) - 1);
409 }
410 else if (ch == 'l')
411 {
412 cmd = 2;
413 strncpy(infile, optarg, sizeof(infile) - 1);
414 }
415 else if (ch == 't')
416 {
417 cmd = 3;
418 strncpy(infile, optarg, sizeof(infile) - 1);
419 }
420 else if (ch == 'd')
421 {
422 strncpy(diskname, optarg, sizeof(diskname) - 1);
423 }
424 else if (ch == 'p')
425 {
426 partoff = (uint64_t)strtoull(optarg, NULL, 10);
427 partoff *= 512;
428 }
429 else if (ch == 'v')
430 {
431 verbose = 1;
432 }
433 else
434 {
435 return 1;
436 }
437 }
438
439 if (cmd == 1)
440 {
441 return create_vlnk(infile, diskname, partoff, outfile);
442 }
443 else if (cmd == 2)
444 {
445 return parse_vlnk(infile);
446 }
447 else if (cmd == 3)
448 {
449 return check_vlnk(infile);
450 }
451 else
452 {
453 printf("Invalid command %d\n", cmd);
454 return 1;
455 }
456 }
457