]> cygwin.com Git - cygwin-apps/setup.git/blame - mount.cc
Make PrereqChecker::setTrust() a static method
[cygwin-apps/setup.git] / mount.cc
CommitLineData
23c9e63c 1/*
c6263b96
CV
2 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3 * 2010, 2013 Red Hat, Inc.
23c9e63c
DD
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * A copy of the GNU General Public License can be found at
11 * http://www.gnu.org/
12 *
13 * Written by DJ Delorie <dj@cygnus.com>
14 *
15 */
16
17/* The purpose of this file is to hide all the details about accessing
18 Cygwin's mount table. If the format or location of the mount table
19 changes, this is the file to change to match it. */
20
558484cc 21#include "ini.h"
23c9e63c 22#include "win32.h"
65288dc7 23#include "filemanip.h"
507e5b52 24#include "LogSingleton.h"
23c9e63c
DD
25
26#include <stdio.h>
a351e48c 27#include <stdlib.h>
2cae901b 28#include <malloc.h>
db04fc41
RC
29
30// These headers aren't available outside the winsup tree
31// #include "../cygwin/include/cygwin/version.h"
32// KEEP SYNCHRONISED WITH /src/winsup/cygwin/include/cygwin/version.h
33
db04fc41 34#define CYGWIN_INFO_CYGWIN_REGISTRY_NAME "Cygwin"
2f0315ad 35#define CYGWIN_INFO_CYGWIN_SETUP_REGISTRY_NAME "setup"
db04fc41
RC
36
37// #include "../cygwin/include/sys/mount.h"
38
39// KEEP SYNCHRONISED WITH /src/winsup/cygwin/include/sys/mount.h
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44enum
45{
46 MOUNT_SYMLINK = 0x001, /* "mount point" is a symlink */
47 MOUNT_BINARY = 0x002, /* "binary" format read/writes */
48 MOUNT_SYSTEM = 0x008, /* mount point came from system table */
49 MOUNT_EXEC = 0x010, /* Any file in the mounted directory gets 'x' bit */
50 MOUNT_AUTO = 0x020, /* mount point refers to auto device mount */
51 MOUNT_CYGWIN_EXEC = 0x040, /* file or directory is or contains a cygwin executable */
52 MOUNT_MIXED = 0x080, /* reads are text, writes are binary */
53};
54
55// int mount (const char *, const char *, unsigned __flags);
56// int umount (const char *);
57// int cygwin_umount (const char *__path, unsigned __flags);
58
59#ifdef __cplusplus
60};
61#endif
62
63
23c9e63c
DD
64
65#include "mount.h"
66#include "msg.h"
67#include "resource.h"
68#include "dialog.h"
a351e48c 69#include "state.h"
23c9e63c 70
4f618d88
MB
71#ifdef MAINTAINER_FEATURES
72#include "getopt++/GetOption.h"
73#include "getopt++/StringOption.h"
9d53f045 74static StringOption CygwinRegistryNameOption (CYGWIN_INFO_CYGWIN_REGISTRY_NAME, '#', "override-registry-name", "Override registry name to allow parallel installs for testing purposes", false);
4f618d88
MB
75#undef CYGWIN_INFO_CYGWIN_REGISTRY_NAME
76#define CYGWIN_INFO_CYGWIN_REGISTRY_NAME (((std::string)CygwinRegistryNameOption).c_str())
77#endif
78
1ac649ed
RC
79/* Used when treating / and \ as equivalent. */
80#define SLASH_P(ch) \
81 ({ \
82 char __c = (ch); \
83 ((__c) == '/' || (__c) == '\\'); \
84 })
85
a351e48c 86static struct mnt
b24c88b3 87{
2bba98e8
MB
88 std::string native;
89 std::string posix;
b24c88b3
RC
90 int istext;
91}
92mount_table[255];
23c9e63c 93
85b43844
CF
94struct mnt *root_here = NULL;
95
a351e48c 96void
2f0315ad
CV
97create_install_root ()
98{
99 char buf[1000];
100 HKEY key;
101 DWORD disposition;
102 DWORD rv;
103
104 snprintf (buf, sizeof(buf), "Software\\%s\\%s",
105 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
106 CYGWIN_INFO_CYGWIN_SETUP_REGISTRY_NAME);
107 HKEY kr = (root_scope == IDC_ROOT_USER) ? HKEY_CURRENT_USER
108 : HKEY_LOCAL_MACHINE;
507e5b52
CV
109 do
110 {
111 rv = RegCreateKeyEx (kr, buf, 0, (char *)"Cygwin", 0,
112 KEY_ALL_ACCESS | SETUP_KEY_WOW64,
113 0, &key, &disposition);
114 if (rv != ERROR_ACCESS_DENIED || kr != HKEY_LOCAL_MACHINE)
115 break;
157dc2b8 116 Log (LOG_PLAIN) << "Access denied trying to create rootdir registry key"
507e5b52
CV
117 << endLog;
118 kr = HKEY_CURRENT_USER;
119 }
120 while (rv == ERROR_ACCESS_DENIED);
121 if (rv == ERROR_SUCCESS)
122 do
123 {
124 rv = RegSetValueEx (key, "rootdir", 0, REG_SZ,
125 (BYTE *) get_root_dir ().c_str (),
126 get_root_dir ().size () + 1);
127 if (rv != ERROR_ACCESS_DENIED || kr != HKEY_LOCAL_MACHINE)
128 break;
157dc2b8 129 Log (LOG_PLAIN) << "Access denied trying to create rootdir registry value"
507e5b52
CV
130 << endLog;
131 kr = HKEY_CURRENT_USER;
132 }
133 while (rv == ERROR_ACCESS_DENIED);
2f0315ad 134 if (rv != ERROR_SUCCESS)
e0373ab5 135 mbox (NULL, "Couldn't create registry key\n"
507e5b52
CV
136 "to store installation path",
137 "Cygwin Setup", MB_OK | MB_ICONWARNING);
2f0315ad
CV
138 RegCloseKey (key);
139
b0bb51b4
CV
140 // The mount table is already in the right shape at this point.
141 // Reading it again is not necessary.
142 //read_mounts (std::string ());
2f0315ad
CV
143}
144
65288dc7
CV
145inline char *
146unconvert_slashes (char *in_name)
147{
148 char *name = in_name;
149 while ((name = strchr (name, '/')) != NULL)
150 *name++ = '\\';
151 return in_name;
152}
153
154inline char *
155skip_ws (char *in)
156{
157 while (*in == ' ' || *in == '\t')
158 ++in;
159 return in;
160}
161
162inline char *
163find_ws (char *in)
164{
165 while (*in && *in != ' ' && *in != '\t')
166 ++in;
167 return in;
168}
169
170inline char *
171conv_fstab_spaces (char *field)
172{
173 register char *sp = field;
ef3be327 174 while ((sp = strstr (sp, "\\040")))
65288dc7
CV
175 {
176 *sp++ = ' ';
177 memmove (sp, sp + 3, strlen (sp + 3) + 1);
178 }
179 return field;
180}
181
d2e8d256
CV
182static bool got_usr_bin;
183static bool got_usr_lib;
184
65288dc7
CV
185static bool
186from_fstab_line (mnt *m, char *line)
187{
188 char *native_path, *posix_path, *fs_type;
189
190 /* First field: Native path. */
191 char *c = skip_ws (line);
192 if (!*c || *c == '#')
193 return false;
194 char *cend = find_ws (c);
195 *cend = '\0';
196 native_path = conv_fstab_spaces (c);
197 /* Second field: POSIX path. */
198 c = skip_ws (cend + 1);
199 if (!*c)
200 return false;
201 cend = find_ws (c);
202 *cend = '\0';
203 posix_path = conv_fstab_spaces (c);
204 /* Third field: FS type. */
205 c = skip_ws (cend + 1);
206 if (!*c)
207 return false;
208 cend = find_ws (c);
209 *cend = '\0';
210 fs_type = c;
211
212 if (strcmp (fs_type, "cygdrive"))
213 {
214 for (mnt *sm = mount_table; sm < m; ++sm)
215 if (sm->posix == std::string (posix_path))
216 {
217 sm->native = std::string (unconvert_slashes (native_path));
218 return false;
219 }
220 m->posix = std::string (posix_path);
221 m->native = std::string (unconvert_slashes (native_path));
d2e8d256
CV
222 if (!strcmp (posix_path, "/usr/bin"))
223 got_usr_bin = true;
224 else if (!strcmp (posix_path, "/usr/lib"))
225 got_usr_lib = true;
65288dc7
CV
226 }
227 return true;
228}
229
230#define BUFSIZE 65536
8669c59a 231#define LFSTAB L"\\etc\\fstab"
65288dc7
CV
232
233static bool
5524f268 234from_fstab (mnt *m, const std::string& in_path)
65288dc7
CV
235{
236 char buf[BUFSIZE];
8669c59a 237 WCHAR path[in_path.size () + sizeof (LFSTAB)];
65288dc7 238
8669c59a
CF
239 mklongpath (path, in_path.c_str (), sizeof (path) / sizeof (WCHAR));
240 wcscat (path, LFSTAB);
65288dc7 241 HANDLE h = CreateFileW (path, GENERIC_READ, FILE_SHARE_READ, NULL,
b41c2908
CV
242 OPEN_EXISTING,
243 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
244 NULL);
65288dc7
CV
245 if (h == INVALID_HANDLE_VALUE)
246 return false;
247 char *got = buf;
248 DWORD len = 0;
249 /* Using BUFSIZE-2 leaves space to append two \0. */
250 while (ReadFile (h, got, BUFSIZE - 2 - (got - buf), &len, NULL))
251 {
252 char *end;
253
254 /* Set end marker. */
255 got[len] = got[len + 1] = '\0';
256 /* Set len to the absolute len of bytes in buf. */
257 len += got - buf;
258 /* Reset got to start reading at the start of the buffer again. */
259 got = buf;
260 while (got < buf + len && (end = strchr (got, '\n')))
261 {
262 end[end[-1] == '\r' ? -1 : 0] = '\0';
263 if (from_fstab_line (m, got))
264 ++m;
265 got = end + 1;
266 }
267 if (len < BUFSIZE - 1)
268 break;
269 /* We have to read once more. Move remaining bytes to the start of
270 the buffer and reposition got so that it points to the end of
271 the remaining bytes. */
272 len = buf + len - got;
273 memmove (buf, got, len);
274 got = buf + len;
275 buf[len] = buf[len + 1] = '\0';
276 }
277 if (got > buf && from_fstab_line (m, got))
278 ++m;
279 CloseHandle (h);
280 return true;
281}
282
2f0315ad
CV
283static void
284add_usr_mnts (struct mnt *m)
285{
286 /* Set default /usr/bin and /usr/lib */
d2e8d256
CV
287 if (!got_usr_bin)
288 {
289 m->posix = "/usr/bin";
290 m->native = root_here->native + "\\bin";
291 ++m;
292 }
293 if (!got_usr_lib)
294 {
295 m->posix = "/usr/lib";
296 m->native = root_here->native + "\\lib";
297 }
2f0315ad
CV
298}
299
1e029da2
YS
300void
301read_mounts (const std::string val)
2f0315ad
CV
302{
303 DWORD posix_path_size;
304 struct mnt *m = mount_table;
2f0315ad
CV
305 char buf[10000];
306
307 root_here = NULL;
308 for (mnt * m1 = mount_table; m1->posix.size (); m1++)
309 {
310 m1->posix.clear();
311 m1->native.clear();
312 }
d2e8d256 313 got_usr_bin = got_usr_lib = false;
2f0315ad 314
507e5b52 315 root_scope = (nt_sec.isRunAsAdmin ())? IDC_ROOT_SYSTEM : IDC_ROOT_USER;
2f0315ad
CV
316
317 if (val.size ())
318 {
a9a8e93a
CV
319 /* Cygwin rootdir always < MAX_PATH. */
320 char rootdir[MAX_PATH + 1];
321
322 if (GetFullPathName (val.c_str (), MAX_PATH + 1, rootdir, NULL))
323 {
324 m->native = rootdir;
325 m->posix = "/";
326 root_here = m;
327 add_usr_mnts (++m);
328 }
2f0315ad
CV
329 }
330 else
331 {
332 /* Always check HKEY_LOCAL_MACHINE first. */
333 for (int isuser = 0; isuser <= 1; isuser++)
334 {
335 snprintf (buf, sizeof(buf), "Software\\%s\\%s",
336 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
337 CYGWIN_INFO_CYGWIN_SETUP_REGISTRY_NAME);
338 HKEY key = isuser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
9fadc65f
CV
339 if (RegOpenKeyEx (key, buf, 0, KEY_ALL_ACCESS | SETUP_KEY_WOW64,
340 &key) != ERROR_SUCCESS)
b0bb51b4 341 continue;
2f0315ad 342 DWORD type;
7cc4d95e 343 /* Cygwin rootdir always < MAX_PATH. */
2f0315ad
CV
344 char aBuffer[MAX_PATH + 1];
345 posix_path_size = MAX_PATH;
346 if (RegQueryValueEx
347 (key, "rootdir", 0, &type, (BYTE *) aBuffer,
348 &posix_path_size) == ERROR_SUCCESS)
349 {
350 m->native = std::string (aBuffer);
351 m->posix = "/";
352 root_scope = isuser ? IDC_ROOT_USER : IDC_ROOT_SYSTEM;
65288dc7 353 root_here = m++;
d2e8d256
CV
354 from_fstab (m, root_here->native);
355 add_usr_mnts (m);
2f0315ad
CV
356 break;
357 }
358 RegCloseKey (key);
359 }
360 }
361
2f0315ad
CV
362 if (!root_here)
363 {
7cc4d95e 364 /* Affected path always < MAX_PATH. */
2f0315ad 365 char windir[MAX_PATH];
7cc4d95e 366 GetSystemWindowsDirectory (windir, sizeof (windir));
2f0315ad 367 windir[2] = 0;
e49fef4d 368 m->native = std::string (windir) + (is_64bit ? "\\cygwin64" : "\\cygwin");
2f0315ad
CV
369 m->posix = "/";
370 root_here = m;
371 add_usr_mnts (++m);
372 }
373}
374
85b43844 375void
2bba98e8 376set_root_dir (const std::string val)
85b43844 377{
1e029da2 378 read_mounts (val);
85b43844
CF
379}
380
d396ed10
CV
381static std::string empty;
382
383const std::string &
85b43844
CF
384get_root_dir ()
385{
d396ed10 386 return root_here ? root_here->native : empty;
85b43844
CF
387}
388
a351e48c
CF
389/* Return non-zero if PATH1 is a prefix of PATH2.
390 Both are assumed to be of the same path style and / vs \ usage.
391 Neither may be "".
a351e48c
CF
392
393 Examples:
394 /foo/ is a prefix of /foo <-- may seem odd, but desired
395 /foo is a prefix of /foo/
396 / is a prefix of /foo/bar
397 / is not a prefix of foo/bar
398 foo/ is a prefix foo/bar
399 /foo is not a prefix of /foobar
400*/
401
402static int
2bba98e8 403path_prefix_p (const std::string path1, const std::string path2)
a351e48c 404{
3c054baf 405 size_t len1 = path1.size ();
a351e48c 406 /* Handle case where PATH1 has trailing '/' and when it doesn't. */
d2a3615c 407 if (len1 > 0 && SLASH_P (path1.c_str ()[len1 - 1]))
3c054baf 408 --len1;
a351e48c
CF
409
410 if (len1 == 0)
d2a3615c
MB
411 return SLASH_P (path2.c_str ()[0])
412 && !SLASH_P (path2.c_str ()[1]);
a351e48c 413
afa76033 414 if (casecompare(path1, path2, len1) != 0)
a351e48c
CF
415 return 0;
416
d2a3615c
MB
417 return SLASH_P (path2.c_str ()[len1]) || path2.size () == len1
418 || path1.c_str ()[len1 - 1] == ':';
a351e48c
CF
419}
420
2bba98e8
MB
421std::string
422cygpath (const std::string& thePath)
a351e48c 423{
3c054baf 424 size_t max_len = 0;
b24c88b3 425 struct mnt *m, *match = NULL;
3c054baf 426 for (m = mount_table; m->posix.size (); m++)
a351e48c 427 {
3c054baf
RC
428 size_t n = m->posix.size ();
429 if (n <= max_len || !path_prefix_p (m->posix, thePath))
a351e48c
CF
430 continue;
431 max_len = n;
432 match = m;
433 }
434
b24c88b3 435 if (!match)
2bba98e8 436 return std::string();
b24c88b3 437
2bba98e8 438 std::string native;
3c054baf
RC
439 if (max_len == thePath.size ())
440 {
441 native = match->native;
442 }
2f0315ad
CV
443 else if (match->posix.size () > 1)
444 native = match->native + thePath.substr(max_len, std::string::npos);
a351e48c 445 else
2bba98e8 446 native = match->native + "/" + thePath.substr(max_len, std::string::npos);
a351e48c
CF
447 return native;
448}
This page took 0.122914 seconds and 5 git commands to generate.