]> cygwin.com Git - cygwin-apps/setup.git/blob - mount.cc
2002-02-19 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / mount.cc
1 /*
2 * Copyright (c) 2000, Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by DJ Delorie <dj@cygnus.com>
13 *
14 */
15
16 /* The purpose of this file is to hide all the details about accessing
17 Cygwin's mount table. If the format or location of the mount table
18 changes, this is the file to change to match it. */
19
20 #if 0
21 static const char *cvsid = "\n%%% $Id$\n";
22 #endif
23
24 #include "win32.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include "../cygwin/include/cygwin/version.h"
29 #include "../cygwin/include/sys/mount.h"
30
31 #include "mount.h"
32 #include "msg.h"
33 #include "resource.h"
34 #include "dialog.h"
35 #include "state.h"
36 #include "concat.h"
37
38 #include "String++.h"
39
40 static struct mnt
41 {
42 String native;
43 String posix;
44 int istext;
45 }
46 mount_table[255];
47
48 struct mnt *root_here = NULL;
49
50 static String
51 find2 (HKEY rkey, int *istext, String const &what)
52 {
53 HKEY key;
54
55 if (RegOpenKeyEx (rkey, what.cstr_oneuse (), 0, KEY_READ, &key) !=
56 ERROR_SUCCESS)
57 return 0;
58
59 DWORD retvallen = 0;
60 DWORD type;
61
62 String Sretval;
63 if (RegQueryValueEx (key, "native", 0, &type, 0, &retvallen)
64 == ERROR_SUCCESS)
65 {
66 char retval[retvallen];
67 if (RegQueryValueEx
68 (key, "native", 0, &type, (BYTE *) retval,
69 &retvallen) == ERROR_SUCCESS)
70 Sretval = String (retval);
71 }
72
73 DWORD flags = 0;
74 retvallen = sizeof (flags);
75 RegQueryValueEx (key, "flags", 0, &type, (BYTE *) & flags, &retvallen);
76
77 RegCloseKey (key);
78
79 if (Sretval.size ())
80 *istext = (flags & MOUNT_BINARY) ? 0 : 1;
81
82 return Sretval;
83 }
84
85 void
86 create_mount (String const posix, String const win32, int istext,
87 int issystem)
88 {
89 char buf[1000];
90 HKEY key;
91 DWORD disposition;
92 DWORD flags;
93
94 remove_mount (posix);
95
96 sprintf (buf, "Software\\%s\\%s\\%s\\%s",
97 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
98 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
99 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, posix.cstr_oneuse ());
100
101 HKEY kr = issystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
102 if (RegCreateKeyEx (kr, buf, 0, "Cygwin", 0, KEY_ALL_ACCESS,
103 0, &key, &disposition) != ERROR_SUCCESS)
104 fatal ("mount");
105
106 RegSetValueEx (key, "native", 0, REG_SZ, (BYTE *) win32.cstr_oneuse (),
107 win32.size () + 1);
108 flags = 0;
109 if (!istext)
110 flags |= MOUNT_BINARY;
111 if (issystem)
112 flags |= MOUNT_SYSTEM;
113 RegSetValueEx (key, "flags", 0, REG_DWORD, (BYTE *) & flags,
114 sizeof (flags));
115
116 RegCloseKey (key);
117 read_mounts ();
118 }
119
120 static void
121 remove1 (HKEY rkey, String const posix)
122 {
123 char buf[1000];
124
125 sprintf (buf, "Software\\%s\\%s\\%s\\%s",
126 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
127 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
128 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, posix.cstr_oneuse ());
129
130 RegDeleteKey (rkey, buf);
131 }
132
133 void
134 remove_mount (String const posix)
135 {
136 remove1 (HKEY_LOCAL_MACHINE, posix);
137 remove1 (HKEY_CURRENT_USER, posix);
138 }
139
140 static void
141 set_cygdrive_flags (HKEY key, int istext, DWORD cygdrive_flags)
142 {
143 int cur_istext = (cygdrive_flags & MOUNT_BINARY) ? 0 : 1;
144 if (cur_istext != istext)
145 {
146 if (!istext)
147 cygdrive_flags |= MOUNT_BINARY;
148 else
149 cygdrive_flags &= ~MOUNT_BINARY;
150 RegSetValueEx (key, CYGWIN_INFO_CYGDRIVE_FLAGS, 0, REG_DWORD,
151 (BYTE *) & cygdrive_flags, sizeof (cygdrive_flags));
152 }
153 }
154
155 static LONG
156 get_cygdrive_flags (HKEY key, DWORD * cygdrive_flags)
157 {
158 DWORD retvallen = sizeof (*cygdrive_flags);
159 LONG status = RegQueryValueEx (key, CYGWIN_INFO_CYGDRIVE_FLAGS, 0, 0,
160 (BYTE *) cygdrive_flags, &retvallen);
161 return status;
162 }
163
164 static DWORD
165 default_cygdrive (HKEY key)
166 {
167 RegSetValueEx (key, CYGWIN_INFO_CYGDRIVE_PREFIX, 0, REG_SZ,
168 (BYTE *) CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX,
169 strlen (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX) + 1);
170 DWORD cygdrive_flags = MOUNT_AUTO;
171 RegSetValueEx (key, CYGWIN_INFO_CYGDRIVE_FLAGS, 0, REG_DWORD,
172 (BYTE *) & cygdrive_flags, sizeof (cygdrive_flags));
173 return cygdrive_flags;
174 }
175
176 void
177 set_cygdrive_flags (int istext, int issystem)
178 {
179 int found_system = 0;
180
181 char buf[1000];
182 sprintf (buf, "Software\\%s\\%s\\%s",
183 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
184 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
185 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME);
186
187 if (issystem)
188 {
189 HKEY key;
190 DWORD disposition;
191 LONG status = RegCreateKeyEx (HKEY_LOCAL_MACHINE, buf, 0, 0, 0,
192 KEY_ALL_ACCESS, 0, &key, &disposition);
193 if (status == ERROR_SUCCESS)
194 {
195 DWORD cygdrive_flags = 0;
196 status = get_cygdrive_flags (key, &cygdrive_flags);
197 if (status == ERROR_SUCCESS)
198 {
199 set_cygdrive_flags (key, istext, cygdrive_flags);
200 found_system = 1;
201 }
202 RegCloseKey (key);
203 }
204 }
205
206 HKEY key;
207 DWORD disposition;
208 LONG status =
209 RegCreateKeyEx (HKEY_CURRENT_USER, buf, 0, 0, 0, KEY_ALL_ACCESS,
210 0, &key, &disposition);
211 if (status != ERROR_SUCCESS)
212 fatal ("set_cygdrive_flags");
213
214 DWORD cygdrive_flags = 0;
215 status = get_cygdrive_flags (key, &cygdrive_flags);
216 if (status == ERROR_FILE_NOT_FOUND && !found_system)
217 {
218 cygdrive_flags = default_cygdrive (key);
219 status = ERROR_SUCCESS;
220 }
221
222 if (status == ERROR_SUCCESS)
223 set_cygdrive_flags (key, istext, cygdrive_flags);
224
225 RegCloseKey (key);
226 }
227
228 static int
229 in_table (struct mnt *m)
230 {
231 for (struct mnt * m1 = mount_table; m1 < m; m1++)
232 if (m1->posix.casecompare (m->posix) == 0)
233 return 1;
234 return 0;
235 }
236
237 /*
238 * is_admin () determines whether or not the current user is a member of the
239 * Administrators group. On Windows 9X, the current user is considered an
240 * Administrator by definition.
241 */
242
243 static int
244 is_admin ()
245 {
246 // Windows 9X users are considered Administrators by definition
247 OSVERSIONINFO verinfo;
248 verinfo.dwOSVersionInfoSize = sizeof (verinfo);
249 GetVersionEx (&verinfo);
250 if (verinfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
251 return 1;
252
253 // Get the process token for the current process
254 HANDLE token;
255 BOOL status = OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token);
256 if (!status)
257 return 0;
258
259 // Get the group token information
260 UCHAR token_info[1024];
261 PTOKEN_GROUPS groups = (PTOKEN_GROUPS) token_info;
262 DWORD token_info_len = sizeof (token_info);
263 status =
264 GetTokenInformation (token, TokenGroups, token_info, token_info_len,
265 &token_info_len);
266 CloseHandle (token);
267 if (!status)
268 return 0;
269
270 // Create the Administrators group SID
271 PSID admin_sid;
272 SID_IDENTIFIER_AUTHORITY authority = { SECURITY_NT_AUTHORITY };
273 status =
274 AllocateAndInitializeSid (&authority, 2, SECURITY_BUILTIN_DOMAIN_RID,
275 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
276 &admin_sid);
277 if (!status)
278 return 0;
279
280 // Check to see if the user is a member of the Administrators group
281 status = 0;
282 for (UINT i = 0; i < groups->GroupCount; i++)
283 {
284 if (EqualSid (groups->Groups[i].Sid, admin_sid))
285 {
286 status = 1;
287 break;
288 }
289 }
290
291 // Destroy the Administrators group SID
292 FreeSid (admin_sid);
293
294 // Return whether or not the user is a member of the Administrators group
295 return status;
296 }
297
298 void
299 read_mounts ()
300 {
301 DWORD posix_path_size;
302 int res;
303 struct mnt *m = mount_table;
304 DWORD disposition;
305 char buf[10000];
306
307 root_here = NULL;
308 for (mnt * m1 = mount_table; m1->posix.size (); m1++)
309 {
310 m1->posix = String (); //empty string;
311 m1->native = String ();
312 }
313
314 /* Loop through subkeys */
315 /* FIXME: we would like to not check MAX_MOUNTS but the heap in the
316 shared area is currently statically allocated so we can't have an
317 arbitrarily large number of mounts. */
318 for (int issystem = 0; issystem <= 1; issystem++)
319 {
320 sprintf (buf, "Software\\%s\\%s\\%s",
321 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
322 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
323 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME);
324
325 HKEY key = issystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
326 if (RegCreateKeyEx (key, buf, 0, "Cygwin", 0, KEY_ALL_ACCESS,
327 0, &key, &disposition) != ERROR_SUCCESS)
328 break;
329 for (int i = 0;; i++, m++)
330 {
331 char aBuffer[MAX_PATH + 1];
332 posix_path_size = MAX_PATH;
333 /* FIXME: if maximum posix_path_size is 256, we're going to
334 run into problems if we ever try to store a mount point that's
335 over 256 but is under MAX_PATH. */
336 res = RegEnumKeyEx (key, i, aBuffer, &posix_path_size, NULL,
337 NULL, NULL, NULL);
338
339 if (res == ERROR_NO_MORE_ITEMS)
340 {
341 m->posix = String ();
342 break;
343 }
344 m->posix = String (aBuffer);
345
346 if (!m->posix.size () || in_table (m))
347 goto no_go;
348 else if (res != ERROR_SUCCESS)
349 break;
350 else
351 {
352 m->native = find2 (key, &m->istext, m->posix);
353 if (!m->native.size ())
354 goto no_go;
355
356 if (m->posix == "/")
357 {
358 root_here = m;
359 if (m->istext)
360 root_text = IDC_ROOT_TEXT;
361 else
362 root_text = IDC_ROOT_BINARY;
363 if (issystem)
364 root_scope = IDC_ROOT_SYSTEM;
365 else
366 root_scope = IDC_ROOT_USER;
367 }
368 }
369 continue;
370 no_go:
371 m->posix = String ();
372 --m;
373 }
374 RegCloseKey (key);
375 }
376
377 if (!root_here)
378 {
379 root_here = m;
380 m->posix = String ("/");
381 char windir[_MAX_PATH];
382 root_text = IDC_ROOT_BINARY;
383 root_scope = (is_admin ())? IDC_ROOT_SYSTEM : IDC_ROOT_USER;
384 GetWindowsDirectory (windir, sizeof (windir));
385 windir[2] = 0;
386 set_root_dir (String (windir) + "\\cygwin");
387 m++;
388 }
389 }
390
391 void
392 set_root_dir (String const val)
393 {
394 root_here->native = val;
395 }
396
397 String const
398 get_root_dir ()
399 {
400 return root_here ? root_here->native : String ();
401 }
402
403 /* Return non-zero if PATH1 is a prefix of PATH2.
404 Both are assumed to be of the same path style and / vs \ usage.
405 Neither may be "".
406
407 Examples:
408 /foo/ is a prefix of /foo <-- may seem odd, but desired
409 /foo is a prefix of /foo/
410 / is a prefix of /foo/bar
411 / is not a prefix of foo/bar
412 foo/ is a prefix foo/bar
413 /foo is not a prefix of /foobar
414 */
415
416 static int
417 path_prefix_p (String const path1, String const path2)
418 {
419 size_t len1 = path1.size ();
420 /* Handle case where PATH1 has trailing '/' and when it doesn't. */
421 if (len1 > 0 && SLASH_P (path1.cstr_oneuse ()[len1 - 1]))
422 --len1;
423
424 if (len1 == 0)
425 return SLASH_P (path2.cstr_oneuse ()[0])
426 && !SLASH_P (path2.cstr_oneuse ()[1]);
427
428 if (path1.casecompare (path2, len1) != 0)
429 return 0;
430
431 return SLASH_P (path2.cstr_oneuse ()[len1]) || path2.size () == len1
432 || path1.cstr_oneuse ()[len1 - 1] == ':';
433 }
434
435 static String
436 cygpath (String const &thePath)
437 {
438 size_t max_len = 0;
439 struct mnt *m, *match = NULL;
440 for (m = mount_table; m->posix.size (); m++)
441 {
442 size_t n = m->posix.size ();
443 if (n <= max_len || !path_prefix_p (m->posix, thePath))
444 continue;
445 max_len = n;
446 match = m;
447 }
448
449 if (!match)
450 return NULL;
451
452 String native;
453 if (max_len == thePath.size ())
454 {
455 native = match->native;
456 }
457 else
458 native = match->native + "/" + String (thePath.cstr_oneuse () + max_len);
459 return native;
460 }
461
462 String
463 cygpath (const char *s, ...)
464 {
465 va_list v;
466
467 va_start (v, s);
468 char *path = vconcat (s, v);
469 if (strncmp (path, "./", 2) == 0)
470 memmove (path, path + 2, strlen (path + 2) + 1);
471 if (strncmp (path, "/./", 3) == 0)
472 memmove (path + 1, path + 3, strlen (path + 3) + 1);
473
474 String thePath (path);
475 delete[]path;
476 return cygpath (thePath);
477 }
This page took 0.057268 seconds and 5 git commands to generate.