Added translation using Weblate (Italian)
[cygwin-setup.git] / mount.cc
bloba38f52ce11f5ac49c54a4cdf8f3361ca6482325c
1 /*
2 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3 * 2010, 2013 Red Hat, Inc.
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.
10 * A copy of the GNU General Public License can be found at
11 * http://www.gnu.org/
13 * Written by DJ Delorie <dj@cygnus.com>
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. */
21 #include "ini.h"
22 #include "win32.h"
23 #include "filemanip.h"
24 #include "LogSingleton.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <malloc.h>
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
34 #define CYGWIN_INFO_CYGWIN_REGISTRY_NAME "Cygwin"
35 #define CYGWIN_INFO_CYGWIN_SETUP_REGISTRY_NAME "setup"
37 // #include "../cygwin/include/sys/mount.h"
39 // KEEP SYNCHRONISED WITH /src/winsup/cygwin/include/sys/mount.h
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
44 enum
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 */
55 // int mount (const char *, const char *, unsigned __flags);
56 // int umount (const char *);
57 // int cygwin_umount (const char *__path, unsigned __flags);
59 #ifdef __cplusplus
61 #endif
65 #include "mount.h"
66 #include "msg.h"
67 #include "resource.h"
68 #include "dialog.h"
69 #include "state.h"
71 #ifdef MAINTAINER_FEATURES
72 #include "getopt++/GetOption.h"
73 #include "getopt++/StringOption.h"
74 static StringOption CygwinRegistryNameOption (CYGWIN_INFO_CYGWIN_REGISTRY_NAME, '#', "override-registry-name", "Override registry name to allow parallel installs for testing purposes", false);
75 #undef CYGWIN_INFO_CYGWIN_REGISTRY_NAME
76 #define CYGWIN_INFO_CYGWIN_REGISTRY_NAME (((std::string)CygwinRegistryNameOption).c_str())
77 #endif
79 /* Used when treating / and \ as equivalent. */
80 #define SLASH_P(ch) \
81 ({ \
82 char __c = (ch); \
83 ((__c) == '/' || (__c) == '\\'); \
86 static struct mnt
88 std::string native;
89 std::string posix;
90 int istext;
92 mount_table[255];
94 struct mnt *root_here = NULL;
96 void
97 create_install_root ()
99 char buf[1000];
100 HKEY key;
101 DWORD disposition;
102 DWORD rv;
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;
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;
116 Log (LOG_PLAIN) << "Access denied trying to create rootdir registry key"
117 << endLog;
118 kr = HKEY_CURRENT_USER;
120 while (rv == ERROR_ACCESS_DENIED);
121 if (rv == ERROR_SUCCESS)
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;
129 Log (LOG_PLAIN) << "Access denied trying to create rootdir registry value"
130 << endLog;
131 kr = HKEY_CURRENT_USER;
133 while (rv == ERROR_ACCESS_DENIED);
134 if (rv != ERROR_SUCCESS)
135 mbox (NULL, IDS_MOUNT_REGISTRY_KEY_FAILED, MB_OK | MB_ICONWARNING);
136 RegCloseKey (key);
138 Log (LOG_TIMESTAMP) << "Registry value set: HKEY_"
139 << (root_scope == IDC_ROOT_USER ? "CURRENT_USER\\"
140 : "LOCAL_MACHINE\\")
141 << buf << "\\rootdir = \"" << get_root_dir () << "\""
142 << endLog;
145 inline char *
146 unconvert_slashes (char *in_name)
148 char *name = in_name;
149 while ((name = strchr (name, '/')) != NULL)
150 *name++ = '\\';
151 return in_name;
154 inline char *
155 skip_ws (char *in)
157 while (*in == ' ' || *in == '\t')
158 ++in;
159 return in;
162 inline char *
163 find_ws (char *in)
165 while (*in && *in != ' ' && *in != '\t')
166 ++in;
167 return in;
170 inline char *
171 conv_fstab_spaces (char *field)
173 register char *sp = field;
174 while ((sp = strstr (sp, "\\040")))
176 *sp++ = ' ';
177 memmove (sp, sp + 3, strlen (sp + 3) + 1);
179 return field;
182 static bool got_usr_bin;
183 static bool got_usr_lib;
185 static bool
186 from_fstab_line (mnt *m, char *line)
188 char *native_path, *posix_path, *fs_type;
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;
212 if (strcmp (fs_type, "cygdrive"))
214 for (mnt *sm = mount_table; sm < m; ++sm)
215 if (sm->posix == std::string (posix_path))
217 sm->native = std::string (unconvert_slashes (native_path));
218 return false;
220 m->posix = std::string (posix_path);
221 m->native = std::string (unconvert_slashes (native_path));
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;
227 return true;
230 #define BUFSIZE 65536
231 #define LFSTAB L"\\etc\\fstab"
233 static bool
234 from_fstab (mnt *m, const std::string& in_path)
236 char buf[BUFSIZE];
237 WCHAR path[in_path.size () + sizeof (LFSTAB)];
239 mklongpath (path, in_path.c_str (), sizeof (path) / sizeof (WCHAR));
240 wcscat (path, LFSTAB);
241 HANDLE h = CreateFileW (path, GENERIC_READ, FILE_SHARE_READ, NULL,
242 OPEN_EXISTING,
243 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
244 NULL);
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))
252 char *end;
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')))
262 end[end[-1] == '\r' ? -1 : 0] = '\0';
263 if (from_fstab_line (m, got))
264 ++m;
265 got = end + 1;
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';
277 if (got > buf && from_fstab_line (m, got))
278 ++m;
279 CloseHandle (h);
280 return true;
283 static void
284 add_usr_mnts (struct mnt *m)
286 /* Set default /usr/bin and /usr/lib */
287 if (!got_usr_bin)
289 m->posix = "/usr/bin";
290 m->native = root_here->native + "\\bin";
291 ++m;
293 if (!got_usr_lib)
295 m->posix = "/usr/lib";
296 m->native = root_here->native + "\\lib";
300 void
301 read_mounts (const std::string val)
303 DWORD posix_path_size;
304 struct mnt *m = mount_table;
305 char buf[10000];
307 root_here = NULL;
308 for (mnt * m1 = mount_table; m1->posix.size (); m1++)
310 m1->posix.clear();
311 m1->native.clear();
313 got_usr_bin = got_usr_lib = false;
315 if (val.size ())
317 /* Cygwin rootdir always < MAX_PATH. */
318 char rootdir[MAX_PATH + 1];
320 if (GetFullPathName (val.c_str (), MAX_PATH + 1, rootdir, NULL))
322 m->native = rootdir;
323 m->posix = "/";
324 root_here = m;
325 add_usr_mnts (++m);
328 else
330 /* Always check HKEY_LOCAL_MACHINE first. */
331 for (int isuser = 0; isuser <= 1; isuser++)
333 snprintf (buf, sizeof(buf), "Software\\%s\\%s",
334 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
335 CYGWIN_INFO_CYGWIN_SETUP_REGISTRY_NAME);
336 HKEY key = isuser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
337 if (RegOpenKeyEx (key, buf, 0, KEY_ALL_ACCESS | SETUP_KEY_WOW64,
338 &key) != ERROR_SUCCESS)
339 continue;
340 DWORD type;
341 /* Cygwin rootdir always < MAX_PATH. */
342 char aBuffer[MAX_PATH + 1];
343 posix_path_size = MAX_PATH;
344 if (RegQueryValueEx
345 (key, "rootdir", 0, &type, (BYTE *) aBuffer,
346 &posix_path_size) == ERROR_SUCCESS)
348 m->native = std::string (aBuffer);
349 m->posix = "/";
350 root_here = m++;
351 from_fstab (m, root_here->native);
352 add_usr_mnts (m);
353 break;
355 RegCloseKey (key);
359 if (!root_here)
361 /* Affected path always < MAX_PATH. */
362 char windir[MAX_PATH];
363 GetSystemWindowsDirectory (windir, sizeof (windir));
364 windir[2] = 0;
365 m->native = std::string (windir) + (is_64bit ? "\\cygwin64" : "\\cygwin");
366 m->posix = "/";
367 root_here = m;
368 add_usr_mnts (++m);
372 // set default root_scope: USER if only HKEY_CURRENT_USER registry key exists,
373 // otherwise SYSTEM.
374 void set_default_root_scope()
376 root_scope = IDC_ROOT_SYSTEM;
378 char buf[10000];
379 for (int isuser = 0; isuser <= 1; isuser++)
381 snprintf (buf, sizeof(buf), "Software\\%s\\%s",
382 CYGWIN_INFO_CYGWIN_REGISTRY_NAME,
383 CYGWIN_INFO_CYGWIN_SETUP_REGISTRY_NAME);
384 HKEY key = isuser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
385 if (RegOpenKeyEx (key, buf, 0, KEY_ALL_ACCESS | SETUP_KEY_WOW64,
386 &key) == ERROR_SUCCESS)
388 RegCloseKey (key);
389 root_scope = isuser ? IDC_ROOT_USER : IDC_ROOT_SYSTEM;
390 break;
395 void
396 set_root_dir (const std::string val)
398 read_mounts (val);
401 static std::string empty;
403 const std::string &
404 get_root_dir ()
406 return root_here ? root_here->native : empty;
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.
411 Neither may be "".
413 Examples:
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
422 static int
423 path_prefix_p (const std::string path1, const std::string 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.c_str ()[len1 - 1]))
428 --len1;
430 if (len1 == 0)
431 return SLASH_P (path2.c_str ()[0])
432 && !SLASH_P (path2.c_str ()[1]);
434 if (casecompare(path1, path2, len1) != 0)
435 return 0;
437 return SLASH_P (path2.c_str ()[len1]) || path2.size () == len1
438 || path1.c_str ()[len1 - 1] == ':';
441 std::string
442 cygpath (const std::string& thePath)
444 size_t max_len = 0;
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))
450 continue;
451 max_len = n;
452 match = m;
455 if (!match)
456 return std::string();
458 std::string native;
459 if (max_len == thePath.size ())
461 native = match->native;
463 else if (match->posix.size () > 1)
464 native = match->native + thePath.substr(max_len, std::string::npos);
465 else
466 native = match->native + "/" + thePath.substr(max_len, std::string::npos);
467 return native;