Skip to content

Commit 17e73bc

Browse files
authored
Update f3fix.c
1 parent bc72e84 commit 17e73bc

File tree

1 file changed

+170
-165
lines changed

1 file changed

+170
-165
lines changed

f3fix.c

Lines changed: 170 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,128 @@
11
#include <stdbool.h>
22
#include <assert.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <string.h>
6+
7+
#ifdef _WIN32
8+
#include <windows.h>
9+
#include <winioctl.h>
10+
#include <getopt.h>
11+
#else
312
#include <argp.h>
413
#include <parted/parted.h>
14+
#endif
515

616
#include "version.h"
717
#include "libutils.h"
818

9-
/* Argp's global variables. */
10-
const char *argp_program_version = "F3 Fix " F3_STR_VERSION;
19+
// Общие константы
20+
#define DEFAULT_FIRST_SEC 2048
21+
#define WIN_SECTOR_SIZE 512
1122

12-
/* Arguments. */
13-
static char adoc[] = "<DISK_DEV>";
14-
15-
static char doc[] = "F3 Fix -- edit the partition table of "
16-
"a fake flash drive to have a single partition that fully covers "
17-
"the real capacity of the drive";
18-
19-
static struct argp_option options[] = {
20-
{"disk-type", 'd', "TYPE", 0,
21-
"Disk type of the partition table", 2},
22-
{"fs-type", 'f', "TYPE", 0,
23-
"Type of the file system of the partition", 0},
24-
{"boot", 'b', NULL, 0,
25-
"Mark the partition for boot", 0},
26-
{"no-boot", 'n', NULL, 0,
27-
"Do not mark the partition for boot", 0},
28-
{"first-sec", 'a', "SEC-NUM", 0,
29-
"Sector where the partition starts", 0},
30-
{"last-sec", 'l', "SEC-NUM", 0,
31-
"Sector where the partition ends", 0},
32-
{"list-disk-types", 'k', NULL, 0,
33-
"List all supported disk types", 3},
34-
{"list-fs-types", 's', NULL, 0,
35-
"List all supported types of file systems", 0},
36-
{ 0 }
37-
};
23+
// Глобальные переменные
24+
const char *argp_program_version = "F3 Fix " F3_STR_VERSION;
3825

26+
// Структура аргументов
3927
struct args {
40-
bool list_disk_types;
41-
bool list_fs_types;
42-
43-
bool boot;
44-
45-
/* 29 free bytes. */
46-
47-
const char *dev_filename;
48-
PedDiskType *disk_type;
49-
PedFileSystemType *fs_type;
50-
PedSector first_sec;
51-
PedSector last_sec;
28+
bool list_disk_types;
29+
bool list_fs_types;
30+
bool boot;
31+
const char *dev_filename;
32+
const char *disk_type;
33+
const char *fs_type;
34+
long long first_sec;
35+
long long last_sec;
5236
};
5337

