]> 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 35#include "state.h"
23c9e63c 36
3c054baf
RC
37#include "String++.h"
38
1ac649ed
RC
39/* Used when treating / and \ as equivalent. */
40#define SLASH_P(ch) \
41 ({ \
42 char __c = (ch); \
43 ((__c) == '/' || (__c) == '\\'); \
44 })
45
a351e48c 46static struct mnt
b24c88b3 47{
3c054baf
RC
48 String native;
49 String posix;
b24c88b3
RC
50 int istext;
51}
52mount_table[255];
23c9e63c 53
85b43844
CF
54struct mnt *root_here = NULL;
55
3c054baf
RC
56static String
57find2 (HKEY rkey, int *istext, String const &what)
23c9e63c 58{
a351e48c 59 HKEY key;
23c9e63c 60
3c054baf
RC
61 if (RegOpenKeyEx (rkey, what.cstr_oneuse (), 0, KEY_READ, &key) !=
62 ERROR_SUCCESS)
23c9e63c
DD
63 return 0;
64
3c054baf
RC
65 DWORD retvallen = 0;
66 DWORD type;
67
68 String Sretval;
23c9e63c
DD
69 if (RegQueryValueEx (key, "native", 0, &type, 0, &retvallen)
70 == ERROR_SUCCESS)
71 {
3c054baf 72 char retval[retvallen];
b24c88b3
RC
73 if (RegQueryValueEx
74 (key, "native", 0, &type, (BYTE *) retval,
3c054baf
RC
75 &retvallen) == ERROR_SUCCESS)
76 Sretval = String (retval);
23c9e63c
DD
77 }
78
3c054baf 79 DWORD flags = 0;
23c9e63c 80 retvallen = sizeof (flags);
b24c88b3 81 RegQueryValueEx (key, "flags", 0, &type, (BYTE *) & flags, &retvallen);
23c9e63c
DD
82
83 RegCloseKey (key);
84
3c054baf 85 if (Sretval.size ())
23c9e63c 86 *istext = (flags & MOUNT_BINARY) ? 0 : 1;
23c9e63c 87
3c054baf 88 return Sretval;
23c9e63c
DD
89}
90
91void
3c054baf
RC
92create_mount (String const posix, String const win32, int istext,
93 int issystem)
23c9e63c
DD
94{
95 char buf[1000];
23c9e63c 96 HKEY key;
b24c88b3 97 DWORD disposition;
23c9e63c
DD
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,
3c054baf 105 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, posix.cstr_oneuse ());
23c9e63c 106
24e259bb 107 HKEY kr = issystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
3c054baf 108 if (RegCreateKeyEx (kr, buf, 0, "Cygwin", 0, KEY_ALL_ACCESS,
23c9e63c
DD
109 0, &key, &disposition) != ERROR_SUCCESS)
110 fatal ("mount");
111
3c054baf
RC
112 RegSetValueEx (key, "native", 0, REG_SZ, (BYTE *) win32.cstr_oneuse (),
113 win32.size () + 1);
24e259bb
DD
114 flags = 0;
115 if (!istext)
116 flags |= MOUNT_BINARY;
117 if (issystem)
118 flags |= MOUNT_SYSTEM;
b24c88b3
RC
119 RegSetValueEx (key, "flags", 0, REG_DWORD, (BYTE *) & flags,
120 sizeof (flags));
121
122 RegCloseKey (key);
0af2d779 123 read_mounts ();
23c9e63c
DD
124}
125
126static void
3c054baf 127remove1 (HKEY rkey, String const posix)
23c9e63c
DD
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,
3c054baf 134 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME, posix.cstr_oneuse ());
23c9e63c
DD
135
136 RegDeleteKey (rkey, buf);
137}
138
139void
3c054baf 140remove_mount (String const posix)
23c9e63c
DD
141{
142 remove1 (HKEY_LOCAL_MACHINE, posix);
143 remove1 (HKEY_CURRENT_USER, posix);
144}
f8a6415f
DD
145
146static void
147set_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,
b24c88b3 157 (BYTE *) & cygdrive_flags, sizeof (cygdrive_flags));
f8a6415f
DD
158 }
159}
160
161static LONG
b24c88b3 162get_cygdrive_flags (HKEY key, DWORD * cygdrive_flags)
f8a6415f 163{
b24c88b3 164 DWORD retvallen = sizeof (*cygdrive_flags);
f8a6415f 165 LONG status = RegQueryValueEx (key, CYGWIN_INFO_CYGDRIVE_FLAGS, 0, 0,
b24c88b3 166 (BYTE *) cygdrive_flags, &retvallen);
f8a6415f
DD
167 return status;
168}
169
170static DWORD
b24c88b3 171default_cygdrive (HKEY key)
f8a6415f
DD
172{
173 RegSetValueEx (key, CYGWIN_INFO_CYGDRIVE_PREFIX, 0, REG_SZ,
b24c88b3 174 (BYTE *) CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX,
f8a6415f
DD
175 strlen (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX) + 1);
176 DWORD cygdrive_flags = MOUNT_AUTO;
177 RegSetValueEx (key, CYGWIN_INFO_CYGDRIVE_FLAGS, 0, REG_DWORD,
b24c88b3 178 (BYTE *) & cygdrive_flags, sizeof (cygdrive_flags));
f8a6415f
DD
179 return cygdrive_flags;
180}
181
182void
183set_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,
b24c88b3 198 KEY_ALL_ACCESS, 0, &key, &disposition);
f8a6415f
DD
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 }
b24c88b3 208 RegCloseKey (key);
f8a6415f
DD
209 }
210 }
211
212 HKEY key;
213 DWORD disposition;
b24c88b3
RC
214 LONG status =
215 RegCreateKeyEx (HKEY_CURRENT_USER, buf, 0, 0, 0, KEY_ALL_ACCESS,
216 0, &key, &disposition);
f8a6415f
DD
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 {
b24c88b3 224 cygdrive_flags = default_cygdrive (key);
f8a6415f
DD
225 status = ERROR_SUCCESS;
226 }
227
228 if (status == ERROR_SUCCESS)
229 set_cygdrive_flags (key, istext, cygdrive_flags);
230
b24c88b3 231 RegCloseKey (key);
f8a6415f 232}
a351e48c 233
85b43844 234static int
a351e48c
CF
235in_table (struct mnt *m)
236{
b24c88b3 237 for (struct mnt * m1 = mount_table; m1 < m; m1++)
3c054baf 238 if (m1->posix.casecompare (m->posix) == 0)
a351e48c
CF
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
249static int
250is_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;
b24c88b3 261 BOOL status = OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token);
a351e48c
CF
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);
b24c88b3
RC
269 status =
270 GetTokenInformation (token, TokenGroups, token_info, token_info_len,
271 &token_info_len);
272 CloseHandle (token);
a351e48c
CF
273 if (!status)
274 return 0;
275
276 // Create the Administrators group SID
277 PSID admin_sid;
b24c88b3
RC
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);
a351e48c
CF
283 if (!status)
284 return 0;
285
286 // Check to see if the user is a member of the Administrators group
287 status = 0;
b24c88b3
RC
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 }
a351e48c 295 }
a351e48c
CF
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
304void
305read_mounts ()
306{
307 DWORD posix_path_size;
308 int res;
309 struct mnt *m = mount_table;
310 DWORD disposition;
311 char buf[10000];
312
0af2d779 313 root_here = NULL;
3c054baf 314 for (mnt * m1 = mount_table; m1->posix.size (); m1++)
0af2d779 315 {
3c054baf
RC
316 m1->posix = String (); //empty string;
317 m1->native = String ();
0af2d779
CF
318 }
319
a351e48c
CF
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;
3c054baf 332 if (RegCreateKeyEx (key, buf, 0, "Cygwin", 0, KEY_ALL_ACCESS,
a351e48c
CF
333 0, &key, &disposition) != ERROR_SUCCESS)
334 break;
b24c88b3 335 for (int i = 0;; i++, m++)
a351e48c 336 {
3c054baf 337 char aBuffer[MAX_PATH + 1];
a351e48c
CF
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. */
3c054baf 342 res = RegEnumKeyEx (key, i, aBuffer, &posix_path_size, NULL,
a351e48c
CF
343 NULL, NULL, NULL);
344
345 if (res == ERROR_NO_MORE_ITEMS)
0af2d779 346 {
3c054baf 347 m->posix = String ();
0af2d779
CF
348 break;
349 }
3c054baf 350 m->posix = String (aBuffer);
a351e48c 351
3c054baf 352 if (!m->posix.size () || in_table (m))
0af2d779 353 goto no_go;
a351e48c
CF
354 else if (res != ERROR_SUCCESS)
355 break;
356 else
357 {
358 m->native = find2 (key, &m->istext, m->posix);
3c054baf 359 if (!m->native.size ())
0af2d779 360 goto no_go;
b24c88b3 361
3c054baf 362 if (m->posix == "/")
a351e48c 363 {
85b43844 364 root_here = m;
a351e48c
CF
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 }
0af2d779
CF
375 continue;
376 no_go:
3c054baf
RC
377 m->posix = String ();
378 --m;
a351e48c
CF
379 }
380 RegCloseKey (key);
381 }
382
85b43844 383 if (!root_here)
a351e48c 384 {
85b43844 385 root_here = m;
3c054baf 386 m->posix = String ("/");
a351e48c 387 char windir[_MAX_PATH];
a351e48c 388 root_text = IDC_ROOT_BINARY;
b24c88b3 389 root_scope = (is_admin ())? IDC_ROOT_SYSTEM : IDC_ROOT_USER;
85b43844
CF
390 GetWindowsDirectory (windir, sizeof (windir));
391 windir[2] = 0;
3c054baf 392 set_root_dir (String (windir) + "\\cygwin");
0af2d779 393 m++;
a351e48c 394 }
a351e48c
CF
395}
396
85b43844 397void
3c054baf 398set_root_dir (String const val)
85b43844
CF
399{
400 root_here->native = val;
401}
402
3c054baf 403String const
85b43844
CF
404get_root_dir ()
405{
3c054baf 406 return root_here ? root_here->native : String ();
85b43844
CF
407}
408
a351e48c
CF
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 "".
a351e48c
CF
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
422static int
3c054baf 423path_prefix_p (String const path1, String const path2)
a351e48c 424{
3c054baf 425 size_t len1 = path1.size ();
a351e48c 426 /* Handle case where PATH1 has trailing '/' and when it doesn't. */
3c054baf
RC
427 if (len1 > 0 && SLASH_P (path1.cstr_oneuse ()[len1 - 1]))
428 --len1;
a351e48c
CF
429
430 if (len1 == 0)
3c054baf
RC
431 return SLASH_P (path2.cstr_oneuse ()[0])
432 && !SLASH_P (path2.cstr_oneuse ()[1]);
a351e48c 433
3c054baf 434 if (path1.casecompare (path2, len1) != 0)
a351e48c
CF
435 return 0;
436
3c054baf
RC
437 return SLASH_P (path2.cstr_oneuse ()[len1]) || path2.size () == len1
438 || path1.cstr_oneuse ()[len1 - 1] == ':';
a351e48c
CF
439}
440
1ac649ed 441String
3c054baf 442cygpath (String const &thePath)
a351e48c 443{
3c054baf 444 size_t max_len = 0;
b24c88b3 445 struct mnt *m, *match = NULL;
3c054baf 446 for (m = mount_table; m->posix.size (); m++)
a351e48c 447 {
3c054baf
RC
448 size_t n = m->posix.size ();
449 if (n <= max_len || !path_prefix_p (m->posix, thePath))
a351e48c
CF
450 continue;
451 max_len = n;
452 match = m;
453 }
454
b24c88b3
RC
455 if (!match)
456 return NULL;
457
3c054baf
RC
458 String native;
459 if (max_len == thePath.size ())
460 {
461 native = match->native;
462 }
a351e48c 463 else
1ac649ed 464 native = match->native + "/" + String (thePath.cstr_oneuse() + max_len);
a351e48c
CF
465 return native;
466}
This page took 0.08079 seconds and 5 git commands to generate.