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";
28 #include "../cygwin/include/cygwin/version.h"
29 #include "../cygwin/include/sys/mount.h"
39 /* Used when treating / and \ as equivalent. */
43 ((__c) == '/' || (__c) == '\\'); \
54 struct mnt
*root_here
= NULL
;
57 find2 (HKEY rkey
, int *istext
, String
const &what
)
61 if (RegOpenKeyEx (rkey
, what
.cstr_oneuse (), 0, KEY_READ
, &key
) !=
69 if (RegQueryValueEx (key
, "native", 0, &type
, 0, &retvallen
)
72 char retval
[retvallen
];
74 (key
, "native", 0, &type
, (BYTE
*) retval
,
75 &retvallen
) == ERROR_SUCCESS
)
76 Sretval
= String (retval
);
80 retvallen
= sizeof (flags
);
81 RegQueryValueEx (key
, "flags", 0, &type
, (BYTE
*) & flags
, &retvallen
);
86 *istext
= (flags
& MOUNT_BINARY
) ? 0 : 1;
92 create_mount (String
const posix
, String
const win32
, int istext
,
100 remove_mount (posix
);
102 sprintf (buf
, "Software\\%s\\%s\\%s\\%s",
103 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
104 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
105 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
, posix
.cstr_oneuse ());
107 HKEY kr
= issystem
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
108 if (RegCreateKeyEx (kr
, buf
, 0, "Cygwin", 0, KEY_ALL_ACCESS
,
109 0, &key
, &disposition
) != ERROR_SUCCESS
)
112 RegSetValueEx (key
, "native", 0, REG_SZ
, (BYTE
*) win32
.cstr_oneuse (),
116 flags
|= MOUNT_BINARY
;
118 flags
|= MOUNT_SYSTEM
;
119 RegSetValueEx (key
, "flags", 0, REG_DWORD
, (BYTE
*) & flags
,
127 remove1 (HKEY rkey
, String
const posix
)
131 sprintf (buf
, "Software\\%s\\%s\\%s\\%s",
132 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
133 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
134 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
, posix
.cstr_oneuse ());
136 RegDeleteKey (rkey
, buf
);
140 remove_mount (String
const posix
)
142 remove1 (HKEY_LOCAL_MACHINE
, posix
);
143 remove1 (HKEY_CURRENT_USER
, posix
);
147 set_cygdrive_flags (HKEY key
, int istext
, DWORD cygdrive_flags
)
149 int cur_istext
= (cygdrive_flags
& MOUNT_BINARY
) ? 0 : 1;
150 if (cur_istext
!= istext
)
153 cygdrive_flags
|= MOUNT_BINARY
;
155 cygdrive_flags
&= ~MOUNT_BINARY
;
156 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, REG_DWORD
,
157 (BYTE
*) & cygdrive_flags
, sizeof (cygdrive_flags
));
162 get_cygdrive_flags (HKEY key
, DWORD
* cygdrive_flags
)
164 DWORD retvallen
= sizeof (*cygdrive_flags
);
165 LONG status
= RegQueryValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, 0,
166 (BYTE
*) cygdrive_flags
, &retvallen
);
171 default_cygdrive (HKEY key
)
173 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_PREFIX
, 0, REG_SZ
,
174 (BYTE
*) CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX
,
175 strlen (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX
) + 1);
176 DWORD cygdrive_flags
= MOUNT_AUTO
;
177 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, REG_DWORD
,
178 (BYTE
*) & cygdrive_flags
, sizeof (cygdrive_flags
));
179 return cygdrive_flags
;
183 set_cygdrive_flags (int istext
, int issystem
)
185 int found_system
= 0;
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
);
197 LONG status
= RegCreateKeyEx (HKEY_LOCAL_MACHINE
, buf
, 0, 0, 0,
198 KEY_ALL_ACCESS
, 0, &key
, &disposition
);
199 if (status
== ERROR_SUCCESS
)
201 DWORD cygdrive_flags
= 0;
202 status
= get_cygdrive_flags (key
, &cygdrive_flags
);
203 if (status
== ERROR_SUCCESS
)
205 set_cygdrive_flags (key
, istext
, cygdrive_flags
);
215 RegCreateKeyEx (HKEY_CURRENT_USER
, buf
, 0, 0, 0, KEY_ALL_ACCESS
,
216 0, &key
, &disposition
);
217 if (status
!= ERROR_SUCCESS
)
218 fatal ("set_cygdrive_flags");
220 DWORD cygdrive_flags
= 0;
221 status
= get_cygdrive_flags (key
, &cygdrive_flags
);
222 if (status
== ERROR_FILE_NOT_FOUND
&& !found_system
)
224 cygdrive_flags
= default_cygdrive (key
);
225 status
= ERROR_SUCCESS
;
228 if (status
== ERROR_SUCCESS
)
229 set_cygdrive_flags (key
, istext
, cygdrive_flags
);
235 in_table (struct mnt
*m
)
237 for (struct mnt
* m1
= mount_table
; m1
< m
; m1
++)
238 if (m1
->posix
.casecompare (m
->posix
) == 0)
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.
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
)
259 // Get the process token for the current process
261 BOOL status
= OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &token
);
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
);
270 GetTokenInformation (token
, TokenGroups
, token_info
, token_info_len
,
276 // Create the Administrators group SID
278 SID_IDENTIFIER_AUTHORITY authority
= { SECURITY_NT_AUTHORITY
};
280 AllocateAndInitializeSid (&authority
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
281 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0,
286 // Check to see if the user is a member of the Administrators group
288 for (UINT i
= 0; i
< groups
->GroupCount
; i
++)
290 if (EqualSid (groups
->Groups
[i
].Sid
, admin_sid
))
297 // Destroy the Administrators group SID
300 // Return whether or not the user is a member of the Administrators group
307 DWORD posix_path_size
;
309 struct mnt
*m
= mount_table
;
314 for (mnt
* m1
= mount_table
; m1
->posix
.size (); m1
++)
316 m1
->posix
= String (); //empty string;
317 m1
->native
= String ();
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
++)
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
);
331 HKEY key
= issystem
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
332 if (RegCreateKeyEx (key
, buf
, 0, "Cygwin", 0, KEY_ALL_ACCESS
,
333 0, &key
, &disposition
) != ERROR_SUCCESS
)
335 for (int i
= 0;; i
++, m
++)
337 char aBuffer
[MAX_PATH
+ 1];
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. */
342 res
= RegEnumKeyEx (key
, i
, aBuffer
, &posix_path_size
, NULL
,
345 if (res
== ERROR_NO_MORE_ITEMS
)
347 m
->posix
= String ();
350 m
->posix
= String (aBuffer
);
352 if (!m
->posix
.size () || in_table (m
))
354 else if (res
!= ERROR_SUCCESS
)
358 m
->native
= find2 (key
, &m
->istext
, m
->posix
);
359 if (!m
->native
.size ())
366 root_text
= IDC_ROOT_TEXT
;
368 root_text
= IDC_ROOT_BINARY
;
370 root_scope
= IDC_ROOT_SYSTEM
;
372 root_scope
= IDC_ROOT_USER
;
377 m
->posix
= String ();
386 m
->posix
= String ("/");
387 char windir
[_MAX_PATH
];
388 root_text
= IDC_ROOT_BINARY
;
389 root_scope
= (is_admin ())? IDC_ROOT_SYSTEM
: IDC_ROOT_USER
;
390 GetWindowsDirectory (windir
, sizeof (windir
));
392 set_root_dir (String (windir
) + "\\cygwin");
398 set_root_dir (String
const val
)
400 root_here
->native
= val
;
406 return root_here
? root_here
->native
: String ();
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.
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
423 path_prefix_p (String
const path1
, String
const path2
)
425 size_t len1
= path1
.size ();
426 /* Handle case where PATH1 has trailing '/' and when it doesn't. */
427 if (len1
> 0 && SLASH_P (path1
.cstr_oneuse ()[len1
- 1]))
431 return SLASH_P (path2
.cstr_oneuse ()[0])
432 && !SLASH_P (path2
.cstr_oneuse ()[1]);
434 if (path1
.casecompare (path2
, len1
) != 0)
437 return SLASH_P (path2
.cstr_oneuse ()[len1
]) || path2
.size () == len1
438 || path1
.cstr_oneuse ()[len1
- 1] == ':';
442 cygpath (String
const &thePath
)
445 struct mnt
*m
, *match
= NULL
;
446 for (m
= mount_table
; m
->posix
.size (); m
++)
448 size_t n
= m
->posix
.size ();
449 if (n
<= max_len
|| !path_prefix_p (m
->posix
, thePath
))
459 if (max_len
== thePath
.size ())
461 native
= match
->native
;
464 native
= match
->native
+ "/" + String (thePath
.cstr_oneuse() + max_len
);