]> cygwin.com Git - cygwin-apps/setup.git/blame - mount.cc
2002-02-19 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / mount.cc
CommitLineData
23c9e63c
DD
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
b24c88b3 20#if 0
3c054baf 21static const char *cvsid = "\n%%% $Id$\n";
b24c88b3 22#endif
8507f105 23
23c9e63c
DD
24#include "win32.h"
25
26#include <stdio.h>
a351e48c 27#include <stdlib.h>
23c9e63c
DD
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"
a351e48c
CF
35#include "state.h"
36#include "concat.h"
23c9e63c 37
3c054baf
RC
38#include "String++.h"
39
a351e48c 40static struct mnt
b24c88b3 41{
3c054baf
RC
42 String native;
43 String posix;
b24c88b3
RC
44 int istext;
45}
46mount_table[255];
23c9e63c 47
85b43844
CF
48struct mnt *root_here = NULL;
49
3c054baf
RC
50static String
51find2 (HKEY rkey, int *istext, String const &what)
23c9e63c 52{
a351e48c 53 HKEY key;
23c9e63c 54
3c054baf
RC
55 if (RegOpenKeyEx (rkey, what.cstr_oneuse (), 0, KEY_READ, &key) !=
56 ERROR_SUCCESS)
23c9e63c
DD
57 return 0;
58
3c054baf
RC
59 DWORD retvallen = 0;
60 DWORD type;
61
62 String Sretval;
23c9e63c
DD
63 if (RegQueryValueEx (key, "native", 0, &type, 0, &retvallen)
64 == ERROR_SUCCESS)
65 {
3c054baf 66 char retval[retvallen];
b24c88b3
RC
67 if (RegQueryValueEx
68 (key, "native", 0, &type, (BYTE *) retval,
3c054baf
RC
69 &retvallen) == ERROR_SUCCESS)
70 Sretval = String (retval);
23c9e63c
DD
71 }
72
3c054baf 73 DWORD flags = 0;
23c9e63c 74 retvallen = sizeof (flags);
b24c88b3 75 RegQueryValueEx (key, "flags", 0, &type, (BYTE *) & flags, &retvallen);
23c9e63c
DD
76
77 RegCloseKey (key);
78
3c054baf 79 if (Sretval.size ())
23c9e63c 80 *istext = (flags & MOUNT_BINARY) ? 0 : 1;
23c9e63c 81
3c054baf 82 return Sretval;
23c9e63c
DD
83}
84
85void
3c054baf
RC
86create_mount (String const posix, String const win32, int istext,
87 int issystem)
23c9e63c
DD
88{
89 char buf[1000];
23c9e63c 90 HKEY key;
b24c88b3 91 DWORD disposition;
23c9e63c
DD
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,
3c054baf 99 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, posix.cstr_oneuse ());
23c9e63c 100
24e259bb 101 HKEY kr = issystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
3c054baf 102 if (RegCreateKeyEx (kr, buf, 0, "Cygwin", 0, KEY_ALL_ACCESS,
23c9e63c
DD
103 0, &key, &disposition) != ERROR_SUCCESS)
104 fatal ("mount");
105
3c054baf
RC
106 RegSetValueEx (key, "native", 0, REG_SZ, (BYTE *) win32.cstr_oneuse (),
107 win32.size () + 1);
24e259bb
DD
108 flags = 0;
109 if (!istext)
110 flags |= MOUNT_BINARY;
111 if (issystem)
112 flags |= MOUNT_SYSTEM;
b24c88b3
RC
113 RegSetValueEx (key, "flags", 0, REG_DWORD, (BYTE *) & flags,
114 sizeof (flags));
115
116 RegCloseKey (key);
0af2d779 117 read_mounts ();
23c9e63c
DD
118}
119
120static void
3c054baf 121remove1 (HKEY rkey, String const posix)
23c9e63c
DD
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,
3c054baf 128 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, posix.cstr_oneuse ());
23c9e63c
DD
129
130 RegDeleteKey (rkey, buf);
131}
132
133void
3c054baf 134remove_mount (String const posix)
23c9e63c
DD
135{
136 remove1 (HKEY_LOCAL_MACHINE, posix);
137 remove1 (HKEY_CURRENT_USER, posix);
138}
f8a6415f
DD
139
140static void
141set_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,
b24c88b3 151 (BYTE *) & cygdrive_flags, sizeof (cygdrive_flags));
f8a6415f
DD
152 }
153}
154
155static LONG
b24c88b3 156get_cygdrive_flags (HKEY key, DWORD * cygdrive_flags)
f8a6415f 157{
b24c88b3 158 DWORD retvallen = sizeof (*cygdrive_flags);
f8a6415f 159 LONG status = RegQueryValueEx (key, CYGWIN_INFO_CYGDRIVE_FLAGS, 0, 0,
b24c88b3 160 (BYTE *) cygdrive_flags, &retvallen);
f8a6415f
DD
161 return status;
162}
163
164static DWORD
b24c88b3 165default_cygdrive (HKEY key)
f8a6415f
DD
166{
167 RegSetValueEx (key, CYGWIN_INFO_CYGDRIVE_PREFIX, 0, REG_SZ,
b24c88b3 168 (BYTE *) CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX,
f8a6415f
DD
169 strlen (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX) + 1);
170 DWORD cygdrive_flags = MOUNT_AUTO;
171 RegSetValueEx (key, CYGWIN_INFO_CYGDRIVE_FLAGS, 0, REG_DWORD,
b24c88b3 172 (BYTE *) & cygdrive_flags, sizeof (cygdrive_flags));
f8a6415f
DD
173 return cygdrive_flags;
174}
175
176void
177set_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,
b24c88b3 192 KEY_ALL_ACCESS, 0, &key, &disposition);
f8a6415f
DD
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 }
b24c88b3 202 RegCloseKey (key);
f8a6415f
DD
203 }
204 }
205
206 HKEY key;
207 DWORD disposition;
b24c88b3
RC
208 LONG status =
209 RegCreateKeyEx (HKEY_CURRENT_USER, buf, 0, 0, 0, KEY_ALL_ACCESS,
210 0, &key, &disposition);
f8a6415f
DD
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 {
b24c88b3 218 cygdrive_flags = default_cygdrive (key);
f8a6415f
DD
219 status = ERROR_SUCCESS;
220 }
221
222 if (status == ERROR_SUCCESS)
223 set_cygdrive_flags (key, istext, cygdrive_flags);
224
b24c88b3 225 RegCloseKey (key);
f8a6415f 226}
a351e48c 227
85b43844 228static int
a351e48c
CF
229in_table (struct mnt *m)
230{
b24c88b3 231 for (struct mnt * m1 = mount_table; m1 < m; m1++)
3c054baf 232 if (m1->posix.casecompare (m->posix) == 0)
a351e48c
CF
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
243static int
244is_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;
b24c88b3 255 BOOL status = OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token);
a351e48c
CF
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);
b24c88b3
RC
263 status =
264 GetTokenInformation (token, TokenGroups, token_info, token_info_len,
265 &token_info_len);
266 CloseHandle (token);
a351e48c
CF
267 if (!status)
268 return 0;
269
270 // Create the Administrators group SID
271 PSID admin_sid;
b24c88b3
RC
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);
a351e48c
CF
277 if (!status)
278 return 0;
279
280 // Check to see if the user is a member of the Administrators group
281 status = 0;
b24c88b3
RC
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 }
a351e48c 289 }
a351e48c
CF
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
298void
299read_mounts ()
300{
301 DWORD posix_path_size;
302 int res;
303 struct mnt *m = mount_table;
304 DWORD disposition;
305 char buf[10000];
306
0af2d779 307 root_here = NULL;
3c054baf 308 for (mnt * m1 = mount_table; m1->posix.size (); m1++)
0af2d779 309 {
3c054baf
RC
310 m1->posix = String (); //empty string;
311 m1->native = String ();
0af2d779
CF
312 }
313
a351e48c
CF
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;
3c054baf 326 if (RegCreateKeyEx (key, buf, 0, "Cygwin", 0, KEY_ALL_ACCESS,
a351e48c
CF
327 0, &key, &disposition) != ERROR_SUCCESS)
328 break;
b24c88b3 329 for (int i = 0;; i++, m++)
a351e48c 330 {
3c054baf 331 char aBuffer[MAX_PATH + 1];
a351e48c
CF
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. */
3c054baf 336 res = RegEnumKeyEx (key, i, aBuffer, &posix_path_size, NULL,
a351e48c
CF
337 NULL, NULL, NULL);
338
339 if (res == ERROR_NO_MORE_ITEMS)
0af2d779 340 {
3c054baf 341 m->posix = String ();
0af2d779
CF
342 break;
343 }
3c054baf 344 m->posix = String (aBuffer);
a351e48c 345
3c054baf 346 if (!m->posix.size () || in_table (m))
0af2d779 347 goto no_go;
a351e48c
CF
348 else if (res != ERROR_SUCCESS)
349 break;
350 else
351 {
352 m->native = find2 (key, &m->istext, m->posix);
3c054baf 353 if (!m->native.size ())
0af2d779 354 goto no_go;
b24c88b3 355
3c054baf 356 if (m->posix == "/")
a351e48c 357 {
85b43844 358 root_here = m;
a351e48c
CF
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 }
0af2d779
CF
369 continue;
370 no_go:
3c054baf
RC
371 m->posix = String ();
372 --m;
a351e48c
CF
373 }
374 RegCloseKey (key);
375 }
376
85b43844 377 if (!root_here)
a351e48c 378 {
85b43844 379 root_here = m;
3c054baf 380 m->posix = String ("/");
a351e48c 381 char windir[_MAX_PATH];
a351e48c 382 root_text = IDC_ROOT_BINARY;
b24c88b3 383 root_scope = (is_admin ())? IDC_ROOT_SYSTEM : IDC_ROOT_USER;
85b43844
CF
384 GetWindowsDirectory (windir, sizeof (windir));
385 windir[2] = 0;
3c054baf 386 set_root_dir (String (windir) + "\\cygwin");
0af2d779 387 m++;
a351e48c 388 }
a351e48c
CF
389}
390
85b43844 391void
3c054baf 392set_root_dir (String const val)
85b43844
CF
393{
394 root_here->native = val;
395}
396
3c054baf 397String const
85b43844
CF
398get_root_dir ()
399{
3c054baf 400 return root_here ? root_here->native : String ();
85b43844
CF
401}
402
a351e48c
CF
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 "".
a351e48c
CF
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
416static int
3c054baf 417path_prefix_p (String const path1, String const path2)
a351e48c 418{
3c054baf 419 size_t len1 = path1.size ();
a351e48c 420 /* Handle case where PATH1 has trailing '/' and when it doesn't. */
3c054baf
RC
421 if (len1 > 0 && SLASH_P (path1.cstr_oneuse ()[len1 - 1]))
422 --len1;
a351e48c
CF
423
424 if (len1 == 0)
3c054baf
RC
425 return SLASH_P (path2.cstr_oneuse ()[0])
426 && !SLASH_P (path2.cstr_oneuse ()[1]);
a351e48c 427
3c054baf 428 if (path1.casecompare (path2, len1) != 0)
a351e48c
CF
429 return 0;
430
3c054baf
RC
431 return SLASH_P (path2.cstr_oneuse ()[len1]) || path2.size () == len1
432 || path1.cstr_oneuse ()[len1 - 1] == ':';
a351e48c
CF
433}
434
3c054baf
RC
435static String
436cygpath (String const &thePath)
a351e48c 437{
3c054baf 438 size_t max_len = 0;
b24c88b3 439 struct mnt *m, *match = NULL;
3c054baf 440 for (m = mount_table; m->posix.size (); m++)
a351e48c 441 {
3c054baf
RC
442 size_t n = m->posix.size ();
443 if (n <= max_len || !path_prefix_p (m->posix, thePath))
a351e48c
CF
444 continue;
445 max_len = n;
446 match = m;
447 }
448
b24c88b3
RC
449 if (!match)
450 return NULL;
451
3c054baf
RC
452 String native;
453 if (max_len == thePath.size ())
454 {
455 native = match->native;
456 }
a351e48c 457 else
3c054baf 458 native = match->native + "/" + String (thePath.cstr_oneuse () + max_len);
a351e48c
CF
459 return native;
460}
3c054baf
RC
461
462String
463cygpath (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.18269 seconds and 5 git commands to generate.