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"
48 struct mnt
*root_here
= NULL
;
51 find2 (HKEY rkey
, int *istext
, String
const &what
)
55 if (RegOpenKeyEx (rkey
, what
.cstr_oneuse (), 0, KEY_READ
, &key
) !=
63 if (RegQueryValueEx (key
, "native", 0, &type
, 0, &retvallen
)
66 char retval
[retvallen
];
68 (key
, "native", 0, &type
, (BYTE
*) retval
,
69 &retvallen
) == ERROR_SUCCESS
)
70 Sretval
= String (retval
);
74 retvallen
= sizeof (flags
);
75 RegQueryValueEx (key
, "flags", 0, &type
, (BYTE
*) & flags
, &retvallen
);
80 *istext
= (flags
& MOUNT_BINARY
) ? 0 : 1;
86 create_mount (String
const posix
, String
const win32
, int istext
,
96 sprintf (buf
, "Software\\%s\\%s\\%s\\%s",
97 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
98 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
99 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
, posix
.cstr_oneuse ());
101 HKEY kr
= issystem
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
102 if (RegCreateKeyEx (kr
, buf
, 0, "Cygwin", 0, KEY_ALL_ACCESS
,
103 0, &key
, &disposition
) != ERROR_SUCCESS
)
106 RegSetValueEx (key
, "native", 0, REG_SZ
, (BYTE
*) win32
.cstr_oneuse (),
110 flags
|= MOUNT_BINARY
;
112 flags
|= MOUNT_SYSTEM
;
113 RegSetValueEx (key
, "flags", 0, REG_DWORD
, (BYTE
*) & flags
,
121 remove1 (HKEY rkey
, String
const posix
)
125 sprintf (buf
, "Software\\%s\\%s\\%s\\%s",
126 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
127 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
128 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
, posix
.cstr_oneuse ());
130 RegDeleteKey (rkey
, buf
);
134 remove_mount (String
const posix
)
136 remove1 (HKEY_LOCAL_MACHINE
, posix
);
137 remove1 (HKEY_CURRENT_USER
, posix
);
141 set_cygdrive_flags (HKEY key
, int istext
, DWORD cygdrive_flags
)
143 int cur_istext
= (cygdrive_flags
& MOUNT_BINARY
) ? 0 : 1;
144 if (cur_istext
!= istext
)
147 cygdrive_flags
|= MOUNT_BINARY
;
149 cygdrive_flags
&= ~MOUNT_BINARY
;
150 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, REG_DWORD
,
151 (BYTE
*) & cygdrive_flags
, sizeof (cygdrive_flags
));
156 get_cygdrive_flags (HKEY key
, DWORD
* cygdrive_flags
)
158 DWORD retvallen
= sizeof (*cygdrive_flags
);
159 LONG status
= RegQueryValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, 0,
160 (BYTE
*) cygdrive_flags
, &retvallen
);
165 default_cygdrive (HKEY key
)
167 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_PREFIX
, 0, REG_SZ
,
168 (BYTE
*) CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX
,
169 strlen (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX
) + 1);
170 DWORD cygdrive_flags
= MOUNT_AUTO
;
171 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, REG_DWORD
,
172 (BYTE
*) & cygdrive_flags
, sizeof (cygdrive_flags
));
173 return cygdrive_flags
;
177 set_cygdrive_flags (int istext
, int issystem
)
179 int found_system
= 0;
182 sprintf (buf
, "Software\\%s\\%s\\%s",
183 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
184 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
185 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
);
191 LONG status
= RegCreateKeyEx (HKEY_LOCAL_MACHINE
, buf
, 0, 0, 0,
192 KEY_ALL_ACCESS
, 0, &key
, &disposition
);
193 if (status
== ERROR_SUCCESS
)
195 DWORD cygdrive_flags
= 0;
196 status
= get_cygdrive_flags (key
, &cygdrive_flags
);
197 if (status
== ERROR_SUCCESS
)
199 set_cygdrive_flags (key
, istext
, cygdrive_flags
);
209 RegCreateKeyEx (HKEY_CURRENT_USER
, buf
, 0, 0, 0, KEY_ALL_ACCESS
,
210 0, &key
, &disposition
);
211 if (status
!= ERROR_SUCCESS
)
212 fatal ("set_cygdrive_flags");
214 DWORD cygdrive_flags
= 0;
215 status
= get_cygdrive_flags (key
, &cygdrive_flags
);
216 if (status
== ERROR_FILE_NOT_FOUND
&& !found_system
)
218 cygdrive_flags
= default_cygdrive (key
);
219 status
= ERROR_SUCCESS
;
222 if (status
== ERROR_SUCCESS
)
223 set_cygdrive_flags (key
, istext
, cygdrive_flags
);
229 in_table (struct mnt
*m
)
231 for (struct mnt
* m1
= mount_table
; m1
< m
; m1
++)
232 if (m1
->posix
.casecompare (m
->posix
) == 0)
238 * is_admin () determines whether or not the current user is a member of the
239 * Administrators group. On Windows 9X, the current user is considered an
240 * Administrator by definition.
246 // Windows 9X users are considered Administrators by definition
247 OSVERSIONINFO verinfo
;
248 verinfo
.dwOSVersionInfoSize
= sizeof (verinfo
);
249 GetVersionEx (&verinfo
);
250 if (verinfo
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
253 // Get the process token for the current process
255 BOOL status
= OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &token
);
259 // Get the group token information
260 UCHAR token_info
[1024];
261 PTOKEN_GROUPS groups
= (PTOKEN_GROUPS
) token_info
;
262 DWORD token_info_len
= sizeof (token_info
);
264 GetTokenInformation (token
, TokenGroups
, token_info
, token_info_len
,
270 // Create the Administrators group SID
272 SID_IDENTIFIER_AUTHORITY authority
= { SECURITY_NT_AUTHORITY
};
274 AllocateAndInitializeSid (&authority
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
275 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0,
280 // Check to see if the user is a member of the Administrators group
282 for (UINT i
= 0; i
< groups
->GroupCount
; i
++)
284 if (EqualSid (groups
->Groups
[i
].Sid
, admin_sid
))
291 // Destroy the Administrators group SID
294 // Return whether or not the user is a member of the Administrators group
301 DWORD posix_path_size
;
303 struct mnt
*m
= mount_table
;
308 for (mnt
* m1
= mount_table
; m1
->posix
.size (); m1
++)
310 m1
->posix
= String (); //empty string;
311 m1
->native
= String ();
314 /* Loop through subkeys */
315 /* FIXME: we would like to not check MAX_MOUNTS but the heap in the
316 shared area is currently statically allocated so we can't have an
317 arbitrarily large number of mounts. */
318 for (int issystem
= 0; issystem
<= 1; issystem
++)
320 sprintf (buf
, "Software\\%s\\%s\\%s",
321 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
322 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
323 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
);
325 HKEY key
= issystem
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
326 if (RegCreateKeyEx (key
, buf
, 0, "Cygwin", 0, KEY_ALL_ACCESS
,
327 0, &key
, &disposition
) != ERROR_SUCCESS
)
329 for (int i
= 0;; i
++, m
++)
331 char aBuffer
[MAX_PATH
+ 1];
332 posix_path_size
= MAX_PATH
;
333 /* FIXME: if maximum posix_path_size is 256, we're going to
334 run into problems if we ever try to store a mount point that's
335 over 256 but is under MAX_PATH. */
336 res
= RegEnumKeyEx (key
, i
, aBuffer
, &posix_path_size
, NULL
,
339 if (res
== ERROR_NO_MORE_ITEMS
)
341 m
->posix
= String ();
344 m
->posix
= String (aBuffer
);
346 if (!m
->posix
.size () || in_table (m
))
348 else if (res
!= ERROR_SUCCESS
)
352 m
->native
= find2 (key
, &m
->istext
, m
->posix
);
353 if (!m
->native
.size ())
360 root_text
= IDC_ROOT_TEXT
;
362 root_text
= IDC_ROOT_BINARY
;
364 root_scope
= IDC_ROOT_SYSTEM
;
366 root_scope
= IDC_ROOT_USER
;
371 m
->posix
= String ();
380 m
->posix
= String ("/");
381 char windir
[_MAX_PATH
];
382 root_text
= IDC_ROOT_BINARY
;
383 root_scope
= (is_admin ())? IDC_ROOT_SYSTEM
: IDC_ROOT_USER
;
384 GetWindowsDirectory (windir
, sizeof (windir
));
386 set_root_dir (String (windir
) + "\\cygwin");
392 set_root_dir (String
const val
)
394 root_here
->native
= val
;
400 return root_here
? root_here
->native
: String ();
403 /* Return non-zero if PATH1 is a prefix of PATH2.
404 Both are assumed to be of the same path style and / vs \ usage.
408 /foo/ is a prefix of /foo <-- may seem odd, but desired
409 /foo is a prefix of /foo/
410 / is a prefix of /foo/bar
411 / is not a prefix of foo/bar
412 foo/ is a prefix foo/bar
413 /foo is not a prefix of /foobar
417 path_prefix_p (String
const path1
, String
const path2
)
419 size_t len1
= path1
.size ();
420 /* Handle case where PATH1 has trailing '/' and when it doesn't. */
421 if (len1
> 0 && SLASH_P (path1
.cstr_oneuse ()[len1
- 1]))
425 return SLASH_P (path2
.cstr_oneuse ()[0])
426 && !SLASH_P (path2
.cstr_oneuse ()[1]);
428 if (path1
.casecompare (path2
, len1
) != 0)
431 return SLASH_P (path2
.cstr_oneuse ()[len1
]) || path2
.size () == len1
432 || path1
.cstr_oneuse ()[len1
- 1] == ':';
436 cygpath (String
const &thePath
)
439 struct mnt
*m
, *match
= NULL
;
440 for (m
= mount_table
; m
->posix
.size (); m
++)
442 size_t n
= m
->posix
.size ();
443 if (n
<= max_len
|| !path_prefix_p (m
->posix
, thePath
))
453 if (max_len
== thePath
.size ())
455 native
= match
->native
;
458 native
= match
->native
+ "/" + String (thePath
.cstr_oneuse () + max_len
);
463 cygpath (const char *s
, ...)
468 char *path
= vconcat (s
, v
);
469 if (strncmp (path
, "./", 2) == 0)
470 memmove (path
, path
+ 2, strlen (path
+ 2) + 1);
471 if (strncmp (path
, "/./", 3) == 0)
472 memmove (path
+ 1, path
+ 3, strlen (path
+ 3) + 1);
474 String
thePath (path
);
476 return cygpath (thePath
);