2001-11-11 07:07:36 +01:00
|
|
|
/* path.cc
|
|
|
|
|
|
|
|
This file is part of Cygwin.
|
|
|
|
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
|
|
details. */
|
2001-11-11 04:06:59 +01:00
|
|
|
|
|
|
|
/* The purpose of this file is to hide all the details about accessing
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
Cygwin's mount table, shortcuts, etc. If the format or location of
|
|
|
|
the mount table, or the shortcut format changes, this is the file to
|
|
|
|
change to match it. */
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2003-09-11 04:00:42 +02:00
|
|
|
#define str(a) #a
|
|
|
|
#define scat(a,b) str(a##b)
|
2001-11-11 04:06:59 +01:00
|
|
|
#include <windows.h>
|
2008-04-22 16:42:05 +02:00
|
|
|
#include <lmcons.h>
|
2001-11-11 04:06:59 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2008-03-16 18:04:02 +01:00
|
|
|
#include <malloc.h>
|
2008-04-22 16:42:05 +02:00
|
|
|
#include <wchar.h>
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
#include "path.h"
|
2012-10-24 12:15:27 +02:00
|
|
|
#include "../cygwin/include/cygwin/version.h"
|
Cygwin: path_conv: decouple path_types from mount types
- Remove another unfortunate amalgamation: Mount flags (MOUNT_xxx)
are converted to path_types (PATH_xxx) and mixed with non-mount
path_types flags in the same storage, leading to a tangled,
pell-mell usage of mount flags and path flags in path_conv and
symlink_info.
- There's also the case of PC_NONULLEMPTY. It's used in exactly
one place with a path_conv constructor only used in this single
place, just to override the automatic PC_NULLEMPTY addition
when calling the other path_conv constructors. Crazily,
PC_NONULLEMPTY is a define, no path_types flag, despite its
name.
- It doesn't help that the binary flag exists as mount and path
flag, while the text flag only exists as path flag. This leads
to mount code using path flags to set text/binary. Very confusing
is the fact that a text mount/path flag is not actually required;
the mount code sets the text flag on non binary mounts anyway, so
there are only two states. However, to puzzle people a bit more,
path_conv::binary wrongly implies there's a third, non-binary/non-text
state.
Clean up this mess:
- Store path flags separately from mount flags in path_conv and
symlink_info classes and change all checks and testing inline
methods accordingly.
- Make PC_NONULLEMPTY a simple path_types flag and drop the
redundant path_check constructor.
- Clean up the definition of pathconv_arg, path_types, and mount flags.
Use _BIT expression, newly define in cygwin/bits.h.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2019-01-06 17:44:20 +01:00
|
|
|
#include "../cygwin/include/cygwin/bits.h"
|
2012-10-24 12:15:27 +02:00
|
|
|
#include "../cygwin/include/sys/mount.h"
|
2013-04-23 11:44:36 +02:00
|
|
|
#define _NOMNTENT_MACROS
|
2012-10-24 12:15:27 +02:00
|
|
|
#include "../cygwin/include/mntent.h"
|
2008-03-09 05:10:10 +01:00
|
|
|
#include "testsuite.h"
|
2010-04-29 12:39:35 +02:00
|
|
|
#ifdef FSTAB_ONLY
|
|
|
|
#include <sys/cygwin.h>
|
|
|
|
#endif
|
2010-08-28 13:22:37 +02:00
|
|
|
#include "loadlib.h"
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2009-07-22 12:20:26 +02:00
|
|
|
#ifndef FSTAB_ONLY
|
2001-11-11 04:06:59 +01:00
|
|
|
/* Used when treating / and \ as equivalent. */
|
2007-06-04 03:57:16 +02:00
|
|
|
#define isslash(ch) \
|
2001-11-11 04:06:59 +01:00
|
|
|
({ \
|
|
|
|
char __c = (ch); \
|
|
|
|
((__c) == '/' || (__c) == '\\'); \
|
|
|
|
})
|
|
|
|
|
|
|
|
|
2008-09-13 00:43:10 +02:00
|
|
|
static const GUID GUID_shortcut =
|
|
|
|
{0x00021401L, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
|
|
|
|
enum {
|
|
|
|
WSH_FLAG_IDLIST = 0x01, /* Contains an ITEMIDLIST. */
|
|
|
|
WSH_FLAG_FILE = 0x02, /* Contains a file locator element. */
|
|
|
|
WSH_FLAG_DESC = 0x04, /* Contains a description. */
|
|
|
|
WSH_FLAG_RELPATH = 0x08, /* Contains a relative path. */
|
|
|
|
WSH_FLAG_WD = 0x10, /* Contains a working dir. */
|
|
|
|
WSH_FLAG_CMDLINE = 0x20, /* Contains command line args. */
|
|
|
|
WSH_FLAG_ICON = 0x40 /* Contains a custom icon. */
|
|
|
|
};
|
|
|
|
|
|
|
|
struct win_shortcut_hdr
|
|
|
|
{
|
|
|
|
DWORD size; /* Header size in bytes. Must contain 0x4c. */
|
|
|
|
GUID magic; /* GUID of shortcut files. */
|
|
|
|
DWORD flags; /* Content flags. See above. */
|
|
|
|
|
|
|
|
/* The next fields from attr to icon_no are always set to 0 in Cygwin
|
|
|
|
and U/Win shortcuts. */
|
|
|
|
DWORD attr; /* Target file attributes. */
|
|
|
|
FILETIME ctime; /* These filetime items are never touched by the */
|
|
|
|
FILETIME mtime; /* system, apparently. Values don't matter. */
|
|
|
|
FILETIME atime;
|
|
|
|
DWORD filesize; /* Target filesize. */
|
|
|
|
DWORD icon_no; /* Icon number. */
|
|
|
|
|
|
|
|
DWORD run; /* Values defined in winuser.h. Use SW_NORMAL. */
|
|
|
|
DWORD hotkey; /* Hotkey value. Set to 0. */
|
|
|
|
DWORD dummy[2]; /* Future extension probably. Always 0. */
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool
|
|
|
|
cmp_shortcut_header (win_shortcut_hdr *file_header)
|
|
|
|
{
|
|
|
|
/* A Cygwin or U/Win shortcut only contains a description and a relpath.
|
|
|
|
Cygwin shortcuts also might contain an ITEMIDLIST. The run type is
|
|
|
|
always set to SW_NORMAL. */
|
|
|
|
return file_header->size == sizeof (win_shortcut_hdr)
|
|
|
|
&& !memcmp (&file_header->magic, &GUID_shortcut, sizeof GUID_shortcut)
|
|
|
|
&& (file_header->flags & ~WSH_FLAG_IDLIST)
|
|
|
|
== (WSH_FLAG_DESC | WSH_FLAG_RELPATH)
|
|
|
|
&& file_header->run == SW_NORMAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
get_word (HANDLE fh, int offset)
|
|
|
|
{
|
|
|
|
unsigned short rv;
|
|
|
|
unsigned r;
|
|
|
|
|
|
|
|
SetLastError(NO_ERROR);
|
|
|
|
if (SetFilePointer (fh, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER
|
|
|
|
&& GetLastError () != NO_ERROR)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!ReadFile (fh, &rv, 2, (DWORD *) &r, 0))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check the value of GetLastError() to find out whether there was an error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
get_dword (HANDLE fh, int offset)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
unsigned r;
|
|
|
|
|
|
|
|
SetLastError(NO_ERROR);
|
|
|
|
if (SetFilePointer (fh, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER
|
|
|
|
&& GetLastError () != NO_ERROR)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!ReadFile (fh, &rv, 4, (DWORD *) &r, 0))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define EXE_MAGIC ((int)*(unsigned short *)"MZ")
|
|
|
|
#define SHORTCUT_MAGIC ((int)*(unsigned short *)"L\0")
|
|
|
|
#define SYMLINK_COOKIE "!<symlink>"
|
|
|
|
#define SYMLINK_MAGIC ((int)*(unsigned short *)SYMLINK_COOKIE)
|
|
|
|
|
|
|
|
bool
|
|
|
|
is_exe (HANDLE fh)
|
|
|
|
{
|
|
|
|
int magic = get_word (fh, 0x0);
|
|
|
|
return magic == EXE_MAGIC;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
is_symlink (HANDLE fh)
|
|
|
|
{
|
2013-07-07 18:57:11 +02:00
|
|
|
bool ret = false;
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
int magic = get_word (fh, 0x0);
|
|
|
|
if (magic != SHORTCUT_MAGIC && magic != SYMLINK_MAGIC)
|
2013-07-07 18:57:11 +02:00
|
|
|
goto out;
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
DWORD got;
|
|
|
|
BY_HANDLE_FILE_INFORMATION local;
|
|
|
|
if (!GetFileInformationByHandle (fh, &local))
|
|
|
|
return false;
|
|
|
|
if (magic == SHORTCUT_MAGIC)
|
|
|
|
{
|
|
|
|
DWORD size;
|
|
|
|
if (!local.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
2013-07-07 18:57:11 +02:00
|
|
|
goto out; /* Not a Cygwin symlink. */
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
if ((size = GetFileSize (fh, NULL)) > 8192)
|
2013-07-07 18:57:11 +02:00
|
|
|
goto out; /* Not a Cygwin symlink. */
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
char buf[size];
|
|
|
|
SetFilePointer (fh, 0, 0, FILE_BEGIN);
|
|
|
|
if (!ReadFile (fh, buf, size, &got, 0))
|
2013-07-07 18:57:11 +02:00
|
|
|
goto out;
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
if (got != size || !cmp_shortcut_header ((win_shortcut_hdr *) buf))
|
2013-07-07 18:57:11 +02:00
|
|
|
goto out; /* Not a Cygwin symlink. */
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
/* TODO: check for invalid path contents
|
2007-06-04 03:57:16 +02:00
|
|
|
(see symlink_info::check() in ../cygwin/path.cc) */
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
}
|
|
|
|
else /* magic == SYMLINK_MAGIC */
|
|
|
|
{
|
2016-10-22 22:44:25 +02:00
|
|
|
if (!(local.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
|
2013-07-07 18:57:11 +02:00
|
|
|
goto out; /* Not a Cygwin symlink. */
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
char buf[sizeof (SYMLINK_COOKIE) - 1];
|
|
|
|
SetFilePointer (fh, 0, 0, FILE_BEGIN);
|
|
|
|
if (!ReadFile (fh, buf, sizeof (buf), &got, 0))
|
2013-07-07 18:57:11 +02:00
|
|
|
goto out;
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
if (got != sizeof (buf) ||
|
2007-06-04 03:57:16 +02:00
|
|
|
memcmp (buf, SYMLINK_COOKIE, sizeof (buf)) != 0)
|
2013-07-07 18:57:11 +02:00
|
|
|
goto out; /* Not a Cygwin symlink. */
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
}
|
2013-07-07 18:57:11 +02:00
|
|
|
ret = true;
|
|
|
|
out:
|
|
|
|
SetFilePointer (fh, 0, 0, FILE_BEGIN);
|
|
|
|
return ret;
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Assumes is_symlink(fh) is true */
|
|
|
|
bool
|
2018-08-08 09:25:12 +02:00
|
|
|
readlink (HANDLE fh, char *path, size_t maxlen)
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
{
|
2008-03-16 18:04:02 +01:00
|
|
|
DWORD rv;
|
|
|
|
char *buf, *cp;
|
|
|
|
unsigned short len;
|
|
|
|
win_shortcut_hdr *file_header;
|
|
|
|
BY_HANDLE_FILE_INFORMATION fi;
|
|
|
|
|
|
|
|
if (!GetFileInformationByHandle (fh, &fi)
|
|
|
|
|| fi.nFileSizeHigh != 0
|
2009-04-07 18:24:50 +02:00
|
|
|
|| fi.nFileSizeLow > 4 * 65536)
|
2008-03-16 18:04:02 +01:00
|
|
|
return false;
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
|
2008-03-16 18:04:02 +01:00
|
|
|
buf = (char *) alloca (fi.nFileSizeLow + 1);
|
|
|
|
file_header = (win_shortcut_hdr *) buf;
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
|
2013-07-07 18:57:11 +02:00
|
|
|
if (!ReadFile (fh, buf, fi.nFileSizeLow, &rv, NULL)
|
2008-03-16 18:04:02 +01:00
|
|
|
|| rv != fi.nFileSizeLow)
|
|
|
|
return false;
|
2011-12-18 00:39:47 +01:00
|
|
|
|
2008-03-16 18:04:02 +01:00
|
|
|
if (fi.nFileSizeLow > sizeof (file_header)
|
|
|
|
&& cmp_shortcut_header (file_header))
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
{
|
2008-03-16 18:04:02 +01:00
|
|
|
cp = buf + sizeof (win_shortcut_hdr);
|
|
|
|
if (file_header->flags & WSH_FLAG_IDLIST) /* Skip ITEMIDLIST */
|
2011-12-18 00:39:47 +01:00
|
|
|
cp += *(unsigned short *) cp + 2;
|
2008-03-16 18:04:02 +01:00
|
|
|
if (!(len = *(unsigned short *) cp))
|
2011-12-18 00:39:47 +01:00
|
|
|
return false;
|
2008-03-16 18:04:02 +01:00
|
|
|
cp += 2;
|
|
|
|
/* Has appended full path? If so, use it instead of description. */
|
|
|
|
unsigned short relpath_len = *(unsigned short *) (cp + len);
|
|
|
|
if (cp + len + 2 + relpath_len < buf + fi.nFileSizeLow)
|
2011-12-18 00:39:47 +01:00
|
|
|
{
|
|
|
|
cp += len + 2 + relpath_len;
|
|
|
|
len = *(unsigned short *) cp;
|
|
|
|
cp += 2;
|
|
|
|
}
|
2009-04-07 18:24:50 +02:00
|
|
|
if (*(PWCHAR) cp == 0xfeff) /* BOM */
|
|
|
|
{
|
2016-10-22 22:53:29 +02:00
|
|
|
size_t wlen = wcstombs (NULL, (wchar_t *) (cp + 2), 0);
|
|
|
|
if (wlen == (size_t) -1 || wlen + 1 > maxlen)
|
2009-04-07 18:24:50 +02:00
|
|
|
return false;
|
2016-10-22 22:53:29 +02:00
|
|
|
wcstombs (path, (wchar_t *) (cp + 2), wlen + 1);
|
2009-04-07 18:24:50 +02:00
|
|
|
}
|
2018-08-08 09:25:12 +02:00
|
|
|
else if ((size_t) (len + 1) > maxlen)
|
2011-12-18 00:39:47 +01:00
|
|
|
return false;
|
2009-04-07 18:24:50 +02:00
|
|
|
else
|
|
|
|
memcpy (path, cp, len);
|
2008-03-16 18:04:02 +01:00
|
|
|
path[len] = '\0';
|
|
|
|
return true;
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
}
|
2008-03-16 18:04:02 +01:00
|
|
|
else if (strncmp (buf, SYMLINK_COOKIE, strlen (SYMLINK_COOKIE)) == 0
|
2011-12-18 00:39:47 +01:00
|
|
|
&& buf[fi.nFileSizeLow - 1] == '\0')
|
2008-03-16 18:04:02 +01:00
|
|
|
{
|
2009-04-07 18:24:50 +02:00
|
|
|
cp = buf + strlen (SYMLINK_COOKIE);
|
|
|
|
if (*(PWCHAR) cp == 0xfeff) /* BOM */
|
|
|
|
{
|
2016-10-22 22:53:29 +02:00
|
|
|
size_t wlen = wcstombs (NULL, (wchar_t *) (cp + 2), 0);
|
|
|
|
if (wlen == (size_t) -1 || wlen + 1 > maxlen)
|
2009-04-07 18:24:50 +02:00
|
|
|
return false;
|
2016-10-22 22:53:29 +02:00
|
|
|
wcstombs (path, (wchar_t *) (cp + 2), wlen + 1);
|
2009-04-07 18:24:50 +02:00
|
|
|
}
|
2018-08-08 09:25:12 +02:00
|
|
|
else if (fi.nFileSizeLow - strlen (SYMLINK_COOKIE) > maxlen)
|
2009-04-07 18:24:50 +02:00
|
|
|
return false;
|
|
|
|
else
|
|
|
|
strcpy (path, cp);
|
2008-03-16 18:04:02 +01:00
|
|
|
return true;
|
2011-12-18 00:39:47 +01:00
|
|
|
}
|
* cygcheck.cc (get_word, get_dword): Move to path.cc.
(LINK_EXTENSION): New macro.
(check_existence): New static function.
(find_on_path): Check for symbolic links if asked.
(dll_info): New error handling.
(track_down): Only call dll_info() for executables, display
an error for symlinks, and print magic number for others.
(find_app_on_path): New static function.
(cygcheck, dump_sysinfo): Call find_app_on_path() instead of
find_on_path().
* path.cc (cmp_shortcut_header): New static function.
(get_word, get_dword): Moved from cygcheck.cc.
(EXE_MAGIC, SHORTCUT_MAGIC, SYMLINK_COOKIE, SYMLINK_MAGIC): New
macros.
(is_exe, is_symlink, readlink): New functions.
* path.h (is_exe, is_symlink, readlink): Declare.
(get_word, get_dword): Ditto.
2006-10-05 19:24:13 +02:00
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
2009-07-22 12:20:26 +02:00
|
|
|
#endif /* !FSTAB_ONLY */
|
2008-03-09 05:10:10 +01:00
|
|
|
|
|
|
|
#ifndef TESTSUITE
|
2009-07-22 12:20:26 +02:00
|
|
|
mnt_t mount_table[255];
|
|
|
|
int max_mount_entry;
|
2008-03-09 05:10:10 +01:00
|
|
|
#else
|
|
|
|
# define TESTSUITE_MOUNT_TABLE
|
|
|
|
# include "testsuite.h"
|
|
|
|
# undef TESTSUITE_MOUNT_TABLE
|
|
|
|
#endif
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2008-04-22 16:42:05 +02:00
|
|
|
inline void
|
|
|
|
unconvert_slashes (char* name)
|
|
|
|
{
|
|
|
|
while ((name = strchr (name, '/')) != NULL)
|
|
|
|
*name++ = '\\';
|
|
|
|
}
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2008-03-09 05:10:10 +01:00
|
|
|
/* These functions aren't called when defined(TESTSUITE) which results
|
|
|
|
in a compiler warning. */
|
|
|
|
#ifndef TESTSUITE
|
2008-04-22 16:42:05 +02:00
|
|
|
inline char *
|
|
|
|
skip_ws (char *in)
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
2008-04-22 16:42:05 +02:00
|
|
|
while (*in == ' ' || *in == '\t')
|
|
|
|
++in;
|
|
|
|
return in;
|
|
|
|
}
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2008-04-22 16:42:05 +02:00
|
|
|
inline char *
|
|
|
|
find_ws (char *in)
|
|
|
|
{
|
|
|
|
while (*in && *in != ' ' && *in != '\t')
|
|
|
|
++in;
|
|
|
|
return in;
|
|
|
|
}
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2008-04-22 16:42:05 +02:00
|
|
|
inline char *
|
|
|
|
conv_fstab_spaces (char *field)
|
|
|
|
{
|
|
|
|
register char *sp = field;
|
2008-09-13 00:43:10 +02:00
|
|
|
while ((sp = strstr (sp, "\\040")) != NULL)
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
2008-04-22 16:42:05 +02:00
|
|
|
*sp++ = ' ';
|
|
|
|
memmove (sp, sp + 3, strlen (sp + 3) + 1);
|
2001-11-11 04:06:59 +01:00
|
|
|
}
|
2008-04-22 16:42:05 +02:00
|
|
|
return field;
|
|
|
|
}
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2011-03-29 13:02:58 +02:00
|
|
|
#ifndef FSTAB_ONLY
|
2008-09-13 00:43:10 +02:00
|
|
|
static struct opt
|
2008-04-22 16:42:05 +02:00
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
unsigned val;
|
|
|
|
bool clear;
|
|
|
|
} oopts[] =
|
|
|
|
{
|
2009-06-10 12:42:22 +02:00
|
|
|
{"acl", MOUNT_NOACL, 1},
|
|
|
|
{"auto", 0, 0},
|
2019-02-18 11:00:06 +01:00
|
|
|
{"binary", MOUNT_TEXT, 1},
|
2008-04-22 16:42:05 +02:00
|
|
|
{"cygexec", MOUNT_CYGWIN_EXEC, 0},
|
2010-04-29 12:39:35 +02:00
|
|
|
{"dos", MOUNT_DOS, 0},
|
2009-06-10 12:42:22 +02:00
|
|
|
{"exec", MOUNT_EXEC, 0},
|
2010-04-29 12:39:35 +02:00
|
|
|
{"ihash", MOUNT_IHASH, 0},
|
2008-07-22 16:40:05 +02:00
|
|
|
{"noacl", MOUNT_NOACL, 0},
|
2009-06-10 12:42:22 +02:00
|
|
|
{"nosuid", 0, 0},
|
|
|
|
{"notexec", MOUNT_NOTEXEC, 0},
|
|
|
|
{"nouser", MOUNT_SYSTEM, 0},
|
|
|
|
{"override", MOUNT_OVERRIDE, 0},
|
|
|
|
{"posix=0", MOUNT_NOPOSIX, 0},
|
2008-07-22 16:40:05 +02:00
|
|
|
{"posix=1", MOUNT_NOPOSIX, 1},
|
2019-02-18 11:00:06 +01:00
|
|
|
{"text", MOUNT_TEXT, 0},
|
2009-06-10 12:42:22 +02:00
|
|
|
{"user", MOUNT_SYSTEM, 1}
|
2008-04-22 16:42:05 +02:00
|
|
|
};
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2008-04-22 16:42:05 +02:00
|
|
|
static bool
|
|
|
|
read_flags (char *options, unsigned &flags)
|
|
|
|
{
|
|
|
|
while (*options)
|
|
|
|
{
|
|
|
|
char *p = strchr (options, ',');
|
|
|
|
if (p)
|
2011-12-18 00:39:47 +01:00
|
|
|
*p++ = '\0';
|
2008-04-22 16:42:05 +02:00
|
|
|
else
|
2011-12-18 00:39:47 +01:00
|
|
|
p = strchr (options, '\0');
|
2008-04-22 16:42:05 +02:00
|
|
|
|
|
|
|
for (opt *o = oopts;
|
2011-12-18 00:39:47 +01:00
|
|
|
o < (oopts + (sizeof (oopts) / sizeof (oopts[0])));
|
|
|
|
o++)
|
|
|
|
if (strcmp (options, o->name) == 0)
|
|
|
|
{
|
|
|
|
if (o->clear)
|
|
|
|
flags &= ~o->val;
|
|
|
|
else
|
|
|
|
flags |= o->val;
|
|
|
|
goto gotit;
|
|
|
|
}
|
2008-04-22 16:42:05 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
gotit:
|
|
|
|
options = p;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2011-03-29 13:02:58 +02:00
|
|
|
#endif
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2009-07-22 12:20:26 +02:00
|
|
|
bool
|
2008-04-22 16:42:05 +02:00
|
|
|
from_fstab_line (mnt_t *m, char *line, bool user)
|
|
|
|
{
|
|
|
|
char *native_path, *posix_path, *fs_type;
|
|
|
|
|
|
|
|
/* First field: Native path. */
|
|
|
|
char *c = skip_ws (line);
|
|
|
|
if (!*c || *c == '#')
|
|
|
|
return false;
|
|
|
|
char *cend = find_ws (c);
|
|
|
|
*cend = '\0';
|
|
|
|
native_path = conv_fstab_spaces (c);
|
|
|
|
/* Second field: POSIX path. */
|
|
|
|
c = skip_ws (cend + 1);
|
|
|
|
if (!*c)
|
|
|
|
return false;
|
|
|
|
cend = find_ws (c);
|
|
|
|
*cend = '\0';
|
|
|
|
posix_path = conv_fstab_spaces (c);
|
|
|
|
/* Third field: FS type. */
|
|
|
|
c = skip_ws (cend + 1);
|
|
|
|
if (!*c)
|
|
|
|
return false;
|
|
|
|
cend = find_ws (c);
|
|
|
|
*cend = '\0';
|
|
|
|
fs_type = c;
|
|
|
|
/* Forth field: Flags. */
|
|
|
|
c = skip_ws (cend + 1);
|
|
|
|
if (!*c)
|
|
|
|
return false;
|
|
|
|
cend = find_ws (c);
|
|
|
|
*cend = '\0';
|
|
|
|
unsigned mount_flags = MOUNT_SYSTEM;
|
2010-04-29 12:39:35 +02:00
|
|
|
#ifndef FSTAB_ONLY
|
2008-04-22 16:42:05 +02:00
|
|
|
if (!read_flags (c, mount_flags))
|
2010-04-29 12:39:35 +02:00
|
|
|
#else
|
|
|
|
if (cygwin_internal (CW_CVT_MNT_OPTS, &c, &mount_flags))
|
|
|
|
#endif
|
2008-04-22 16:42:05 +02:00
|
|
|
return false;
|
|
|
|
if (user)
|
|
|
|
mount_flags &= ~MOUNT_SYSTEM;
|
|
|
|
if (!strcmp (fs_type, "cygdrive"))
|
|
|
|
{
|
|
|
|
for (mnt_t *sm = mount_table; sm < m; ++sm)
|
|
|
|
if (sm->flags & MOUNT_CYGDRIVE)
|
|
|
|
{
|
|
|
|
if ((mount_flags & MOUNT_SYSTEM) || !(sm->flags & MOUNT_SYSTEM))
|
|
|
|
{
|
2011-12-18 00:39:47 +01:00
|
|
|
if (sm->posix)
|
2008-04-22 16:42:05 +02:00
|
|
|
free (sm->posix);
|
|
|
|
sm->posix = strdup (posix_path);
|
|
|
|
sm->flags = mount_flags | MOUNT_CYGDRIVE;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
m->posix = strdup (posix_path);
|
2009-06-10 12:42:22 +02:00
|
|
|
m->native = strdup ("cygdrive prefix");
|
2008-04-22 16:42:05 +02:00
|
|
|
m->flags = mount_flags | MOUNT_CYGDRIVE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (mnt_t *sm = mount_table; sm < m; ++sm)
|
2009-06-10 12:42:22 +02:00
|
|
|
if (!strcmp (sm->posix, posix_path))
|
2008-04-22 16:42:05 +02:00
|
|
|
{
|
2009-06-10 12:42:22 +02:00
|
|
|
/* Don't allow overriding of a system mount with a user mount. */
|
|
|
|
if ((sm->flags & MOUNT_SYSTEM) && !(mount_flags & MOUNT_SYSTEM))
|
|
|
|
return false;
|
|
|
|
if ((sm->flags & MOUNT_SYSTEM) != (mount_flags & MOUNT_SYSTEM))
|
|
|
|
continue;
|
|
|
|
/* Changing immutable mount points require the override flag. */
|
|
|
|
if ((sm->flags & MOUNT_IMMUTABLE)
|
2011-12-18 00:39:47 +01:00
|
|
|
&& !(mount_flags & MOUNT_OVERRIDE))
|
2009-06-10 12:42:22 +02:00
|
|
|
return false;
|
|
|
|
if (mount_flags & MOUNT_OVERRIDE)
|
|
|
|
mount_flags |= MOUNT_IMMUTABLE;
|
|
|
|
if (sm->native)
|
|
|
|
free (sm->native);
|
|
|
|
sm->native = strdup (native_path);
|
|
|
|
sm->flags = mount_flags;
|
2008-04-22 16:42:05 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
m->posix = strdup (posix_path);
|
2015-06-08 17:37:55 +02:00
|
|
|
/* Bind mounts require POSIX paths, otherwise the path is wrongly
|
|
|
|
prefixed with the Cygwin root dir when trying to convert it to
|
|
|
|
a Win32 path in mount(2). So don't convert slashes to backslashes
|
|
|
|
in this case. */
|
|
|
|
if (!(mount_flags & MOUNT_BIND))
|
|
|
|
unconvert_slashes (native_path);
|
2008-04-22 16:42:05 +02:00
|
|
|
m->native = strdup (native_path);
|
|
|
|
m->flags = mount_flags;
|
|
|
|
}
|
|
|
|
return true;
|
2001-11-11 04:06:59 +01:00
|
|
|
}
|
|
|
|
|
2009-07-22 12:20:26 +02:00
|
|
|
#ifndef FSTAB_ONLY
|
|
|
|
|
2008-04-22 16:42:05 +02:00
|
|
|
#define BUFSIZE 65536
|
|
|
|
|
|
|
|
static char *
|
|
|
|
get_user ()
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
2008-04-22 16:42:05 +02:00
|
|
|
static char user[UNLEN + 1];
|
|
|
|
char *userenv;
|
|
|
|
|
|
|
|
user[0] = '\0';
|
|
|
|
if ((userenv = getenv ("USER")) || (userenv = getenv ("USERNAME")))
|
|
|
|
strncat (user, userenv, UNLEN);
|
|
|
|
return user;
|
2001-11-11 04:06:59 +01:00
|
|
|
}
|
|
|
|
|
2008-04-22 16:42:05 +02:00
|
|
|
void
|
|
|
|
from_fstab (bool user, PWCHAR path, PWCHAR path_end)
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
2008-04-22 16:42:05 +02:00
|
|
|
mnt_t *m = mount_table + max_mount_entry;
|
|
|
|
char buf[BUFSIZE];
|
|
|
|
|
|
|
|
if (!user)
|
|
|
|
{
|
|
|
|
/* Create a default root dir from path. */
|
2009-03-14 15:58:05 +01:00
|
|
|
wcstombs (buf, path, BUFSIZE);
|
2008-04-22 16:42:05 +02:00
|
|
|
unconvert_slashes (buf);
|
|
|
|
char *native_path = buf;
|
|
|
|
if (!strncmp (native_path, "\\\\?\\", 4))
|
2011-12-18 00:39:47 +01:00
|
|
|
native_path += 4;
|
2008-04-22 16:42:05 +02:00
|
|
|
if (!strncmp (native_path, "UNC\\", 4))
|
2011-12-18 00:39:47 +01:00
|
|
|
*(native_path += 2) = '\\';
|
2008-04-22 16:42:05 +02:00
|
|
|
m->posix = strdup ("/");
|
|
|
|
m->native = strdup (native_path);
|
2019-02-18 11:00:06 +01:00
|
|
|
m->flags = MOUNT_SYSTEM | MOUNT_IMMUTABLE | MOUNT_AUTOMATIC;
|
2009-06-10 12:42:22 +02:00
|
|
|
++m;
|
|
|
|
/* Create default /usr/bin and /usr/lib entries. */
|
|
|
|
char *trail = strchr (native_path, '\0');
|
|
|
|
strcpy (trail, "\\bin");
|
|
|
|
m->posix = strdup ("/usr/bin");
|
|
|
|
m->native = strdup (native_path);
|
2019-02-18 11:00:06 +01:00
|
|
|
m->flags = MOUNT_SYSTEM | MOUNT_AUTOMATIC;
|
2009-06-10 12:42:22 +02:00
|
|
|
++m;
|
|
|
|
strcpy (trail, "\\lib");
|
|
|
|
m->posix = strdup ("/usr/lib");
|
|
|
|
m->native = strdup (native_path);
|
2019-02-18 11:00:06 +01:00
|
|
|
m->flags = MOUNT_SYSTEM | MOUNT_AUTOMATIC;
|
2008-04-22 16:42:05 +02:00
|
|
|
++m;
|
|
|
|
/* Create a default cygdrive entry. Note that this is a user entry.
|
2011-12-18 00:39:47 +01:00
|
|
|
This allows to override it with mount, unless the sysadmin created
|
|
|
|
a cygdrive entry in /etc/fstab. */
|
2008-04-22 16:42:05 +02:00
|
|
|
m->posix = strdup (CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX);
|
2009-06-10 12:42:22 +02:00
|
|
|
m->native = strdup ("cygdrive prefix");
|
2019-02-18 11:00:06 +01:00
|
|
|
m->flags = MOUNT_CYGDRIVE;
|
2008-04-22 16:42:05 +02:00
|
|
|
++m;
|
|
|
|
max_mount_entry = m - mount_table;
|
|
|
|
}
|
|
|
|
|
|
|
|
PWCHAR u = wcscpy (path_end, L"\\etc\\fstab") + 10;
|
|
|
|
if (user)
|
2009-03-14 15:58:05 +01:00
|
|
|
mbstowcs (wcscpy (u, L".d\\") + 3, get_user (), BUFSIZE - (u - path));
|
2008-04-22 16:42:05 +02:00
|
|
|
HANDLE h = CreateFileW (path, GENERIC_READ, FILE_SHARE_READ, NULL,
|
2011-12-18 00:39:47 +01:00
|
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
2008-04-22 16:42:05 +02:00
|
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
|
|
return;
|
|
|
|
char *got = buf;
|
|
|
|
DWORD len = 0;
|
|
|
|
/* Using BUFSIZE-1 leaves space to append two \0. */
|
|
|
|
while (ReadFile (h, got, BUFSIZE - 1 - (got - buf),
|
2011-12-18 00:39:47 +01:00
|
|
|
&len, NULL))
|
2008-04-22 16:42:05 +02:00
|
|
|
{
|
|
|
|
char *end;
|
|
|
|
|
|
|
|
/* Set end marker. */
|
|
|
|
got[len] = got[len + 1] = '\0';
|
|
|
|
/* Set len to the absolute len of bytes in buf. */
|
|
|
|
len += got - buf;
|
|
|
|
/* Reset got to start reading at the start of the buffer again. */
|
|
|
|
got = buf;
|
|
|
|
while (got < buf + len && (end = strchr (got, '\n')))
|
2011-12-18 00:39:47 +01:00
|
|
|
{
|
|
|
|
end[end[-1] == '\r' ? -1 : 0] = '\0';
|
|
|
|
if (from_fstab_line (m, got, user))
|
|
|
|
++m;
|
|
|
|
got = end + 1;
|
|
|
|
}
|
2008-04-22 16:42:05 +02:00
|
|
|
if (len < BUFSIZE - 1)
|
2011-12-18 00:39:47 +01:00
|
|
|
break;
|
2008-04-22 16:42:05 +02:00
|
|
|
/* We have to read once more. Move remaining bytes to the start of
|
2011-12-18 00:39:47 +01:00
|
|
|
the buffer and reposition got so that it points to the end of
|
|
|
|
the remaining bytes. */
|
2008-04-22 16:42:05 +02:00
|
|
|
len = buf + len - got;
|
|
|
|
memmove (buf, got, len);
|
|
|
|
got = buf + len;
|
|
|
|
buf[len] = buf[len + 1] = '\0';
|
|
|
|
}
|
|
|
|
if (got > buf && from_fstab_line (m, got, user))
|
|
|
|
++m;
|
|
|
|
max_mount_entry = m - mount_table;
|
|
|
|
CloseHandle (h);
|
2001-11-11 04:06:59 +01:00
|
|
|
}
|
2009-07-22 12:20:26 +02:00
|
|
|
#endif /* !FSTAB_ONLY */
|
|
|
|
#endif /* !TESTSUITE */
|
|
|
|
|
|
|
|
#ifndef FSTAB_ONLY
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2008-09-13 00:43:10 +02:00
|
|
|
static int
|
2008-04-22 16:42:05 +02:00
|
|
|
mnt_sort (const void *a, const void *b)
|
|
|
|
{
|
|
|
|
const mnt_t *ma = (const mnt_t *) a;
|
|
|
|
const mnt_t *mb = (const mnt_t *) b;
|
|
|
|
int ret;
|
2011-12-18 00:39:47 +01:00
|
|
|
|
2008-04-22 16:42:05 +02:00
|
|
|
ret = (ma->flags & MOUNT_CYGDRIVE) - (mb->flags & MOUNT_CYGDRIVE);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
ret = (ma->flags & MOUNT_SYSTEM) - (mb->flags & MOUNT_SYSTEM);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
return strcmp (ma->posix, mb->posix);
|
|
|
|
}
|
|
|
|
|
2009-11-04 18:00:45 +01:00
|
|
|
extern "C" WCHAR cygwin_dll_path[];
|
|
|
|
|
2001-11-11 07:07:36 +01:00
|
|
|
static void
|
2001-11-11 04:06:59 +01:00
|
|
|
read_mounts ()
|
|
|
|
{
|
2008-03-09 05:10:10 +01:00
|
|
|
/* If TESTSUITE is defined, bypass this whole function as a harness
|
|
|
|
mount table will be provided. */
|
|
|
|
#ifndef TESTSUITE
|
2008-04-22 16:42:05 +02:00
|
|
|
HKEY setup_key;
|
|
|
|
LONG ret;
|
|
|
|
DWORD len;
|
|
|
|
WCHAR path[32768];
|
|
|
|
PWCHAR path_end;
|
|
|
|
|
|
|
|
for (mnt_t *m1 = mount_table; m1->posix; m1++)
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
|
|
|
free (m1->posix);
|
|
|
|
if (m1->native)
|
|
|
|
free ((char *) m1->native);
|
|
|
|
m1->posix = NULL;
|
|
|
|
}
|
2008-04-22 16:42:05 +02:00
|
|
|
max_mount_entry = 0;
|
|
|
|
|
2009-11-04 18:00:45 +01:00
|
|
|
/* First fetch the cygwin1.dll path from the LoadLibrary call in load_cygwin.
|
|
|
|
This utilizes the DLL search order to find a matching cygwin1.dll and to
|
|
|
|
compute the installation path from that DLL's path. */
|
|
|
|
if (cygwin_dll_path[0])
|
|
|
|
wcscpy (path, cygwin_dll_path);
|
|
|
|
/* If we can't load cygwin1.dll, check where cygcheck is living itself and
|
|
|
|
try to fetch installation path from here. Does cygwin1.dll exist in the
|
|
|
|
same path? This should only kick in if the cygwin1.dll in the same path
|
|
|
|
has been made non-executable for the current user accidentally. */
|
|
|
|
else if (!GetModuleFileNameW (NULL, path, 32768))
|
2009-11-04 16:47:29 +01:00
|
|
|
return;
|
|
|
|
path_end = wcsrchr (path, L'\\');
|
|
|
|
if (path_end)
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
2009-11-04 18:09:32 +01:00
|
|
|
if (!cygwin_dll_path[0])
|
|
|
|
{
|
|
|
|
wcscpy (path_end, L"\\cygwin1.dll");
|
|
|
|
DWORD attr = GetFileAttributesW (path);
|
|
|
|
if (attr == (DWORD) -1
|
|
|
|
|| (attr & (FILE_ATTRIBUTE_DIRECTORY
|
|
|
|
| FILE_ATTRIBUTE_REPARSE_POINT)))
|
|
|
|
path_end = NULL;
|
|
|
|
}
|
|
|
|
if (path_end)
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
2008-04-22 16:42:05 +02:00
|
|
|
*path_end = L'\0';
|
|
|
|
path_end = wcsrchr (path, L'\\');
|
2001-11-11 04:06:59 +01:00
|
|
|
}
|
|
|
|
}
|
2009-11-04 16:47:29 +01:00
|
|
|
/* If we can't create a valid installation dir from that, try to fetch
|
|
|
|
the installation dir from the setup registry key. */
|
2008-04-22 16:42:05 +02:00
|
|
|
if (!path_end)
|
2009-11-04 16:47:29 +01:00
|
|
|
{
|
|
|
|
for (int i = 0; i < 2; ++i)
|
|
|
|
if ((ret = RegOpenKeyExW (i ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
|
|
|
|
L"Software\\Cygwin\\setup", 0,
|
|
|
|
KEY_READ, &setup_key)) == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
len = 32768 * sizeof (WCHAR);
|
|
|
|
ret = RegQueryValueExW (setup_key, L"rootdir", NULL, NULL,
|
|
|
|
(PBYTE) path, &len);
|
|
|
|
RegCloseKey (setup_key);
|
|
|
|
if (ret == ERROR_SUCCESS)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ret == ERROR_SUCCESS)
|
2009-11-04 18:00:45 +01:00
|
|
|
path_end = wcschr (path, L'\0');
|
2009-11-04 16:47:29 +01:00
|
|
|
}
|
|
|
|
/* If we can't fetch an installation dir, bail out. */
|
|
|
|
if (!path_end)
|
2009-11-04 18:00:45 +01:00
|
|
|
return;
|
2008-04-22 16:42:05 +02:00
|
|
|
*path_end = L'\0';
|
|
|
|
|
|
|
|
from_fstab (false, path, path_end);
|
|
|
|
from_fstab (true, path, path_end);
|
|
|
|
qsort (mount_table, max_mount_entry, sizeof (mnt_t), mnt_sort);
|
2008-03-09 05:10:10 +01:00
|
|
|
#endif /* !defined(TESTSUITE) */
|
2001-11-11 04:06:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Return non-zero if PATH1 is a prefix of PATH2.
|
|
|
|
Both are assumed to be of the same path style and / vs \ usage.
|
|
|
|
Neither may be "".
|
|
|
|
LEN1 = strlen (PATH1). It's passed because often it's already known.
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
/foo/ is a prefix of /foo <-- may seem odd, but desired
|
|
|
|
/foo is a prefix of /foo/
|
|
|
|
/ is a prefix of /foo/bar
|
|
|
|
/ is not a prefix of foo/bar
|
|
|
|
foo/ is a prefix foo/bar
|
|
|
|
/foo is not a prefix of /foobar
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
2018-02-16 17:21:48 +01:00
|
|
|
path_prefix_p (const char *path1, const char *path2, size_t len1)
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
|
|
|
/* Handle case where PATH1 has trailing '/' and when it doesn't. */
|
2007-06-04 03:57:16 +02:00
|
|
|
if (len1 > 0 && isslash (path1[len1 - 1]))
|
2001-11-11 04:06:59 +01:00
|
|
|
len1--;
|
|
|
|
|
|
|
|
if (len1 == 0)
|
2007-06-04 03:57:16 +02:00
|
|
|
return isslash (path2[0]) && !isslash (path2[1]);
|
2001-11-11 04:06:59 +01:00
|
|
|
|
|
|
|
if (strncasecmp (path1, path2, len1) != 0)
|
|
|
|
return 0;
|
|
|
|
|
2007-06-04 03:57:16 +02:00
|
|
|
return isslash (path2[len1]) || path2[len1] == 0 || path1[len1 - 1] == ':';
|
2001-11-11 04:06:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
vconcat (const char *s, va_list v)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char *rv, *arg;
|
|
|
|
va_list save_v = v;
|
|
|
|
int unc;
|
|
|
|
|
|
|
|
if (!s)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
len = strlen (s);
|
|
|
|
|
2007-06-04 03:57:16 +02:00
|
|
|
unc = isslash (*s) && isslash (s[1]);
|
2001-11-11 04:06:59 +01:00
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
arg = va_arg (v, char *);
|
|
|
|
if (arg == 0)
|
|
|
|
break;
|
|
|
|
len += strlen (arg);
|
|
|
|
}
|
|
|
|
va_end (v);
|
|
|
|
|
|
|
|
rv = (char *) malloc (len + 1);
|
|
|
|
strcpy (rv, s);
|
|
|
|
v = save_v;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
arg = va_arg (v, char *);
|
|
|
|
if (arg == 0)
|
|
|
|
break;
|
|
|
|
strcat (rv, arg);
|
|
|
|
}
|
|
|
|
va_end (v);
|
|
|
|
|
|
|
|
char *d, *p;
|
|
|
|
|
|
|
|
/* concat is only used for urls and files, so we can safely
|
|
|
|
canonicalize the results */
|
|
|
|
for (p = d = rv; *p; p++)
|
|
|
|
{
|
|
|
|
*d++ = *p;
|
|
|
|
/* special case for URLs */
|
|
|
|
if (*p == ':' && p[1] == '/' && p[2] == '/' && p > rv + 1)
|
|
|
|
{
|
|
|
|
*d++ = *++p;
|
|
|
|
*d++ = *++p;
|
|
|
|
}
|
2008-03-09 05:10:10 +01:00
|
|
|
else if (isslash (*p))
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
|
|
|
if (p == rv && unc)
|
2003-03-04 06:30:50 +01:00
|
|
|
*d++ = *p++;
|
2001-11-11 04:06:59 +01:00
|
|
|
while (p[1] == '/')
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*d = 0;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
concat (const char *s, ...)
|
|
|
|
{
|
|
|
|
va_list v;
|
|
|
|
|
|
|
|
va_start (v, s);
|
|
|
|
|
|
|
|
return vconcat (s, v);
|
|
|
|
}
|
|
|
|
|
2008-03-11 18:20:02 +01:00
|
|
|
/* This is a helper function for when vcygpath is passed what appears
|
|
|
|
to be a relative POSIX path. We take a Win32 CWD (either as specified
|
|
|
|
in 'cwd' or as retrieved with GetCurrentDirectory() if 'cwd' is NULL)
|
|
|
|
and find the mount table entry with the longest match. We replace the
|
|
|
|
matching portion with the corresponding POSIX prefix, and to that append
|
|
|
|
's' and anything in 'v'. The returned result is a mostly-POSIX
|
|
|
|
absolute path -- 'mostly' because the portions of CWD that didn't
|
|
|
|
match the mount prefix will still have '\\' separators. */
|
2007-06-04 03:57:16 +02:00
|
|
|
static char *
|
2008-03-11 18:20:02 +01:00
|
|
|
rel_vconcat (const char *cwd, const char *s, va_list v)
|
2007-06-04 03:57:16 +02:00
|
|
|
{
|
2008-03-11 18:20:02 +01:00
|
|
|
char pathbuf[MAX_PATH];
|
|
|
|
if (!cwd || *cwd == '\0')
|
|
|
|
{
|
|
|
|
if (!GetCurrentDirectory (MAX_PATH, pathbuf))
|
2011-12-18 00:39:47 +01:00
|
|
|
return NULL;
|
2008-03-11 18:20:02 +01:00
|
|
|
cwd = pathbuf;
|
|
|
|
}
|
2007-06-04 03:57:16 +02:00
|
|
|
|
2018-08-08 09:25:12 +02:00
|
|
|
size_t max_len = 0;
|
2008-04-22 16:42:05 +02:00
|
|
|
mnt_t *m, *match = NULL;
|
2007-06-04 03:57:16 +02:00
|
|
|
|
2008-03-11 18:20:02 +01:00
|
|
|
for (m = mount_table; m->posix; m++)
|
2007-06-04 03:57:16 +02:00
|
|
|
{
|
|
|
|
if (m->flags & MOUNT_CYGDRIVE)
|
|
|
|
continue;
|
|
|
|
|
2018-02-16 17:21:48 +01:00
|
|
|
size_t n = strlen (m->native);
|
2008-03-11 18:20:02 +01:00
|
|
|
if (n < max_len || !path_prefix_p (m->native, cwd, n))
|
2007-06-04 03:57:16 +02:00
|
|
|
continue;
|
|
|
|
max_len = n;
|
|
|
|
match = m;
|
|
|
|
}
|
|
|
|
|
2008-03-09 05:10:10 +01:00
|
|
|
char *temppath;
|
|
|
|
if (!match)
|
|
|
|
// No prefix matched - best effort to return meaningful value.
|
2008-03-11 18:20:02 +01:00
|
|
|
temppath = concat (cwd, "/", s, NULL);
|
2008-03-09 05:10:10 +01:00
|
|
|
else if (strcmp (match->posix, "/") != 0)
|
|
|
|
// Matched on non-root. Copy matching prefix + remaining 'path'.
|
2008-03-11 18:20:02 +01:00
|
|
|
temppath = concat (match->posix, cwd + max_len, "/", s, NULL);
|
|
|
|
else if (cwd[max_len] == '\0')
|
2008-03-09 05:10:10 +01:00
|
|
|
// Matched on root and there's no remaining 'path'.
|
|
|
|
temppath = concat ("/", s, NULL);
|
2008-03-11 18:20:02 +01:00
|
|
|
else if (isslash (cwd[max_len]))
|
2008-03-09 05:10:10 +01:00
|
|
|
// Matched on root but remaining 'path' starts with a slash anyway.
|
2008-03-11 18:20:02 +01:00
|
|
|
temppath = concat (cwd + max_len, "/", s, NULL);
|
2008-03-09 05:10:10 +01:00
|
|
|
else
|
2008-03-11 18:20:02 +01:00
|
|
|
temppath = concat ("/", cwd + max_len, "/", s, NULL);
|
2007-06-04 03:57:16 +02:00
|
|
|
|
|
|
|
char *res = vconcat (temppath, v);
|
|
|
|
free (temppath);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2008-03-11 18:20:02 +01:00
|
|
|
/* Convert a POSIX path in 's' to an absolute Win32 path, and append
|
|
|
|
anything in 'v' to the end, returning the result. If 's' is a
|
|
|
|
relative path then 'cwd' is used as the working directory to make
|
|
|
|
it absolute. Pass NULL in 'cwd' to use GetCurrentDirectory. */
|
|
|
|
static char *
|
|
|
|
vcygpath (const char *cwd, const char *s, va_list v)
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
2018-02-16 17:21:48 +01:00
|
|
|
size_t max_len = 0;
|
2008-04-22 16:42:05 +02:00
|
|
|
mnt_t *m, *match = NULL;
|
2001-11-11 04:06:59 +01:00
|
|
|
|
2008-04-22 16:42:05 +02:00
|
|
|
if (!max_mount_entry)
|
2001-11-11 07:07:36 +01:00
|
|
|
read_mounts ();
|
2007-06-04 03:57:16 +02:00
|
|
|
char *path;
|
2008-03-09 05:10:10 +01:00
|
|
|
if (s[0] == '.' && isslash (s[1]))
|
|
|
|
s += 2;
|
|
|
|
|
2007-06-04 03:57:16 +02:00
|
|
|
if (s[0] == '/' || s[1] == ':') /* FIXME: too crude? */
|
|
|
|
path = vconcat (s, v);
|
|
|
|
else
|
2008-03-11 18:20:02 +01:00
|
|
|
path = rel_vconcat (cwd, s, v);
|
2007-06-04 03:57:16 +02:00
|
|
|
|
|
|
|
if (!path)
|
|
|
|
return NULL;
|
|
|
|
|
2001-11-11 04:06:59 +01:00
|
|
|
if (strncmp (path, "/./", 3) == 0)
|
|
|
|
memmove (path + 1, path + 3, strlen (path + 3) + 1);
|
|
|
|
|
2008-03-11 18:20:02 +01:00
|
|
|
for (m = mount_table; m->posix; m++)
|
2001-11-11 04:06:59 +01:00
|
|
|
{
|
2018-02-16 17:21:48 +01:00
|
|
|
size_t n = strlen (m->posix);
|
2001-11-11 04:06:59 +01:00
|
|
|
if (n < max_len || !path_prefix_p (m->posix, path, n))
|
|
|
|
continue;
|
2018-02-16 17:21:48 +01:00
|
|
|
if (m->flags & MOUNT_CYGDRIVE)
|
|
|
|
{
|
|
|
|
if (strlen (path) < n + 2)
|
|
|
|
continue;
|
|
|
|
/* If cygdrive path is just '/', fix n for followup evaluation. */
|
|
|
|
if (n == 1)
|
|
|
|
n = 0;
|
|
|
|
if (path[n] != '/')
|
|
|
|
continue;
|
|
|
|
if (!isalpha (path[n + 1]))
|
|
|
|
continue;
|
|
|
|
if (path[n + 2] != '/')
|
|
|
|
continue;
|
|
|
|
}
|
2001-11-11 04:06:59 +01:00
|
|
|
max_len = n;
|
|
|
|
match = m;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *native;
|
|
|
|
if (match == NULL)
|
|
|
|
native = strdup (path);
|
2018-02-16 17:21:48 +01:00
|
|
|
else if (max_len == strlen (path))
|
2001-11-11 04:06:59 +01:00
|
|
|
native = strdup (match->native);
|
2012-11-09 09:53:01 +01:00
|
|
|
else if (match->flags & MOUNT_CYGDRIVE)
|
|
|
|
{
|
|
|
|
char drive[3] = { path[max_len + 1], ':', '\0' };
|
|
|
|
native = concat (drive, path + max_len + 2, NULL);
|
|
|
|
}
|
2008-03-09 05:10:10 +01:00
|
|
|
else if (isslash (path[max_len]))
|
|
|
|
native = concat (match->native, path + max_len, NULL);
|
2001-11-11 04:06:59 +01:00
|
|
|
else
|
2006-08-03 17:29:30 +02:00
|
|
|
native = concat (match->native, "\\", path + max_len, NULL);
|
2001-11-11 04:06:59 +01:00
|
|
|
free (path);
|
|
|
|
|
2008-03-09 05:10:10 +01:00
|
|
|
unconvert_slashes (native);
|
|
|
|
for (char *s = strstr (native + 1, "\\.\\"); s && *s; s = strstr (s, "\\.\\"))
|
|
|
|
memmove (s + 1, s + 3, strlen (s + 3) + 1);
|
2001-11-11 04:06:59 +01:00
|
|
|
return native;
|
|
|
|
}
|
|
|
|
|
2008-03-11 18:20:02 +01:00
|
|
|
char *
|
|
|
|
cygpath_rel (const char *cwd, const char *s, ...)
|
|
|
|
{
|
|
|
|
va_list v;
|
|
|
|
|
|
|
|
va_start (v, s);
|
|
|
|
|
|
|
|
return vcygpath (cwd, s, v);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
cygpath (const char *s, ...)
|
|
|
|
{
|
|
|
|
va_list v;
|
2011-12-18 00:39:47 +01:00
|
|
|
|
2008-03-11 18:20:02 +01:00
|
|
|
va_start (v, s);
|
2011-12-18 00:39:47 +01:00
|
|
|
|
2008-03-11 18:20:02 +01:00
|
|
|
return vcygpath (NULL, s, v);
|
|
|
|
}
|
|
|
|
|
2008-04-22 16:42:05 +02:00
|
|
|
static mnt_t *m = NULL;
|
2001-11-11 04:06:59 +01:00
|
|
|
|
|
|
|
extern "C" FILE *
|
|
|
|
setmntent (const char *, const char *)
|
|
|
|
{
|
|
|
|
m = mount_table;
|
2008-04-22 16:42:05 +02:00
|
|
|
if (!max_mount_entry)
|
2001-11-11 04:06:59 +01:00
|
|
|
read_mounts ();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" struct mntent *
|
|
|
|
getmntent (FILE *)
|
|
|
|
{
|
|
|
|
static mntent mnt;
|
|
|
|
if (!m->posix)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
mnt.mnt_fsname = (char *) m->native;
|
|
|
|
mnt.mnt_dir = (char *) m->posix;
|
|
|
|
if (!mnt.mnt_type)
|
2009-06-10 12:42:22 +02:00
|
|
|
mnt.mnt_type = (char *) malloc (16);
|
2001-11-11 04:06:59 +01:00
|
|
|
if (!mnt.mnt_opts)
|
2009-06-10 12:42:22 +02:00
|
|
|
mnt.mnt_opts = (char *) malloc (64);
|
|
|
|
|
2013-04-23 11:44:36 +02:00
|
|
|
strcpy (mnt.mnt_type,
|
|
|
|
(char *) ((m->flags & MOUNT_SYSTEM) ? "system" : "user"));
|
2009-06-10 12:42:22 +02:00
|
|
|
|
2019-02-18 11:00:06 +01:00
|
|
|
if (m->flags & MOUNT_TEXT)
|
2009-06-10 12:42:22 +02:00
|
|
|
strcpy (mnt.mnt_opts, (char *) "text");
|
2001-11-11 04:06:59 +01:00
|
|
|
else
|
2009-06-10 12:42:22 +02:00
|
|
|
strcpy (mnt.mnt_opts, (char *) "binary");
|
|
|
|
|
2001-11-11 04:06:59 +01:00
|
|
|
if (m->flags & MOUNT_CYGWIN_EXEC)
|
|
|
|
strcat (mnt.mnt_opts, (char *) ",cygexec");
|
|
|
|
else if (m->flags & MOUNT_EXEC)
|
|
|
|
strcat (mnt.mnt_opts, (char *) ",exec");
|
2005-04-29 18:39:34 +02:00
|
|
|
else if (m->flags & MOUNT_NOTEXEC)
|
2009-07-22 18:24:17 +02:00
|
|
|
strcat (mnt.mnt_opts, (char *) ",notexec");
|
2009-06-10 12:42:22 +02:00
|
|
|
|
|
|
|
if (m->flags & MOUNT_NOACL)
|
2008-07-22 16:40:05 +02:00
|
|
|
strcat (mnt.mnt_opts, (char *) ",noacl");
|
2009-06-10 12:42:22 +02:00
|
|
|
|
|
|
|
if (m->flags & MOUNT_NOPOSIX)
|
2008-07-22 16:40:05 +02:00
|
|
|
strcat (mnt.mnt_opts, (char *) ",posix=0");
|
2009-06-10 12:42:22 +02:00
|
|
|
|
|
|
|
if (m->flags & (MOUNT_AUTOMATIC | MOUNT_CYGDRIVE))
|
|
|
|
strcat (mnt.mnt_opts, (char *) ",auto");
|
|
|
|
|
2001-11-11 04:06:59 +01:00
|
|
|
mnt.mnt_freq = 1;
|
|
|
|
mnt.mnt_passno = 1;
|
|
|
|
m++;
|
|
|
|
return &mnt;
|
|
|
|
}
|
2009-07-22 12:20:26 +02:00
|
|
|
|
|
|
|
#endif /* !FSTAB_ONLY */
|