* path.cc (conv_path_list): Fix wild indexing into path due to conflicting

methods for setting src pointer.
* dir.cc (opendir): Only pass path_conv argument to opendir, since name is
already part of the fhandler.
* dtable.cc (dtable::build_fhandler): Accomodate new FH_CYGDRIVE type.
* fhandler.cc (fhandler_base::opendir): Nuke name argument.
* fhandler.h: Add FH_CYGDRIVE to "device" enum.
(fhandler_base::opendir): Nuke name argument.
(fhandler_disk_file::opendir): Ditto.
(fhandler_disk_file::fhandler_disk_file): Declare new method which passes
devtype through.
(fhandler_cygdrive): Add elements for tracking drives.
(fhandler_cygdrive::set_drives): Declare new method.
(fhandler_cygdrive::iscygdrive_root): Declare new method.
(fhandler_cygdrive::opendir): Declare new method.
(fhandler_cygdrive::readdir): Declare new method.
(fhandler_cygdrive::telldir): Declare new method.
(fhandler_cygdrive::seekdir): Declare new method.
(fhandler_cygdrive::rewinddir): Declare new method.
(fhandler_cygdrive::closedir): Declare new method.
(fhandler_cygdrive::fstat): Declare new method.
* fhandler_disk_file.cc (fhandler_disk_file::fhandler_disk_file): Define new
method which passes devtype through.
(fhandler_disk_file::open): Tweak debug output.
(fhandler_disk_file::opendir): Nuke first argument.  Use info from path_conv
and class rather than calling fstat.
(fhandler_cygdrive::set_drives): New method.
(fhandler_cygdrive::iscygdrive_root): New method.
(fhandler_cygdrive::opendir): New method.
(fhandler_cygdrive::readdir): New method.
(fhandler_cygdrive::telldir): New method.
(fhandler_cygdrive::seekdir): New method.
(fhandler_cygdrive::rewinddir): New method.
(fhandler_cygdrive::closedir): New method.
(fhandler_cygdrive::fstat): New method.
* path.cc (iscygdrive_device): Assume cygdriveness is already verified.
(path_conv::check): Treat FH_CYGDRIVE "method" as a special case, setting file
attributes as needed.
(mount_info::conv_to_win32_path): Allow stand-alone /cygdrive, meaning "the
directory which contains all of the drives on the system".
(fillout_mntent): Use cyg_tolower for conversions.
(mount_info::cygdrive_win32_path): Replace unused argument with unit number.
* shared_info.h (mount_info::cygdrive_win32_path): Reflect argument change.
This commit is contained in:
Christopher Faylor 2001-11-22 05:59:07 +00:00
parent 53e61a867b
commit 97a2e0756d
8 changed files with 239 additions and 50 deletions

View File