54-
static long long arg_to_long_long(const struct argp_state *state,
55-
const char *arg)
56-
{
57-
char *end;
58-
long long ll = strtoll(arg, &end, 0);
59-
if (!arg)
60-
argp_error(state, "An integer must be provided");
61-
if (!*arg || *end)
62-
argp_error(state, "`%s' is not an integer", arg);
63-
return ll;
38+
#ifdef _WIN32
39+
// Windows-специфичные функции
40+
static int fix_disk_win(const char *dev_path, long long start, long long end) {
41+
HANDLE hDevice = CreateFileA(dev_path, GENERIC_READ | GENERIC_WRITE,
42+
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
43+
44+
if (hDevice == INVALID_HANDLE_VALUE) {
45+
fprintf(stderr, "Error opening device: %lu\n", GetLastError());
46+
return 0;
47+
}
48+
49+
// Создание новой MBR
50+
CREATE_DISK createDisk = {0};
51+
createDisk.PartitionStyle = PARTITION_STYLE_MBR;
52+
DWORD bytesReturned;
53+
54+
if (!DeviceIoControl(hDevice, IOCTL_DISK_CREATE_DISK,
55+
&createDisk, sizeof(createDisk), NULL, 0, &bytesReturned, NULL)) {
56+
fprintf(stderr, "Create disk failed: %lu\n", GetLastError());
57+
CloseHandle(hDevice);
58+
return 0;
59+
}
60+
61+
// Настройка разделов
62+
DRIVE_LAYOUT_INFORMATION_EX layout = {0};
63+
layout.PartitionStyle = PARTITION_STYLE_MBR;
64+
layout.Mbr.Signature = 0x12345678;
65+
66+
// Расчет параметров раздела
67+
PARTITION_INFORMATION_EX part = {0};
68+
part.PartitionStyle = PARTITION_STYLE_MBR;
69+
part.Mbr.PartitionType = 0x0C; // FAT32
70+
part.StartingOffset.QuadPart = start * WIN_SECTOR_SIZE;
71+
part.PartitionLength.QuadPart = (end - start + 1) * WIN_SECTOR_SIZE;
72+
part.Mbr.BootIndicator = args.boot;
73+
74+
memcpy(&layout.Mbr.PartitionEntry[0], &part, sizeof(PARTITION_INFORMATION_EX));
75+
layout.PartitionCount = 1;
76+
77+
if (!DeviceIoControl(hDevice, IOCTL_DISK_SET_DRIVE_LAYOUT_EX,
78+
&layout, sizeof(layout), NULL, 0, &bytesReturned, NULL)) {
79+
fprintf(stderr, "Set layout failed: %lu\n", GetLastError());
80+
CloseHandle(hDevice);
81+
return 0;
82+
}
83+
84+
CloseHandle(hDevice);
85+
return 1;
6486
}
6587

66-
static error_t parse_opt(int key, char *arg, struct argp_state *state)
67-
{
88+
// Парсинг аргументов для Windows
89+
static void parse_args(int argc, char **argv, struct args *args) {
90+
int opt;
91+
static struct option long_options[] = {
92+
{"disk-type", required_argument, 0, 'd'},
93+
{"fs-type", required_argument, 0, 'f'},
94+
{"boot", no_argument, 0, 'b'},
95+
{"no-boot", no_argument, 0, 'n'},
96+
{"first-sec", required_argument, 0, 'a'},
97+
{"last-sec", required_argument, 0, 'l'},
98+
{"list-disk-types", no_argument, 0, 'k'},
99+
{"list-fs-types", no_argument, 0, 's'},
100+
{0, 0, 0, 0}
101+
};
102+
103+
while ((opt = getopt_long(argc, argv, "d:f:bn:a:l:ks", long_options, NULL)) != -1) {
104+
switch (opt) {
105+
case 'd': args->disk_type = optarg; break;
106+
case 'f': args->fs_type = optarg; break;
107+
case 'b': args->boot = true; break;
108+
case 'n': args->boot = false; break;
109+
case 'a': args->first_sec = atoll(optarg); break;
110+
case 'l': args->last_sec = atoll(optarg); break;
111+
case 'k': args->list_disk_types = true; break;
112+
case 's': args->list_fs_types = true; break;
113+
default: exit(EXIT_FAILURE);
114+
}
115+
}
116+
117+
if (optind < argc) {
118+
args->dev_filename = argv[optind];
119+
}
120+
}
121+
122+
#else // Linux реализация
123+
124+
// Оригинальные Linux-функции с argp
125+
static error_t parse_opt(int key, char *arg, struct argp_state *state) {
68126
struct args *args = state->input;
69127
long long ll;
70128

@@ -152,116 +210,62 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
152210
}
153211

154212
static struct argp argp = {options, parse_opt, adoc, doc, NULL, NULL, NULL};
155-
156-
static void list_disk_types(void)
157-
{
158-
PedDiskType *type;
159-
int i = 0;
160-
printf("Disk types:\n");
161-
for (type = ped_disk_type_get_next(NULL); type;
162-
type = ped_disk_type_get_next(type)) {
163-
printf("%s\t", type->name);
164-
i++;
165-
if (i == 5) {
166-
printf("\n");
167-
i = 0;
168-
}
169-
}
170-
if (i > 0)
171-
printf("\n");
172-
printf("\n");
173-
}
174-
175-
static void list_fs_types(void)
176-
{
177-
PedFileSystemType *fs_type;
178-
int i = 0;
179-
printf("File system types:\n");
180-
for (fs_type = ped_file_system_type_get_next(NULL); fs_type;
181-
fs_type = ped_file_system_type_get_next(fs_type)) {
182-
printf("%s\t", fs_type->name);
183-
i++;
184-
if (i == 5) {
185-
printf("\n");
186-
i = 0;
187-
}
188-
}
189-
if (i > 0)
190-
printf("\n");
191-
printf("\n");
192-
}
193-
194-
static PedSector map_sector_to_logical_sector(PedSector sector,
195-
int logical_sector_size)
196-
{
197-
assert(logical_sector_size >= 512);
198-
assert(logical_sector_size % 512 == 0);
199-
return sector / (logical_sector_size / 512);
200-
}
201-
202-
/* 0 on failure, 1 otherwise. */
203-
static int fix_disk(PedDevice *dev, PedDiskType *type,
204-
PedFileSystemType *fs_type, int boot, PedSector start, PedSector end)
205-
{
206-
PedDisk *disk;
207-
PedPartition *part;
208-
PedGeometry *geom;
209-
PedConstraint *constraint;
210-
int ret = 0;
211-
212-
disk = ped_disk_new_fresh(dev, type);
213-
if (!disk)
214-
goto out;
215-
216-
start = map_sector_to_logical_sector(start, dev->sector_size);
217-
end = map_sector_to_logical_sector(end, dev->sector_size);
218-
part = ped_partition_new(disk, PED_PARTITION_NORMAL,
219-
fs_type, start, end);
220-
if (!part)
221-
goto disk;
222-
if (boot && !ped_partition_set_flag(part, PED_PARTITION_BOOT, 1))
223-
goto part;
224-
225-
geom = ped_geometry_new(dev, start, end - start + 1);
226-
if (!geom)
227-
goto part;
228-
constraint = ped_constraint_exact(geom);
229-
ped_geometry_destroy(geom);
230-
if (!constraint)
231-
goto part;
232-
233-
ret = ped_disk_add_partition(disk, part, constraint);
234-
ped_constraint_destroy(constraint);
235-
if (!ret)
236-
goto part;
237-
/* ped_disk_print(disk); */
238-
239-
ret = ped_disk_commit(disk);
240-
goto disk;
241-
242-
part:
243-
ped_partition_destroy(part);
244-
disk:
245-
ped_disk_destroy(disk);
246-
out:
247-
return ret;
248-
}
249-
250-
int main (int argc, char *argv[])
251-
{
252-
struct args args = {
253-
/* Defaults. */
254-
.list_disk_types = false,
255-
.list_fs_types = false,
256-
257-
.boot = true,
258-
259-
.disk_type = ped_disk_type_get("msdos"),
260-
.fs_type = ped_file_system_type_get("fat32"),
261-
.first_sec = 2048, /* Skip first 1MB. */
262-
};
263-
264-
PedDevice *dev;
213+
#endif
214+
215+
int main(int argc, char *argv[]) {
216+
struct args args = {
217+
.list_disk_types = false,
218+
.list_fs_types = false,
219+
.boot = true,
220+
.disk_type = "msdos",
221+
.fs_type = "fat32",
222+
.first_sec = DEFAULT_FIRST_SEC,
223+
.last_sec = -1
224+
};
225+
226+
#ifdef _WIN32
227+
// Windows инициализация
228+
WSADATA wsaData;
229+
WSAStartup(MAKEWORD(2, 2), &wsaData);
230+
parse_args(argc, argv, &args);
231+
#else
232+
// Linux парсинг аргументов
233+
argp_parse(&argp, argc, argv, 0, NULL, &args);
234+
#endif
235+
236+
// Общая логика
237+
if (args.list_disk_types) {
238+
printf("Supported disk types: msdos\n");
239+
return 0;
240+
}
241+
242+
if (args.list_fs_types) {
243+
printf("Supported filesystems: fat32\n");
244+
return 0;
245+
}
246+
247+
if (!args.dev_filename || args.last_sec < 0) {
248+
fprintf(stderr, "Missing required arguments\n");
249+
return 1;
250+
}
251+
252+
#ifdef _WIN32
253+
// Windows: преобразование пути
254+
char win_path[MAX_PATH];
255+
if (sscanf(args.dev_filename, "/dev/sd%c", &drive_letter) == 1) {
256+
int drive_num = tolower(drive_letter) - 'a';
257+
snprintf(win_path, MAX_PATH, "\\\\.\\PhysicalDrive%d", drive_num);
258+
} else {
259+
strncpy(win_path, args.dev_filename, MAX_PATH);
260+
}
261+
262+
if (!fix_disk_win(win_path, args.first_sec, args.last_sec)) {
263+
fprintf(stderr, "Failed to fix disk\n");
264+
return 1;
265+
}
266+
#else
267+
// Linux реализация с libparted
268+
PedDevice *dev = ped_device_get(args.dev_filename);
265269
int ret;
266270

267271
/* Read parameters. */
@@ -290,7 +294,8 @@ int main (int argc, char *argv[])
290294

291295
ret = !fix_disk(dev, args.disk_type, args.fs_type, args.boot,
292296
args.first_sec, args.last_sec);
293-
printf("Drive `%s' was successfully fixed\n", args.dev_filename);
294-
ped_device_destroy(dev);
295-
return ret;
297+
#endif
298+
299+
printf("Drive %s was successfully fixed\n", args.dev_filename);
300+
return 0;
296301
}

0 commit comments

Comments
 (0)