2 * Copyright (c) 2000, Red Hat, Inc.
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.
9 * A copy of the GNU General Public License can be found at
12 * Written by DJ Delorie <dj@cygnus.com>
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. */
21 static const char *cvsid
= "\n%%% $Id$\n";
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
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"
41 // #include "../cygwin/include/sys/mount.h"
43 // KEEP SYNCHRONISED WITH /src/winsup/cygwin/include/sys/mount.h
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 */
59 // int mount (const char *, const char *, unsigned __flags);
60 // int umount (const char *);
61 // int cygwin_umount (const char *__path, unsigned __flags);
77 #ifdef MAINTAINER_FEATURES
78 #include "getopt++/GetOption.h"
79 #include "getopt++/StringOption.h"
80 static StringOption
CygwinRegistryNameOption (CYGWIN_INFO_CYGWIN_REGISTRY_NAME
, '#', "override-registry-name", "Override registry name to allow parallel installs for testing purposes", false);
81 #undef CYGWIN_INFO_CYGWIN_REGISTRY_NAME
82 #define CYGWIN_INFO_CYGWIN_REGISTRY_NAME (((std::string)CygwinRegistryNameOption).c_str())
85 /* Used when treating / and \ as equivalent. */
89 ((__c) == '/' || (__c) == '\\'); \
100 struct mnt
*root_here
= NULL
;
103 find2 (HKEY rkey
, int *istext
, String
const &what
)
107 if (RegOpenKeyEx (rkey
, what
.cstr_oneuse (), 0, KEY_READ
, &key
) !=
115 if (RegQueryValueEx (key
, "native", 0, &type
, 0, &retvallen
)
118 char retval
[retvallen
];
120 (key
, "native", 0, &type
, (BYTE
*) retval
,
121 &retvallen
) == ERROR_SUCCESS
)
122 Sretval
= String (retval
);
126 retvallen
= sizeof (flags
);
127 RegQueryValueEx (key
, "flags", 0, &type
, (BYTE
*) & flags
, &retvallen
);
132 *istext
= (flags
& MOUNT_BINARY
) ? 0 : 1;
138 create_mount (String
const posix
, String
const win32
, int istext
,
146 remove_mount (posix
);
148 snprintf (buf
, sizeof(buf
), "Software\\%s\\%s\\%s\\%s",
149 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
150 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
151 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
, posix
.cstr_oneuse ());
153 HKEY kr
= issystem
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
154 if (RegCreateKeyEx (kr
, buf
, 0, (char *)"Cygwin", 0, KEY_ALL_ACCESS
,
155 0, &key
, &disposition
) != ERROR_SUCCESS
)
158 RegSetValueEx (key
, "native", 0, REG_SZ
, (BYTE
*) win32
.cstr_oneuse (),
162 flags
|= MOUNT_BINARY
;
164 flags
|= MOUNT_SYSTEM
;
165 RegSetValueEx (key
, "flags", 0, REG_DWORD
, (BYTE
*) & flags
,
173 remove1 (HKEY rkey
, String
const posix
)
177 snprintf (buf
, sizeof(buf
), "Software\\%s\\%s\\%s\\%s",
178 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
179 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
180 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
, posix
.cstr_oneuse ());
182 RegDeleteKey (rkey
, buf
);
186 remove_mount (String
const posix
)
188 remove1 (HKEY_LOCAL_MACHINE
, posix
);
189 remove1 (HKEY_CURRENT_USER
, posix
);
193 set_cygdrive_flags (HKEY key
, int istext
, DWORD cygdrive_flags
)
195 int cur_istext
= (cygdrive_flags
& MOUNT_BINARY
) ? 0 : 1;
196 if (cur_istext
!= istext
)
199 cygdrive_flags
|= MOUNT_BINARY
;
201 cygdrive_flags
&= ~MOUNT_BINARY
;
202 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, REG_DWORD
,
203 (BYTE
*) & cygdrive_flags
, sizeof (cygdrive_flags
));
208 get_cygdrive_flags (HKEY key
, DWORD
* cygdrive_flags
)
210 DWORD retvallen
= sizeof (*cygdrive_flags
);
211 LONG status
= RegQueryValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, 0,
212 (BYTE
*) cygdrive_flags
, &retvallen
);
217 default_cygdrive (HKEY key
)
219 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_PREFIX
, 0, REG_SZ
,
220 (BYTE
*) CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX
,
221 strlen (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX
) + 1);
222 DWORD cygdrive_flags
= MOUNT_AUTO
;
223 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, REG_DWORD
,
224 (BYTE
*) & cygdrive_flags
, sizeof (cygdrive_flags
));
225 return cygdrive_flags
;
229 set_cygdrive_flags (int istext
, int issystem
)
231 int found_system
= 0;
234 snprintf (buf
, sizeof(buf
), "Software\\%s\\%s\\%s",
235 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
236 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
237 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
);
243 LONG status
= RegCreateKeyEx (HKEY_LOCAL_MACHINE
, buf
, 0, 0, 0,
244 KEY_ALL_ACCESS
, 0, &key
, &disposition
);
245 if (status
== ERROR_SUCCESS
)
247 DWORD cygdrive_flags
= 0;
248 status
= get_cygdrive_flags (key
, &cygdrive_flags
);
249 if (status
== ERROR_FILE_NOT_FOUND
)
251 status
= ERROR_SUCCESS
;
252 cygdrive_flags
= default_cygdrive (key
);
254 if (status
== ERROR_SUCCESS
)
256 set_cygdrive_flags (key
, istext
, cygdrive_flags
);
266 RegCreateKeyEx (HKEY_CURRENT_USER
, buf
, 0, 0, 0, KEY_ALL_ACCESS
,
267 0, &key
, &disposition
);
268 if (status
!= ERROR_SUCCESS
)
269 fatal ("set_cygdrive_flags");
271 DWORD cygdrive_flags
= 0;
272 status
= get_cygdrive_flags (key
, &cygdrive_flags
);
273 if (status
== ERROR_FILE_NOT_FOUND
&& !found_system
)
275 cygdrive_flags
= default_cygdrive (key
);
276 status
= ERROR_SUCCESS
;
279 if (status
== ERROR_SUCCESS
)
280 set_cygdrive_flags (key
, istext
, cygdrive_flags
);
286 in_table (struct mnt
*m
)
288 for (struct mnt
* m1
= mount_table
; m1
< m
; m1
++)
289 if (m1
->posix
.casecompare (m
->posix
) == 0)
295 * is_admin () determines whether or not the current user is a member of the
296 * Administrators group. On Windows 9X, the current user is considered an
297 * Administrator by definition.
303 // Windows 9X users are considered Administrators by definition
304 OSVERSIONINFO verinfo
;
305 verinfo
.dwOSVersionInfoSize
= sizeof (verinfo
);
306 GetVersionEx (&verinfo
);
307 if (verinfo
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
310 // Get the process token for the current process
312 BOOL status
= OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &token
);
316 // Get the group token information
317 UCHAR token_info
[1024];
318 PTOKEN_GROUPS groups
= (PTOKEN_GROUPS
) token_info
;
319 DWORD token_info_len
= sizeof (token_info
);
321 GetTokenInformation (token
, TokenGroups
, token_info
, token_info_len
,
327 // Create the Administrators group SID
329 SID_IDENTIFIER_AUTHORITY authority
= { SECURITY_NT_AUTHORITY
};
331 AllocateAndInitializeSid (&authority
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
332 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0,
337 // Check to see if the user is a member of the Administrators group
339 for (UINT i
= 0; i
< groups
->GroupCount
; i
++)
341 if (EqualSid (groups
->Groups
[i
].Sid
, admin_sid
))
348 // Destroy the Administrators group SID
351 // Return whether or not the user is a member of the Administrators group
358 DWORD posix_path_size
;
360 struct mnt
*m
= mount_table
;
365 for (mnt
* m1
= mount_table
; m1
->posix
.size (); m1
++)
367 m1
->posix
= String (); //empty string;
368 m1
->native
= String ();
371 /* Loop through subkeys */
372 /* FIXME: we would like to not check MAX_MOUNTS but the heap in the
373 shared area is currently statically allocated so we can't have an
374 arbitrarily large number of mounts. */
375 for (int issystem
= 0; issystem
<= 1; issystem
++)
377 snprintf (buf
, sizeof(buf
), "Software\\%s\\%s\\%s",
378 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
379 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
380 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
);
382 HKEY key
= issystem
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
383 if (RegCreateKeyEx (key
, buf
, 0, (char *)"Cygwin", 0, KEY_ALL_ACCESS
,
384 0, &key
, &disposition
) != ERROR_SUCCESS
)
386 for (int i
= 0;; i
++, m
++)
388 char aBuffer
[MAX_PATH
+ 1];
389 posix_path_size
= MAX_PATH
;
390 /* FIXME: if maximum posix_path_size is 256, we're going to
391 run into problems if we ever try to store a mount point that's
392 over 256 but is under MAX_PATH. */
393 res
= RegEnumKeyEx (key
, i
, aBuffer
, &posix_path_size
, NULL
,
396 if (res
== ERROR_NO_MORE_ITEMS
)
398 m
->posix
= String ();
401 m
->posix
= String (aBuffer
);
403 if (!m
->posix
.size () || in_table (m
))
405 else if (res
!= ERROR_SUCCESS
)
409 m
->native
= find2 (key
, &m
->istext
, m
->posix
);
410 if (!m
->native
.size ())
417 root_text
= IDC_ROOT_TEXT
;
419 root_text
= IDC_ROOT_BINARY
;
421 root_scope
= IDC_ROOT_SYSTEM
;
423 root_scope
= IDC_ROOT_USER
;
428 m
->posix
= String ();
437 m
->posix
= String ("/");
438 char windir
[_MAX_PATH
];
439 root_text
= IDC_ROOT_BINARY
;
440 root_scope
= (is_admin ())? IDC_ROOT_SYSTEM
: IDC_ROOT_USER
;
441 GetWindowsDirectory (windir
, sizeof (windir
));
443 set_root_dir (String (windir
) + "\\cygwin");
449 set_root_dir (String
const val
)
451 root_here
->native
= val
;
457 return root_here
? root_here
->native
: String ();
460 /* Return non-zero if PATH1 is a prefix of PATH2.
461 Both are assumed to be of the same path style and / vs \ usage.
465 /foo/ is a prefix of /foo <-- may seem odd, but desired
466 /foo is a prefix of /foo/
467 / is a prefix of /foo/bar
468 / is not a prefix of foo/bar
469 foo/ is a prefix foo/bar
470 /foo is not a prefix of /foobar
474 path_prefix_p (String
const path1
, String
const path2
)
476 size_t len1
= path1
.size ();
477 /* Handle case where PATH1 has trailing '/' and when it doesn't. */
478 if (len1
> 0 && SLASH_P (path1
.cstr_oneuse ()[len1
- 1]))
482 return SLASH_P (path2
.cstr_oneuse ()[0])
483 && !SLASH_P (path2
.cstr_oneuse ()[1]);
485 if (path1
.casecompare (path2
, len1
) != 0)
488 return SLASH_P (path2
.cstr_oneuse ()[len1
]) || path2
.size () == len1
489 || path1
.cstr_oneuse ()[len1
- 1] == ':';
493 cygpath (String
const &thePath
)
496 struct mnt
*m
, *match
= NULL
;
497 for (m
= mount_table
; m
->posix
.size (); m
++)
499 size_t n
= m
->posix
.size ();
500 if (n
<= max_len
|| !path_prefix_p (m
->posix
, thePath
))
510 if (max_len
== thePath
.size ())
512 native
= match
->native
;
515 native
= match
->native
+ "/" + String (thePath
.cstr_oneuse() + max_len
);