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 /* Used when treating / and \ as equivalent. */
81 ((__c) == '/' || (__c) == '\\'); \
92 struct mnt
*root_here
= NULL
;
95 find2 (HKEY rkey
, int *istext
, String
const &what
)
99 if (RegOpenKeyEx (rkey
, what
.cstr_oneuse (), 0, KEY_READ
, &key
) !=
107 if (RegQueryValueEx (key
, "native", 0, &type
, 0, &retvallen
)
110 char retval
[retvallen
];
112 (key
, "native", 0, &type
, (BYTE
*) retval
,
113 &retvallen
) == ERROR_SUCCESS
)
114 Sretval
= String (retval
);
118 retvallen
= sizeof (flags
);
119 RegQueryValueEx (key
, "flags", 0, &type
, (BYTE
*) & flags
, &retvallen
);
124 *istext
= (flags
& MOUNT_BINARY
) ? 0 : 1;
130 create_mount (String
const posix
, String
const win32
, int istext
,
138 remove_mount (posix
);
140 sprintf (buf
, "Software\\%s\\%s\\%s\\%s",
141 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
142 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
143 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
, posix
.cstr_oneuse ());
145 HKEY kr
= issystem
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
146 if (RegCreateKeyEx (kr
, buf
, 0, (char *)"Cygwin", 0, KEY_ALL_ACCESS
,
147 0, &key
, &disposition
) != ERROR_SUCCESS
)
150 RegSetValueEx (key
, "native", 0, REG_SZ
, (BYTE
*) win32
.cstr_oneuse (),
154 flags
|= MOUNT_BINARY
;
156 flags
|= MOUNT_SYSTEM
;
157 RegSetValueEx (key
, "flags", 0, REG_DWORD
, (BYTE
*) & flags
,
165 remove1 (HKEY rkey
, String
const posix
)
169 sprintf (buf
, "Software\\%s\\%s\\%s\\%s",
170 CYGWIN_INFO_CYGNUS_REGISTRY_NAME
,
171 CYGWIN_INFO_CYGWIN_REGISTRY_NAME
,
172 CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME
, posix
.cstr_oneuse ());
174 RegDeleteKey (rkey
, buf
);
178 remove_mount (String
const posix
)
180 remove1 (HKEY_LOCAL_MACHINE
, posix
);
181 remove1 (HKEY_CURRENT_USER
, posix
);
185 set_cygdrive_flags (HKEY key
, int istext
, DWORD cygdrive_flags
)
187 int cur_istext
= (cygdrive_flags
& MOUNT_BINARY
) ? 0 : 1;
188 if (cur_istext
!= istext
)
191 cygdrive_flags
|= MOUNT_BINARY
;
193 cygdrive_flags
&= ~MOUNT_BINARY
;
194 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, REG_DWORD
,
195 (BYTE
*) & cygdrive_flags
, sizeof (cygdrive_flags
));
200 get_cygdrive_flags (HKEY key
, DWORD
* cygdrive_flags
)
202 DWORD retvallen
= sizeof (*cygdrive_flags
);
203 LONG status
= RegQueryValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, 0,
204 (BYTE
*) cygdrive_flags
, &retvallen
);
209 default_cygdrive (HKEY key
)
211 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_PREFIX
, 0, REG_SZ
,
212 (BYTE
*) CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX
,
213 strlen (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX
) + 1);
214 DWORD cygdrive_flags
= MOUNT_AUTO
;
215 RegSetValueEx (key
, CYGWIN_INFO_CYGDRIVE_FLAGS
, 0, REG_DWORD
,
216 (BYTE
*) & cygdrive_flags
, sizeof (cygdrive_flags
));
217 return cygdrive_flags
;
221 set_cygdrive_flags (int istext
, int issystem
)
223 int found_system
= 0;
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
);
235 LONG status
= RegCreateKeyEx (HKEY_LOCAL_MACHINE
, buf
, 0, 0, 0,
236 KEY_ALL_ACCESS
, 0, &key
, &disposition
);
237 if (status
== ERROR_SUCCESS
)
239 DWORD cygdrive_flags
= 0;
240 status
= get_cygdrive_flags (key
, &cygdrive_flags
);
241 if (status
== ERROR_FILE_NOT_FOUND
)
243 status
= ERROR_SUCCESS
;
244 cygdrive_flags
= default_cygdrive (key
);
246 if (status
== ERROR_SUCCESS
)
248 set_cygdrive_flags (key
, istext
, cygdrive_flags
);
258 RegCreateKeyEx (HKEY_CURRENT_USER
, buf
, 0, 0, 0, KEY_ALL_ACCESS
,
259 0, &key
, &disposition
);
260 if (status
!= ERROR_SUCCESS
)
261 fatal ("set_cygdrive_flags");
263 DWORD cygdrive_flags
= 0;
264 status
= get_cygdrive_flags (key
, &cygdrive_flags
);
265 if (status
== ERROR_FILE_NOT_FOUND
&& !found_system
)
267 cygdrive_flags
= default_cygdrive (key
);
268 status
= ERROR_SUCCESS
;
271 if (status
== ERROR_SUCCESS
)
272 set_cygdrive_flags (key
, istext
, cygdrive_flags
);
278 in_table (struct mnt
*m
)
280 for (struct mnt
* m1
= mount_table
; m1
< m
; m1
++)
281 if (m1
->posix
.casecompare (m
->posix
) == 0)
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.
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
)
302 // Get the process token for the current process
304 BOOL status
= OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &token
);
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
);
313 GetTokenInformation (token
, TokenGroups
, token_info
, token_info_len
,
319 // Create the Administrators group SID
321 SID_IDENTIFIER_AUTHORITY authority
= { SECURITY_NT_AUTHORITY
};
323 AllocateAndInitializeSid (&authority
, 2, SECURITY_BUILTIN_DOMAIN_RID
,
324 DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0,
329 // Check to see if the user is a member of the Administrators group
331 for (UINT i
= 0; i
< groups
->GroupCount
; i
++)
333 if (EqualSid (groups
->Groups
[i
].Sid
, admin_sid
))
340 // Destroy the Administrators group SID
343 // Return whether or not the user is a member of the Administrators group
350 DWORD posix_path_size
;
352 struct mnt
*m
= mount_table
;
357 for (mnt
* m1
= mount_table
; m1
->posix
.size (); m1
++)
359 m1
->posix
= String (); //empty string;
360 m1
->native
= String ();
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
++)
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
);
374 HKEY key
= issystem
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
375 if (RegCreateKeyEx (key
, buf
, 0, (char *)"Cygwin", 0, KEY_ALL_ACCESS
,
376 0, &key
, &disposition
) != ERROR_SUCCESS
)
378 for (int i
= 0;; i
++, m
++)
380 char aBuffer
[MAX_PATH
+ 1];
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. */
385 res
= RegEnumKeyEx (key
, i
, aBuffer
, &posix_path_size
, NULL
,
388 if (res
== ERROR_NO_MORE_ITEMS
)
390 m
->posix
= String ();
393 m
->posix
= String (aBuffer
);
395 if (!m
->posix
.size () || in_table (m
))
397 else if (res
!= ERROR_SUCCESS
)
401 m
->native
= find2 (key
, &m
->istext
, m
->posix
);
402 if (!m
->native
.size ())
409 root_text
= IDC_ROOT_TEXT
;
411 root_text
= IDC_ROOT_BINARY
;
413 root_scope
= IDC_ROOT_SYSTEM
;
415 root_scope
= IDC_ROOT_USER
;
420 m
->posix
= String ();
429 m
->posix
= String ("/");
430 char windir
[_MAX_PATH
];
431 root_text
= IDC_ROOT_BINARY
;
432 root_scope
= (is_admin ())? IDC_ROOT_SYSTEM
: IDC_ROOT_USER
;
433 GetWindowsDirectory (windir
, sizeof (windir
));
435 set_root_dir (String (windir
) + "\\cygwin");
441 set_root_dir (String
const val
)
443 root_here
->native
= val
;
449 return root_here
? root_here
->native
: String ();
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.
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
466 path_prefix_p (String
const path1
, String
const path2
)
468 size_t len1
= path1
.size ();
469 /* Handle case where PATH1 has trailing '/' and when it doesn't. */
470 if (len1
> 0 && SLASH_P (path1
.cstr_oneuse ()[len1
- 1]))
474 return SLASH_P (path2
.cstr_oneuse ()[0])
475 && !SLASH_P (path2
.cstr_oneuse ()[1]);
477 if (path1
.casecompare (path2
, len1
) != 0)
480 return SLASH_P (path2
.cstr_oneuse ()[len1
]) || path2
.size () == len1
481 || path1
.cstr_oneuse ()[len1
- 1] == ':';
485 cygpath (String
const &thePath
)
488 struct mnt
*m
, *match
= NULL
;
489 for (m
= mount_table
; m
->posix
.size (); m
++)
491 size_t n
= m
->posix
.size ();
492 if (n
<= max_len
|| !path_prefix_p (m
->posix
, thePath
))
502 if (max_len
== thePath
.size ())
504 native
= match
->native
;
507 native
= match
->native
+ "/" + String (thePath
.cstr_oneuse() + max_len
);