Line 0
Link Here
|
|
|
1 |
--- src/calibre/devices/linux_mount_helper.c.orig 2011-11-11 23:22:34.000000000 -0500 |
2 |
+++ src/calibre/devices/linux_mount_helper.c 2011-11-16 13:06:45.000000000 -0500 |
3 |
@@ -1,7 +1,226 @@ |
4 |
#include <stdlib.h> |
5 |
+#include <stdio.h> |
6 |
+#include <unistd.h> |
7 |
+#include <string.h> |
8 |
+#include <errno.h> |
9 |
+#include <sys/types.h> |
10 |
+#include <sys/stat.h> |
11 |
+#include <sys/wait.h> |
12 |
+#include <fcntl.h> |
13 |
+ |
14 |
+#define MARKER ".created_by_calibre_mount_helper" |
15 |
+#define False 0 |
16 |
+#define True 1 |
17 |
+ |
18 |
+int exists(const char *path) { |
19 |
+ struct stat file_info; |
20 |
+ if (stat(path, &file_info) == 0) return True; |
21 |
+ return False; |
22 |
+} |
23 |
+ |
24 |
+int get_root() { |
25 |
+ int res; |
26 |
+ res = setreuid(0, 0); |
27 |
+ if (res != 0) return False; |
28 |
+ if (setregid(0, 0) != 0) return False; |
29 |
+ return True; |
30 |
+} |
31 |
+ |
32 |
+void ensure_root() { |
33 |
+ if (!get_root()) { |
34 |
+ fprintf(stderr, "Failed to get root.\n"); |
35 |
+ exit(EXIT_FAILURE); |
36 |
+ } |
37 |
+} |
38 |
+ |
39 |
+int do_mount(const char *dev, const char *mp) { |
40 |
+ char options[1000], marker[2000]; |
41 |
+#ifdef __NetBSD__ |
42 |
+ char uids[100], gids[100]; |
43 |
+#endif |
44 |
+ int errsv; |
45 |
+ |
46 |
+ if (!exists(dev)) { |
47 |
+ fprintf(stderr, "Specified device node does not exist\n"); |
48 |
+ return EXIT_FAILURE; |
49 |
+ } |
50 |
+ if (!exists(mp)) { |
51 |
+ if (mkdir(mp, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) { |
52 |
+ errsv = errno; |
53 |
+ fprintf(stderr, "Failed to create mount point with error: %s\n", strerror(errsv)); |
54 |
+ } |
55 |
+ } |
56 |
+ snprintf(marker, 2000, "%s/%s", mp, MARKER); |
57 |
+ if (!exists(marker)) { |
58 |
+ int fd = creat(marker, S_IRUSR|S_IWUSR); |
59 |
+ if (fd == -1) { |
60 |
+ int errsv = errno; |
61 |
+ fprintf(stderr, "Failed to create marker with error: %s\n", strerror(errsv)); |
62 |
+ return EXIT_FAILURE; |
63 |
+ } |
64 |
+ close(fd); |
65 |
+ } |
66 |
+#ifdef __NetBSD__ |
67 |
+ snprintf(options, 1000, "rw,noexec,nosuid,sync,nodev"); |
68 |
+ snprintf(uids, 100, "%d", getuid()); |
69 |
+ snprintf(gids, 100, "%d", getgid()); |
70 |
+#else |
71 |
+#ifdef __FreeBSD__ |
72 |
+ snprintf(options, 1000, "rw,noexec,nosuid,sync,-u=%d,-g=%d",getuid(),getgid()); |
73 |
+#else |
74 |
+ snprintf(options, 1000, "rw,noexec,nosuid,sync,nodev,quiet,shortname=mixed,uid=%d,gid=%d,umask=077,fmask=0177,dmask=0077,utf8,iocharset=iso8859-1", getuid(), getgid()); |
75 |
+#endif |
76 |
+#endif |
77 |
+ |
78 |
+ ensure_root(); |
79 |
+ |
80 |
+#ifdef __NetBSD__ |
81 |
+ execlp("mount_msdos", "mount_msdos", "-u", uids, "-g", gids, "-o", options, dev, mp, NULL); |
82 |
+#else |
83 |
+#ifdef __FreeBSD__ |
84 |
+ execl("/sbin/mount", "mount", "-t", "msdosfs", "-o", options, dev, mp, NULL); |
85 |
+#else |
86 |
+ execlp("mount", "mount", "-t", "auto", "-o", options, dev, mp, NULL); |
87 |
+#endif |
88 |
+#endif |
89 |
+ errsv = errno; |
90 |
+ fprintf(stderr, "Failed to mount with error: %s\n", strerror(errsv)); |
91 |
+ return EXIT_FAILURE; |
92 |
+} |
93 |
+ |
94 |
+int call_eject(const char *dev, const char *mp) { |
95 |
+ int ret, pid, errsv, i, status = EXIT_FAILURE; |
96 |
+ |
97 |
+ pid = fork(); |
98 |
+ if (pid == -1) { |
99 |
+ fprintf(stderr, "Failed to fork\n"); |
100 |
+ exit(EXIT_FAILURE); |
101 |
+ } |
102 |
+ |
103 |
+ if (pid == 0) { /* Child process */ |
104 |
+ ensure_root(); |
105 |
+#ifdef __NetBSD__ |
106 |
+ execlp("eject", "eject", dev, NULL); |
107 |
+#else |
108 |
+#ifdef __FreeBSD__ |
109 |
+ execl("/sbin/umount", "umount", dev, NULL); |
110 |
+#else |
111 |
+ execlp("eject", "eject", "-s", dev, NULL); |
112 |
+#endif |
113 |
+#endif |
114 |
+ /* execlp failed */ |
115 |
+ errsv = errno; |
116 |
+ fprintf(stderr, "Failed to eject with error: %s\n", strerror(errsv)); |
117 |
+ exit(EXIT_FAILURE); |
118 |
+ } else { /* Parent */ |
119 |
+ for (i = 0; i < 7; i++) { |
120 |
+ sleep(1); |
121 |
+ ret = waitpid(pid, &status, WNOHANG); |
122 |
+ if (ret == -1) return False; |
123 |
+ if (ret > 0) break; |
124 |
+ } |
125 |
+ return WIFEXITED(status) && WEXITSTATUS(status) == 0; |
126 |
+ } |
127 |
+ return False; |
128 |
+} |
129 |
+ |
130 |
+int call_umount(const char *dev, const char *mp) { |
131 |
+ int ret, pid, errsv, i, status = EXIT_FAILURE; |
132 |
+ |
133 |
+ pid = fork(); |
134 |
+ if (pid == -1) { |
135 |
+ fprintf(stderr, "Failed to fork\n"); |
136 |
+ exit(EXIT_FAILURE); |
137 |
+ } |
138 |
+ |
139 |
+ if (pid == 0) { /* Child process */ |
140 |
+ ensure_root(); |
141 |
+#ifdef __FreeBSD__ |
142 |
+ execl("/sbin/umount", "umount", mp, NULL); |
143 |
+#else |
144 |
+ execlp("umount", "umount", "-l", mp, NULL); |
145 |
+#endif |
146 |
+ /* execlp failed */ |
147 |
+ errsv = errno; |
148 |
+ fprintf(stderr, "Failed to umount with error: %s\n", strerror(errsv)); |
149 |
+ exit(EXIT_FAILURE); |
150 |
+ } else { /* Parent */ |
151 |
+ for (i = 0; i < 7; i++) { |
152 |
+ sleep(1); |
153 |
+ ret = waitpid(pid, &status, WNOHANG); |
154 |
+ if (ret == -1) return False; |
155 |
+ if (ret > 0) break; |
156 |
+ } |
157 |
+ return WIFEXITED(status) && WEXITSTATUS(status) == 0; |
158 |
+ } |
159 |
+ return False; |
160 |
+} |
161 |
+ |
162 |
+int cleanup_mount_point(const char *mp) { |
163 |
+ char marker[2000]; |
164 |
+ int urt, rmd, errsv; |
165 |
+ |
166 |
+ snprintf(marker, 2000, "%s/%s", mp, MARKER); |
167 |
+ if (exists(marker)) { |
168 |
+ urt = unlink(marker); |
169 |
+ if (urt == -1) { |
170 |
+ errsv = errno; |
171 |
+ fprintf(stderr, "Failed to unlink marker: %s\n", strerror(errsv)); |
172 |
+ return EXIT_FAILURE; |
173 |
+ } |
174 |
+ } |
175 |
+ rmd = rmdir(mp); |
176 |
+ if (rmd == -1) { |
177 |
+ errsv = errno; |
178 |
+ fprintf(stderr, "Failed to remove mount point: %s\n", strerror(errsv)); |
179 |
+ return EXIT_FAILURE; |
180 |
+ } |
181 |
+ return EXIT_SUCCESS; |
182 |
+} |
183 |
+ |
184 |
+int do_eject(const char *dev, const char *mp) { |
185 |
+ int unmounted = False; |
186 |
+ |
187 |
+ ensure_root(); |
188 |
+ |
189 |
+ unmounted = call_eject(dev, mp); |
190 |
+ if (!unmounted) call_umount(dev, mp); |
191 |
+ if (unmounted) return cleanup_mount_point(mp); |
192 |
+ return EXIT_FAILURE; |
193 |
+} |
194 |
+ |
195 |
+int cleanup(const char *dev, const char *mp) { |
196 |
+ ensure_root(); |
197 |
+ call_umount(dev, mp); |
198 |
+ return cleanup_mount_point(mp); |
199 |
+} |
200 |
|
201 |
int main(int argc, char** argv) |
202 |
{ |
203 |
- return EXIT_FAILURE; |
204 |
+ char *action, *dev, *mp; |
205 |
+ int status = EXIT_FAILURE; |
206 |
+ |
207 |
+ /*printf("Real UID\t= %d\n", getuid()); |
208 |
+ printf("Effective UID\t= %d\n", geteuid()); |
209 |
+ printf("Real GID\t= %d\n", getgid()); |
210 |
+ printf("Effective GID\t= %d\n", getegid());*/ |
211 |
+ |
212 |
+ if (argc != 4) { |
213 |
+ fprintf(stderr, "Needs 3 arguments: action, device node and mount point\n"); |
214 |
+ exit(EXIT_FAILURE); |
215 |
+ } |
216 |
+ action = argv[1]; dev = argv[2]; mp = argv[3]; |
217 |
+ |
218 |
+ if (strncmp(action, "mount", 5) == 0) { |
219 |
+ status = do_mount(dev, mp); |
220 |
+ } else if (strncmp(action, "eject", 5) == 0) { |
221 |
+ status = do_eject(dev, mp); |
222 |
+ } else if (strncmp(action, "cleanup", 7) == 0) { |
223 |
+ status = cleanup(dev, mp); |
224 |
+ } else { |
225 |
+ fprintf(stderr, "Unrecognized action: must be mount, eject or cleanup\n"); |
226 |
+ } |
227 |
+ |
228 |
+ return status; |
229 |
} |
230 |
|