@ -1,3 +1,52 @@
2001-11-22 Christopher Faylor <cgf@redhat.com>
* path.cc (conv_path_list): Fix wild indexing into path due to
conflicting methods for setting src pointer.
* dir.cc (opendir): Only pass path_conv argument to opendir, since name
is already part of the fhandler.
* dtable.cc (dtable::build_fhandler): Accomodate new FH_CYGDRIVE type.
* fhandler.cc (fhandler_base::opendir): Nuke name argument.
* fhandler.h: Add FH_CYGDRIVE to "device" enum.
(fhandler_base::opendir): Nuke name argument.
(fhandler_disk_file::opendir): Ditto.
(fhandler_disk_file::fhandler_disk_file): Declare new method which
passes devtype through.
(fhandler_cygdrive): Add elements for tracking drives.
(fhandler_cygdrive::set_drives): Declare new method.
(fhandler_cygdrive::iscygdrive_root): Declare new method.
(fhandler_cygdrive::opendir): Declare new method.
(fhandler_cygdrive::readdir): Declare new method.
(fhandler_cygdrive::telldir): Declare new method.
(fhandler_cygdrive::seekdir): Declare new method.
(fhandler_cygdrive::rewinddir): Declare new method.
(fhandler_cygdrive::closedir): Declare new method.
(fhandler_cygdrive::fstat): Declare new method.
* fhandler_disk_file.cc (fhandler_disk_file::fhandler_disk_file):
Define new method which passes devtype through.
(fhandler_disk_file::open): Tweak debug output.
(fhandler_disk_file::opendir): Nuke first argument. Use info from
path_conv and class rather than calling fstat.
(fhandler_cygdrive::set_drives): New method.
(fhandler_cygdrive::iscygdrive_root): New method.
(fhandler_cygdrive::opendir): New method.
(fhandler_cygdrive::readdir): New method.
(fhandler_cygdrive::telldir): New method.
(fhandler_cygdrive::seekdir): New method.
(fhandler_cygdrive::rewinddir): New method.
(fhandler_cygdrive::closedir): New method.
(fhandler_cygdrive::fstat): New method.
* path.cc (iscygdrive_device): Assume cygdriveness is already verified.
(path_conv::check): Treat FH_CYGDRIVE "method" as a special case,
setting file attributes as needed.
(mount_info::conv_to_win32_path): Allow stand-alone /cygdrive, meaning
"the directory which contains all of the drives on the system".
(fillout_mntent): Use cyg_tolower for conversions.
(mount_info::cygdrive_win32_path): Replace unused argument with unit
number.
* shared_info.h (mount_info::cygdrive_win32_path): Reflect argument
change.
2001-11-21 Christopher Faylor <cgf@redhat.com> 2001-11-21 Christopher Faylor <cgf@redhat.com>
* Makefile.in (DLL_OFILES): Add fhandler_disk_file.o. * Makefile.in (DLL_OFILES): Add fhandler_disk_file.o.

View File

@ -86,7 +86,7 @@ opendir (const char *name)
fh = cygheap->fdtab.build_fhandler_from_name (-1, name, NULL, pc, fh = cygheap->fdtab.build_fhandler_from_name (-1, name, NULL, pc,
PC_SYM_FOLLOW | PC_FULL, NULL); PC_SYM_FOLLOW | PC_FULL, NULL);
res = fh->opendir (name, pc); res = fh->opendir (pc);
if (!res) if (!res)
delete fh; delete fh;
return res; return res;

View File

@ -301,6 +301,9 @@ dtable::build_fhandler (int fd, DWORD dev, const char *name, int unit)
case FH_DISK: case FH_DISK:
fh = cnew (fhandler_disk_file) (); fh = cnew (fhandler_disk_file) ();
break; break;
case FH_CYGDRIVE:
fh = cnew (fhandler_cygdrive) (unit);
break;
case FH_FLOPPY: case FH_FLOPPY:
fh = cnew (fhandler_dev_floppy) (unit); fh = cnew (fhandler_dev_floppy) (unit);
break; break;

View File

