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