-
Notifications
You must be signed in to change notification settings - Fork 8
/
util.c
137 lines (122 loc) · 3.7 KB
/
util.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
* util.c
* FuseHFS
*
* This is fusefs_hfs.util, which is called during the probing/mount process.
* See full description in main.c
*
* Created by Zydeco on 2010-03-11.
* Copyright 2010 namedfork.net. All rights reserved.
* Edited by Joel Cretan 2022-08-24
*
* Licensed under GPLv2: https://www.gnu.org/licenses/gpl-2.0.html
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <libhfs/libhfs.h>
#include <sys/loadable_fs.h>
#include <sys/stat.h>
#include <iconv.h>
#include <sys/errno.h>
#include "common.h"
#include "log.h"
#define FILENAME "[util.c]\t"
/* no longer supported in xnu 3247 / osx 10.11 */
/* from xnu/bsd/sys/loadable_fs.h.auto.html */
#define FSUC_INITIALIZE 'i' /* initialize FS */
int usage() {
fprintf(stderr, FILENAME "usage: fusefs_hfs.util [-p|-m|-i] <options>\n");
return EXIT_FAILURE;
}
int have_macfuse() {
struct stat us;
return (stat("/usr/local/lib/libfuse.dylib", &us) == 0);
}
#define HFSPLUS_SIGWORD 0x482b /* 'H+' */
#define HFSX_SIGWORD 0x482b /* 'HX' */
int probe (const char *device, int removable, int readonly) {
char *path;
int ret = FSUR_RECOGNIZED;
asprintf(&path, "/dev/%s", device);
hfsvol * vol = hfs_mount(path, 0, HFS_MODE_RDONLY);
free(path);
if (vol == NULL) return FSUR_UNRECOGNIZED;
/* Refuse to mount HFS+ wrapper volume */
int embed = vol->mdb.drEmbedSigWord;
if (embed == HFSPLUS_SIGWORD || embed == HFSX_SIGWORD) {
ret = FSUR_UNRECOGNIZED;
} else {
hfsvolent ent;
if (hfs_vstat(vol, &ent) == 0)
// WARNING!! apparently stdout is a pipe!!!
printf("%s\n", ent.name); // TODO: convert to UTF8
}
hfs_umount(vol);
return ret;
}
int initialize (const char *device, const char *label) {
// convert label to MacRoman
char volname[HFS_MAX_VLEN+1];
size_t len = strlen(label);
size_t outleft = HFS_MAX_VLEN;
char *outp = volname;
iconv_t conv = iconv_open("Macintosh", "UTF-8");
iconv(conv, (char **restrict)&label, &len, &outp, &outleft);
volname[HFS_MAX_VLEN-outleft] = '\0';
volname[HFS_MAX_VLEN] = '\0';
iconv_close(conv);
// format
if (hfs_format(device, 0, 0, volname, 0, NULL)) {
return FSUR_IO_FAIL;
}
return EXIT_SUCCESS;
}
/*int mount (const char *device, const char *mountpoint) {
char *cmd;
asprintf(&cmd, "/Library/Filesystems/fusefs_hfs.fs/Contents/Resources/fuse_wait \"%s\" %d /Library/Filesystems/fusefs_hfs.fs/Contents/Resources/fusefs_hfs \"%s\" \"%s\"", mountpoint, 5, device, mountpoint);
fprintf(stderr, FILENAME "mount cmd: %s", cmd);
fflush(stderr);
int ret = system(cmd); // TODO: escape input to avoid command injection
free(cmd);
return ret?FSUR_IO_FAIL:FSUR_IO_SUCCESS;
}*/
int main (int argc, char * argv[], char * envp[], char * apple[]) {
log_to_file();
log_invoking_command(FILENAME, argc, argv);
// check arguments
if (argc < 3) return usage();
int ret = 0;
switch (argv[1][1]) {
case FSUC_PROBE:
fprintf(stderr, FILENAME "probing\n");
fflush(stderr);
ret = probe(argv[2], !strcmp(argv[3],DEVICE_REMOVABLE), !strcmp(argv[4],DEVICE_READONLY));
break;
case FSUC_INITIALIZE: {
fprintf(stderr, FILENAME "initializing\n");
fflush(stderr);
int larg = 2;
const char *label, *device;
if (strcmp(argv[2], "-v") == 0) larg = 3;
label = argv[larg];
device = argv[larg+1];
ret = initialize(device, label);
break; }
/*case FSUC_MOUNT:
fprintf(stderr, FILENAME "mounting\n");
fflush(stderr);
ret = mount(argv[argc-2], argv[argc-1]);
break;*/
case 'k': // get UUID
case 's': // set UUID
ret = FSUR_INVAL;
break;
default:
ret = FSUR_INVAL;
break;
}
fprintf(stderr, FILENAME "returning %d\n", ret);
return ret;
}