@ -1166,7 +1166,7 @@ fhandler_base::set_nonblocking (int yes)
} }
DIR * DIR *
fhandler_base::opendir (const char *, path_conv&) fhandler_base::opendir (path_conv&)
{ {
set_errno (ENOTDIR); set_errno (ENOTDIR);
return NULL; return NULL;

View File

@ -67,10 +67,11 @@ enum
FH_ZERO = 0x00000014, /* is the zero device */ FH_ZERO = 0x00000014, /* is the zero device */
FH_RANDOM = 0x00000015, /* is a random device */ FH_RANDOM = 0x00000015, /* is a random device */
FH_MEM = 0x00000016, /* is a mem device */ FH_MEM = 0x00000016, /* is a mem device */
FH_CLIPBOARD = 0x00000017, /* is a clipbaord device */ FH_CLIPBOARD = 0x00000017, /* is a clipboard device */
FH_OSS_DSP = 0x00000018, /* is a dsp audio device */ FH_OSS_DSP = 0x00000018, /* is a dsp audio device */
FH_CYGDRIVE= 0x00000019, /* /cygdrive/x */
FH_NDEV = 0x00000019, /* Maximum number of devices */ FH_NDEV = 0x0000001a, /* Maximum number of devices */
FH_DEVMASK = 0x00000fff, /* devices live here */ FH_DEVMASK = 0x00000fff, /* devices live here */
FH_BAD = 0xffffffff FH_BAD = 0xffffffff
}; };
@ -340,7 +341,7 @@ class fhandler_base
void operator delete (void *); void operator delete (void *);
virtual HANDLE get_guard () const {return NULL;} virtual HANDLE get_guard () const {return NULL;}
virtual void set_eof () {} virtual void set_eof () {}
virtual DIR *opendir (const char *dirname, path_conv& pc); virtual DIR *opendir (path_conv& pc);
virtual dirent *readdir (DIR *); virtual dirent *readdir (DIR *);
virtual off_t telldir (DIR *); virtual off_t telldir (DIR *);
virtual void seekdir (DIR *, off_t); virtual void seekdir (DIR *, off_t);
@ -527,6 +528,7 @@ class fhandler_disk_file: public fhandler_base
{ {
public: public:
fhandler_disk_file (); fhandler_disk_file ();
fhandler_disk_file (DWORD devtype);
int open (path_conv * real_path, int flags, mode_t mode); int open (path_conv * real_path, int flags, mode_t mode);
int close (); int close ();
@ -540,7 +542,7 @@ class fhandler_disk_file: public fhandler_base
int msync (HANDLE h, caddr_t addr, size_t len, int flags); int msync (HANDLE h, caddr_t addr, size_t len, int flags);
BOOL fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset, BOOL fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset,
DWORD size, void *address); DWORD size, void *address);
DIR *opendir (const char *dirname, path_conv& pc); DIR *opendir (path_conv& pc);
struct dirent *readdir (DIR *); struct dirent *readdir (DIR *);
off_t telldir (DIR *); off_t telldir (DIR *);
void seekdir (DIR *, off_t); void seekdir (DIR *, off_t);
@ -548,6 +550,24 @@ class fhandler_disk_file: public fhandler_base
int closedir (DIR *); int closedir (DIR *);
}; };
class fhandler_cygdrive: public fhandler_disk_file
{
int unit;
int ndrives;
const char *pdrive;
void set_drives ();
public:
bool iscygdrive_root () const { return !unit; }
fhandler_cygdrive (int unit);
DIR *opendir (path_conv& pc);
struct dirent *readdir (DIR *);
off_t telldir (DIR *);
void seekdir (DIR *, off_t);
void rewinddir (DIR *);
int closedir (DIR *);
int __stdcall fstat (struct stat *buf, path_conv *pc) __attribute__ ((regparm (3)));
};
class fhandler_serial: public fhandler_base class fhandler_serial: public fhandler_base
{ {
private: private:
@ -591,12 +611,6 @@ class fhandler_serial: public fhandler_base
select_record *select_except (select_record *s); select_record *select_except (select_record *s);
}; };
class fhandler_cygdrive: public fhandler_disk_file
{
public:
fhandler_cygdrive ();
};
#define acquire_output_mutex(ms) \ #define acquire_output_mutex(ms) \
__acquire_output_mutex (__PRETTY_FUNCTION__, __LINE__, ms); __acquire_output_mutex (__PRETTY_FUNCTION__, __LINE__, ms);

View File

