]> cygwin.com Git - cygwin-apps/setup.git/blame - mount.cc
2002-05-26 Ralf Habacker <ralf.habacker@freenet.de>
[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);
45e01f23
RC
241 if (status == ERROR_FILE_NOT_FOUND)
242 {
243 status = ERROR_SUCCESS;
244 cygdrive_flags = default_cygdrive (key);
245 }
f8a6415f
DD
246 if (status == ERROR_SUCCESS)
247 {
248 set_cygdrive_flags (key, istext, cygdrive_flags);
249 found_system = 1;
250 }
b24c88b3 251 RegCloseKey (key);
f8a6415f
DD
252 }
253 }
254
255 HKEY key;
256 DWORD disposition;
b24c88b3
RC
257 LONG status =
258 RegCreateKeyEx (HKEY_CURRENT_USER, buf, 0, 0, 0, KEY_ALL_ACCESS,
259 0, &key, &disposition);
f8a6415f
DD
260 if (status != ERROR_SUCCESS)
261 fatal ("set_cygdrive_flags");
262
263 DWORD cygdrive_flags = 0;
264 status = get_cygdrive_flags (key, &cygdrive_flags);
265 if (status == ERROR_FILE_NOT_FOUND && !found_system)
266 {
b24c88b3 267 cygdrive_flags = default_cygdrive (key);
f8a6415f
DD
268 status = ERROR_SUCCESS;
269 }
270
271 if (status == ERROR_SUCCESS)
272 set_cygdrive_flags (key, istext, cygdrive_flags);
273
b24c88b3 274 RegCloseKey (key);
f8a6415f 275}
a351e48c 276
85b43844 277static int
a351e48c
CF
278in_table (struct mnt *m)
279{
b24c88b3 280 for (struct mnt * m1 = mount_table; m1 < m; m1++)
3c054baf 281 if (m1->posix.casecompare (m->posix) == 0)
a351e48c
CF
282 return 1;
283 return 0;
284}
285
286/*
287 * is_admin () determines whether or not the current user is a member of the
288 * Administrators group. On Windows 9X, the current user is considered an
289 * Administrator by definition.
290 */
291
292static int
293is_admin ()
294{
295 // Windows 9X users are considered Administrators by definition
296 OSVERSIONINFO verinfo;
297 verinfo.dwOSVersionInfoSize = sizeof (verinfo);
298 GetVersionEx (&verinfo);
299 if (verinfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
300 return 1;
301
302 // Get the process token for the current process
303 HANDLE token;
b24c88b3 304 BOOL status = OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token);
a351e48c
CF
305 if (!status)
306 return 0;
307
308 // Get the group token information
309 UCHAR token_info[1024];
310 PTOKEN_GROUPS groups = (PTOKEN_GROUPS) token_info;
311 DWORD token_info_len = sizeof (token_info);
b24c88b3
RC
312 status =
313 GetTokenInformation (token, TokenGroups, token_info, token_info_len,
314 &token_info_len);
315 CloseHandle (token);
a351e48c
CF
316 if (!status)
317 return 0;
318
319 // Create the Administrators group SID
320 PSID admin_sid;
b24c88b3
RC
321 SID_IDENTIFIER_AUTHORITY authority = { SECURITY_NT_AUTHORITY };
322 status =
323 AllocateAndInitializeSid (&authority, 2, SECURITY_BUILTIN_DOMAIN_RID,
324 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
325 &admin_sid);
a351e48c
CF
326 if (!status)
327 return 0;
328
329 // Check to see if the user is a member of the Administrators group
330 status = 0;
b24c88b3
RC
331 for (UINT i = 0; i < groups->GroupCount; i++)
332 {
333 if (EqualSid (groups->Groups[i].Sid, admin_sid))
334 {
335 status = 1;
336 break;
337 }
a351e48c 338 }
a351e48c
CF
339
340 // Destroy the Administrators group SID
341 FreeSid (admin_sid);
342
343 // Return whether or not the user is a member of the Administrators group
344 return status;
345}
346
347void
348read_mounts ()
349{
350 DWORD posix_path_size;
351 int res;
352 struct mnt *m = mount_table;
353 DWORD disposition;
354 char buf[10000];
355
0af2d779 356 root_here = NULL;
3c054baf 357 for (mnt * m1 = mount_table; m1->posix.size (); m1++)
0af2d779 358 {
3c054baf
RC
359 m1->posix = String (); //empty string;
360 m1->native = String ();
0af2d779
CF
361 }
362
a351e48c
CF
363 /* Loop through subkeys */
364 /* FIXME: we would like to not check MAX_MOUNTS but the heap in the
365 shared area is currently statically allocated so we can't have an
366 arbitrarily large number of mounts. */
367 for (int issystem = 0; issystem <= 1; issystem++)
368 {
369 sprintf (buf, "Software\\%s\\%s\\%s",
370 CYGWIN_INFO_CYGNUS_REGISTRY_NAME,
371 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
372 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME);
373
374 HKEY key = issystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
c90bc3df 375 if (RegCreateKeyEx (key, buf, 0, (char *)"Cygwin", 0, KEY_ALL_ACCESS,
a351e48c
CF
376 0, &key, &disposition) != ERROR_SUCCESS)
377 break;
b24c88b3 378 for (int i = 0;; i++, m++)
a351e48c 379 {
3c054baf 380 char aBuffer[MAX_PATH + 1];
a351e48c
CF
381 posix_path_size = MAX_PATH;
382 /* FIXME: if maximum posix_path_size is 256, we're going to
383 run into problems if we ever try to store a mount point that's
384 over 256 but is under MAX_PATH. */
3c054baf 385 res = RegEnumKeyEx (key, i, aBuffer, &posix_path_size, NULL,
a351e48c
CF
386 NULL, NULL, NULL);
387
388 if (res == ERROR_NO_MORE_ITEMS)
0af2d779 389 {
3c054baf 390 m->posix = String ();
0af2d779
CF
391 break;
392 }
3c054baf 393 m->posix = String (aBuffer);
a351e48c 394
3c054baf 395 if (!m->posix.size () || in_table (m))
0af2d779 396 goto no_go;
a351e48c
CF
397 else if (res != ERROR_SUCCESS)
398 break;
399 else
400 {
401 m->native = find2 (key, &m->istext, m->posix);
3c054baf 402 if (!m->native.size ())
0af2d779 403 goto no_go;
b24c88b3 404
3c054baf 405 if (m->posix == "/")
a351e48c 406 {
85b43844 407 root_here = m;
a351e48c
CF
408 if (m->istext)
409 root_text = IDC_ROOT_TEXT;
410 else
411 root_text = IDC_ROOT_BINARY;
412 if (issystem)
413 root_scope = IDC_ROOT_SYSTEM;
414 else
415 root_scope = IDC_ROOT_USER;
416 }
417 }
0af2d779
CF
418 continue;
419 no_go:
3c054baf
RC
420 m->posix = String ();
421 --m;
a351e48c
CF
422 }
423 RegCloseKey (key);
424 }
425
85b43844 426 if (!root_here)
a351e48c 427 {
85b43844 428 root_here = m;
3c054baf 429 m->posix = String ("/");
a351e48c 430 char windir[_MAX_PATH];
a351e48c 431 root_text = IDC_ROOT_BINARY;
b24c88b3 432 root_scope = (is_admin ())? IDC_ROOT_SYSTEM : IDC_ROOT_USER;
85b43844
CF
433 GetWindowsDirectory (windir, sizeof (windir));
434 windir[2] = 0;
3c054baf 435 set_root_dir (String (windir) + "\\cygwin");
0af2d779 436 m++;
a351e48c 437 }
a351e48c
CF
438}
439
85b43844 440void
3c054baf 441set_root_dir (String const val)
85b43844
CF
442{
443 root_here->native = val;
444}
445
3c054baf 446String const
85b43844
CF
447get_root_dir ()
448{
3c054baf 449 return root_here ? root_here->native : String ();
85b43844
CF
450}
451
a351e48c
CF
452/* Return non-zero if PATH1 is a prefix of PATH2.
453 Both are assumed to be of the same path style and / vs \ usage.
454 Neither may be "".
a351e48c
CF
455
456 Examples:
457 /foo/ is a prefix of /foo <-- may seem odd, but desired
458 /foo is a prefix of /foo/
459 / is a prefix of /foo/bar
460 / is not a prefix of foo/bar
461 foo/ is a prefix foo/bar
462 /foo is not a prefix of /foobar
463*/
464
465static int
3c054baf 466path_prefix_p (String const path1, String const path2)
a351e48c 467{
3c054baf 468 size_t len1 = path1.size ();
a351e48c 469 /* Handle case where PATH1 has trailing '/' and when it doesn't. */
3c054baf
RC
470 if (len1 > 0 && SLASH_P (path1.cstr_oneuse ()[len1 - 1]))
471 --len1;
a351e48c
CF
472
473 if (len1 == 0)
3c054baf
RC
474 return SLASH_P (path2.cstr_oneuse ()[0])
475 && !SLASH_P (path2.cstr_oneuse ()[1]);
a351e48c 476
3c054baf 477 if (path1.casecompare (path2, len1) != 0)
a351e48c
CF
478 return 0;
479
3c054baf
RC
480 return SLASH_P (path2.cstr_oneuse ()[len1]) || path2.size () == len1
481 || path1.cstr_oneuse ()[len1 - 1] == ':';
a351e48c
CF
482}
483
1ac649ed 484String
3c054baf 485cygpath (String const &thePath)
a351e48c 486{
3c054baf 487 size_t max_len = 0;
b24c88b3 488 struct mnt *m, *match = NULL;
3c054baf 489 for (m = mount_table; m->posix.size (); m++)
a351e48c 490 {
3c054baf
RC
491 size_t n = m->posix.size ();
492 if (n <= max_len || !path_prefix_p (m->posix, thePath))
a351e48c
CF
493 continue;
494 max_len = n;
495 match = m;
496 }
497
b24c88b3 498 if (!match)
076654e7 499 return String();
b24c88b3 500
3c054baf
RC
501 String native;
502 if (max_len == thePath.size ())
503 {
504 native = match->native;
505 }
a351e48c 506 else
1ac649ed 507 native = match->native + "/" + String (thePath.cstr_oneuse() + max_len);
a351e48c
CF
508 return native;
509}
This page took 0.085775 seconds and 5 git commands to generate.