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