@ -338,8 +338,13 @@ fhandler_disk_file::fstat_helper (struct stat *buf)
return 0; return 0;
} }
fhandler_disk_file::fhandler_disk_file (DWORD devtype) :
fhandler_base (devtype)
{
}
fhandler_disk_file::fhandler_disk_file () : fhandler_disk_file::fhandler_disk_file () :
fhandler_base (FH_DISK) fhandler_base (FH_DISK)
{ {
} }
@ -348,7 +353,7 @@ fhandler_disk_file::open (path_conv *real_path, int flags, mode_t mode)
{ {
if (real_path->case_clash && flags & O_CREAT) if (real_path->case_clash && flags & O_CREAT)
{ {
debug_printf ("Caseclash detected."); debug_printf ("case clash detected");
set_errno (ECASECLASH); set_errno (ECASECLASH);
return 0; return 0;
} }
@ -564,14 +569,13 @@ fhandler_disk_file::lock (int cmd, struct flock *fl)
} }
DIR * DIR *
fhandler_disk_file::opendir (const char *name, path_conv& real_name) fhandler_disk_file::opendir (path_conv& real_name)
{ {
struct stat statbuf;
DIR *dir; DIR *dir;
DIR *res = NULL; DIR *res = NULL;
size_t len; size_t len;
if (fstat (&statbuf, &real_name) ||!(statbuf.st_mode & S_IFDIR)) if (!real_name.isdir ())
set_errno (ENOTDIR); set_errno (ENOTDIR);
else if ((len = strlen (real_name))> MAX_PATH - 3) else if ((len = strlen (real_name))> MAX_PATH - 3)
set_errno (ENAMETOOLONG); set_errno (ENAMETOOLONG);
@ -606,12 +610,12 @@ fhandler_disk_file::opendir (const char *name, path_conv& real_name)
dir->__d_cookie = __DIRENT_COOKIE; dir->__d_cookie = __DIRENT_COOKIE;
dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE; dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
dir->__d_position = 0; dir->__d_position = 0;
dir->__d_dirhash = statbuf.st_ino; dir->__d_dirhash = get_namehash ();
res = dir; res = dir;
} }
syscall_printf ("%p = opendir (%s)", res, name); syscall_printf ("%p = opendir (%s)", res, get_name ());
return res; return res;
} }
@ -702,7 +706,7 @@ fhandler_disk_file::readdir (DIR *dir)
dir->__d_dirent->d_ino = hash_path_name (dino, buf.cFileName); dir->__d_dirent->d_ino = hash_path_name (dino, buf.cFileName);
} }
++dir->__d_position; dir->__d_position++;
res = dir->__d_dirent; res = dir->__d_dirent;
syscall_printf ("%p = readdir (%p) (%s)", syscall_printf ("%p = readdir (%p) (%s)",
&dir->__d_dirent, dir, buf.cFileName); &dir->__d_dirent, dir, buf.cFileName);
@ -720,7 +724,7 @@ fhandler_disk_file::seekdir (DIR *dir, off_t loc)
{ {
rewinddir (dir); rewinddir (dir);
while (loc > dir->__d_position) while (loc > dir->__d_position)
if (! readdir (dir)) if (!readdir (dir))
break; break;
} }
@ -748,3 +752,100 @@ fhandler_disk_file::closedir (DIR *dir)
syscall_printf ("%d = closedir (%p)", res, dir); syscall_printf ("%d = closedir (%p)", res, dir);
return 0; return 0;
} }
fhandler_cygdrive::fhandler_cygdrive (int unit) :
fhandler_disk_file (FH_CYGDRIVE), unit (unit), ndrives (0), pdrive (NULL)
{
}
#define DRVSZ sizeof ("x:\\")
void
fhandler_cygdrive::set_drives ()
{
const int len = 1 + 26 * DRVSZ;
win32_path_name = (char *) crealloc (win32_path_name, len);
ndrives = GetLogicalDriveStrings (len, win32_path_name) / DRVSZ;
pdrive = win32_path_name;
}
int
fhandler_cygdrive::fstat (struct stat *buf, path_conv *pc)
{
if (!iscygdrive_root ())
return fhandler_disk_file::fstat (buf, pc);
buf->st_mode = S_IFDIR | 0555;
if (!ndrives)
set_drives ();
buf->st_nlink = ndrives;
return 0;
}
DIR *
fhandler_cygdrive::opendir (path_conv& real_name)
{
DIR *dir;
dir = fhandler_disk_file::opendir (real_name);
if (dir && iscygdrive_root () && !ndrives)
set_drives ();
return dir;
}
struct dirent *
fhandler_cygdrive::readdir (DIR *dir)
{
if (!iscygdrive_root ())
return fhandler_disk_file::readdir (dir);
if (!pdrive || !*pdrive)
{
set_errno (ENMFILE);
return NULL;
}
*dir->__d_dirent->d_name = cyg_tolower (*pdrive);
dir->__d_dirent->d_name[1] = '\0';
dir->__d_position++;
pdrive += DRVSZ;
syscall_printf ("%p = readdir (%p) (%s)", &dir->__d_dirent, dir,
dir->__d_dirent->d_name);
return dir->__d_dirent;
}
off_t
fhandler_cygdrive::telldir (DIR *dir)
{
return fhandler_disk_file::telldir (dir);
}
void
fhandler_cygdrive::seekdir (DIR *dir, off_t loc)
{
if (!iscygdrive_root ())
return fhandler_disk_file::seekdir (dir, loc);
for (pdrive = win32_path_name, dir->__d_position = -1; *pdrive; pdrive += DRVSZ)
if (++dir->__d_position >= loc)
break;
return;
}
void
fhandler_cygdrive::rewinddir (DIR *dir)
{
if (!iscygdrive_root ())
return fhandler_disk_file::rewinddir (dir);
pdrive = win32_path_name;
dir->__d_position = 0;
return;
}
int
fhandler_cygdrive::closedir (DIR *dir)
{
if (!iscygdrive_root ())
return fhandler_disk_file::closedir (dir);
pdrive = win32_path_name;
return -1;
}

View File

@ -114,7 +114,7 @@ int pcheck_case = PCHECK_RELAXED; /* Determines the case check behaviour. */
(path_prefix_p (mount_table->cygdrive, (path), mount_table->cygdrive_len)) (path_prefix_p (mount_table->cygdrive, (path), mount_table->cygdrive_len))
#define iscygdrive_device(path) \ #define iscygdrive_device(path) \
(iscygdrive(path) && isalpha(path[mount_table->cygdrive_len]) && \ (isalpha(path[mount_table->cygdrive_len]) && \
(isdirsep(path[mount_table->cygdrive_len + 1]) || \ (isdirsep(path[mount_table->cygdrive_len + 1]) || \
!path[mount_table->cygdrive_len + 1])) !path[mount_table->cygdrive_len + 1]))
@ -482,12 +482,19 @@ path_conv::check (const char *src, unsigned opt,
/* devn should not be a device. If it is, then stop parsing now. */ /* devn should not be a device. If it is, then stop parsing now. */
if (devn != FH_BAD) if (devn != FH_BAD)
{ {
if (component) if (devn == FH_CYGDRIVE)
fileattr = !unit ? FILE_ATTRIBUTE_DIRECTORY
: GetFileAttributes (full_path);
else
{ {
error = ENOTDIR; if (component)
return; {
error = ENOTDIR;
return;
}
fileattr = 0;
} }
fileattr = 0;
goto out; /* Found a device. Stop parsing. */ goto out; /* Found a device. Stop parsing. */
} }
@ -510,7 +517,7 @@ path_conv::check (const char *src, unsigned opt,
if ((opt & PC_SYM_IGNORE) && pcheck_case == PCHECK_RELAXED) if ((opt & PC_SYM_IGNORE) && pcheck_case == PCHECK_RELAXED)
{ {
fileattr = GetFileAttributesA (full_path); fileattr = GetFileAttributes (full_path);
goto out; goto out;
} }
@ -1237,21 +1244,18 @@ conv_path_list (const char *src, char *dst, int to_posix_p)
char *srcbuf = (char *) alloca (strlen (src) + 1); char *srcbuf = (char *) alloca (strlen (src) + 1);
do for (;;)
{ {
s = strccpy (srcbuf, &src, src_delim); s = strccpy (srcbuf, &src, src_delim);
int len = s - srcbuf; int len = s - srcbuf;
if (len >= MAX_PATH) if (len >= MAX_PATH)
srcbuf[MAX_PATH - 1] = '\0'; srcbuf[MAX_PATH - 1] = '\0';
(*conv_fn) (len ? srcbuf : ".", d); (*conv_fn) (len ? srcbuf : ".", d);
src += len; if (!*src++)
if (*src) break;
{ d = strchr (d, '\0');
d = strchr (d, '\0'); *d++ = dst_delim;
*d++ = dst_delim;
}
} }
while (*src++);
} }
/* init: Initialize the mount table. */ /* init: Initialize the mount table. */
@ -1374,11 +1378,21 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
/* Check if the cygdrive prefix was specified. If so, just strip /* Check if the cygdrive prefix was specified. If so, just strip
off the prefix and transform it into an MS-DOS path. */ off the prefix and transform it into an MS-DOS path. */
MALLOC_CHECK; MALLOC_CHECK;
if (iscygdrive_device (pathbuf)) if (iscygdrive (pathbuf))
{ {
if (!cygdrive_win32_path (pathbuf, dst, 0)) int n = mount_table->cygdrive_len - 1;
if (!pathbuf[n] ||
(pathbuf[n] == '/' && pathbuf[n + 1] == '.' && !pathbuf[n + 2]))
{
unit = 0;
dst[0] = '\0';
}
else if (!cygdrive_win32_path (pathbuf, dst, unit))
return ENOENT; return ENOENT;
*flags = cygdrive_flags; else
*flags = cygdrive_flags;
if (mount_table->cygdrive_len > 1)
devn = FH_CYGDRIVE;
goto out; goto out;
} }
@ -1497,15 +1511,23 @@ mount_info::cygdrive_posix_path (const char *src, char *dst, int trailing_slash_
} }
int int
mount_info::cygdrive_win32_path (const char *src, char *dst, int trailing_slash_p) mount_info::cygdrive_win32_path (const char *src, char *dst, int& unit)
{ {
int res;
const char *p = src + cygdrive_len; const char *p = src + cygdrive_len;
if (!isalpha (*p) || (!isdirsep (p[1]) && p[1])) if (!isalpha (*p) || (!isdirsep (p[1]) && p[1]))
return 0; {
dst[0] = *p; res = unit = -1;
dst[1] = ':'; dst[0] = '\0';
strcpy (dst + 2, p + 1); }
backslashify (dst, dst, trailing_slash_p || !dst[2]); else
{
dst[0] = cyg_tolower (*p);
dst[1] = ':';
strcpy (dst + 2, p + 1);
backslashify (dst, dst, !dst[2]);
unit = dst[0];
}
debug_printf ("src '%s', dst '%s'", src, dst); debug_printf ("src '%s', dst '%s'", src, dst);
return 1; return 1;
} }
@ -2305,7 +2327,7 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
/* Remove drivenum from list if we see a x: style path */ /* Remove drivenum from list if we see a x: style path */
if (strlen (native_path) == 2 && native_path[1] == ':') if (strlen (native_path) == 2 && native_path[1] == ':')
{ {
int drivenum = tolower (native_path[0]) - 'a'; int drivenum = cyg_tolower (native_path[0]) - 'a';
if (drivenum >= 0 && drivenum <= 31) if (drivenum >= 0 && drivenum <= 31)
available_drives &= ~(1 << drivenum); available_drives &= ~(1 << drivenum);
} }
@ -2657,7 +2679,7 @@ symlink (const char *topath, const char *frompath)
if ((cp && cp[1] == '.') || *win32_path == '.') if ((cp && cp[1] == '.') || *win32_path == '.')
attr |= FILE_ATTRIBUTE_HIDDEN; attr |= FILE_ATTRIBUTE_HIDDEN;
#endif #endif
SetFileAttributesA (win32_path.get_win32 (), attr); SetFileAttributes (win32_path.get_win32 (), attr);
if (win32_path.fs_fast_ea ()) if (win32_path.fs_fast_ea ())
set_symlink_ea (win32_path, topath); set_symlink_ea (win32_path, topath);
@ -2886,13 +2908,13 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
while (suffix.next ()) while (suffix.next ())
{ {
error = 0; error = 0;
fileattr = GetFileAttributesA (suffix.path); fileattr = GetFileAttributes (suffix.path);
if (fileattr == (DWORD) -1) if (fileattr == (DWORD) -1)
{ {
/* The GetFileAttributesA call can fail for reasons that don't /* The GetFileAttributes call can fail for reasons that don't
matter, so we just return 0. For example, getting the matter, so we just return 0. For example, getting the
attributes of \\HOST will typically fail. */ attributes of \\HOST will typically fail. */
debug_printf ("GetFileAttributesA (%s) failed", suffix.path); debug_printf ("GetFileAttributes (%s) failed", suffix.path);
error = geterrno_from_win_error (GetLastError (), EACCES); error = geterrno_from_win_error (GetLastError (), EACCES);
continue; continue;
} }

View File

@ -97,7 +97,7 @@ class mount_info
void mount_slash (); void mount_slash ();
void to_registry (); void to_registry ();
int cygdrive_win32_path (const char *src, char *dst, int trailing_slash_p); int cygdrive_win32_path (const char *src, char *dst, int& unit);
void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p); void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p);
void read_cygdrive_info_from_registry (); void read_cygdrive_info_from_registry ();
}; };