From ffcc67abf1b214ab38d95ad36c059918ca18a6b5 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 29 Apr 2004 20:04:48 +0000 Subject: [PATCH] Added auto-detection of DOS drive devices based on finding the corresponding mount point in /etc/mtab or /etc/fstab. --- configure | 2 + configure.ac | 1 + dlls/ntdll/cdrom.c | 24 +------ dlls/ntdll/directory.c | 139 ++++++++++++++++++++++++++++++++--------- dlls/ntdll/file.c | 5 ++ include/config.h.in | 3 + 6 files changed, 122 insertions(+), 52 deletions(-) diff --git a/configure b/configure index 755829de6f6..0ba7318068a 100755 --- a/configure +++ b/configure @@ -16280,6 +16280,7 @@ done + for ac_header in \ @@ -16307,6 +16308,7 @@ for ac_header in \ linux/serial.h \ linux/ucdrom.h \ machine/cpu.h \ + mntent.h \ netdb.h \ netinet/in.h \ netinet/in_systm.h \ diff --git a/configure.ac b/configure.ac index fba45a34676..5c0542016ed 100644 --- a/configure.ac +++ b/configure.ac @@ -1100,6 +1100,7 @@ AC_CHECK_HEADERS(\ linux/serial.h \ linux/ucdrom.h \ machine/cpu.h \ + mntent.h \ netdb.h \ netinet/in.h \ netinet/in_systm.h \ diff --git a/dlls/ntdll/cdrom.c b/dlls/ntdll/cdrom.c index 59dcedfff3c..42ce4b99306 100644 --- a/dlls/ntdll/cdrom.c +++ b/dlls/ntdll/cdrom.c @@ -382,11 +382,7 @@ static int CDROM_GetInterfaceInfo(int fd, int* port, int* iface, int* device,int { #if defined(linux) struct stat st; - if ( fstat(fd, &st) == -1 || ! S_ISBLK(st.st_mode)) - { - FIXME("cdrom not a block device!!!\n"); - return 0; - } + if ( fstat(fd, &st) == -1 || ! S_ISBLK(st.st_mode)) return 0; *port = 0; *iface = 0; *device = 0; @@ -501,23 +497,7 @@ static NTSTATUS CDROM_Open(int fd, int* dev) static NTSTATUS CDROM_GetStatusCode(int io) { if (io == 0) return STATUS_SUCCESS; - switch (errno) - { - case EIO: -#ifdef ENOMEDIUM - case ENOMEDIUM: -#endif - return STATUS_NO_MEDIA_IN_DEVICE; - case EPERM: - return STATUS_ACCESS_DENIED; - case EINVAL: - return STATUS_INVALID_PARAMETER; - /* case EBADF: Bad file descriptor */ - case EOPNOTSUPP: - return STATUS_NOT_SUPPORTED; - } - FIXME("Unmapped error code %d: %s\n", errno, strerror(errno)); - return STATUS_IO_DEVICE_ERROR; + return FILE_GetNtStatus(); } /****************************************************************** diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index 3e35eac6012..9828023bd96 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -27,9 +27,13 @@ #include #include #include +#ifdef HAVE_MNTENT_H +#include +#endif #include #include #include +#include #include #ifdef HAVE_SYS_IOCTL_H #include @@ -101,14 +105,14 @@ static int show_dot_files; /* at some point we may want to allow Winelib apps to set this */ static const int is_case_sensitive = FALSE; -static CRITICAL_SECTION chdir_section; +static CRITICAL_SECTION dir_section; static CRITICAL_SECTION_DEBUG critsect_debug = { - 0, 0, &chdir_section, + 0, 0, &dir_section, { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { 0, (DWORD)(__FILE__ ": chdir_section") } + 0, 0, { 0, (DWORD)(__FILE__ ": dir_section") } }; -static CRITICAL_SECTION chdir_section = { &critsect_debug, -1, 0, 0, 0, 0 }; +static CRITICAL_SECTION dir_section = { &critsect_debug, -1, 0, 0, 0, 0 }; /*********************************************************************** @@ -188,6 +192,90 @@ static char *get_default_lpt_device( int num ) } +/*********************************************************************** + * parse_mount_entries + * + * Parse mount entries looking for a given device. Helper for get_default_drive_device. + */ +#ifdef linux +static char *parse_mount_entries( FILE *f, dev_t dev, ino_t ino ) +{ + struct mntent *entry; + struct stat st; + char *device; + + while ((entry = getmntent( f ))) + { + if (stat( entry->mnt_dir, &st ) == -1) continue; + if (st.st_dev != dev || st.st_ino != ino) continue; + if (!strcmp( entry->mnt_type, "supermount" )) + { + if ((device = strstr( entry->mnt_opts, "dev=" ))) + { + char *p = strchr( device + 4, ',' ); + if (p) *p = 0; + return device + 4; + } + } + else + return entry->mnt_fsname; + } + return NULL; +} +#endif + +/*********************************************************************** + * get_default_drive_device + * + * Return the default device to use for a given drive mount point. + */ +static char *get_default_drive_device( const char *root ) +{ + char *ret = NULL; + +#ifdef linux + FILE *f; + char *device = NULL; + int fd, res = -1; + struct stat st; + + /* try to open it first to force it to get mounted */ + if ((fd = open( root, O_RDONLY | O_DIRECTORY )) != -1) + { + res = fstat( fd, &st ); + close( fd ); + } + /* now try normal stat just in case */ + if (res == -1) res = stat( root, &st ); + if (res == -1) return NULL; + + RtlEnterCriticalSection( &dir_section ); + + if ((f = fopen( "/etc/mtab", "r" ))) + { + device = parse_mount_entries( f, st.st_dev, st.st_ino ); + endmntent( f ); + } + /* look through fstab too in case it's not mounted (for instance if it's an audio CD) */ + if (!device && (f = fopen( "/etc/fstab", "r" ))) + { + device = parse_mount_entries( f, st.st_dev, st.st_ino ); + endmntent( f ); + } + if (device) + { + ret = RtlAllocateHeap( GetProcessHeap(), 0, strlen(device) + 1 ); + if (ret) strcpy( ret, device ); + } + RtlLeaveCriticalSection( &dir_section ); +#else + static int warned; + if (!warned++) FIXME( "auto detection of DOS devices not supported on this platform\n" ); +#endif + return ret; +} + + /*********************************************************************** * init_options * @@ -548,7 +636,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, io->Information = 0; - RtlEnterCriticalSection( &chdir_section ); + RtlEnterCriticalSection( &dir_section ); if (show_dir_symlinks == -1) init_options(); @@ -681,7 +769,7 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event, } else io->u.Status = FILE_GetNtStatus(); - RtlLeaveCriticalSection( &chdir_section ); + RtlLeaveCriticalSection( &dir_section ); wine_server_release_fd( handle, fd ); if (cwd != -1) close( cwd ); @@ -833,7 +921,7 @@ static NTSTATUS get_dos_device( const WCHAR *name, UINT name_len, ANSI_STRING *u { const char *config_dir = wine_get_config_dir(); struct stat st; - char *unix_name, *dev; + char *unix_name, *new_name, *dev; int i, unix_len; /* make sure the device name is ASCII */ @@ -888,31 +976,22 @@ static NTSTATUS get_dos_device( const WCHAR *name, UINT name_len, ANSI_STRING *u dev = NULL; /* last try */ continue; } - if (!strncmp( dev, "com", 3 )) + + new_name = NULL; + if (dev[1] == ':' && dev[2] == ':') /* drive device */ { - char *name = get_default_com_device( dev[3] - '0' ); - if (name) - { - RtlFreeHeap( GetProcessHeap(), 0, unix_name ); - unix_name = name; - unix_len = strlen(name) + 1; - dev = NULL; /* last try */ - continue; - } + dev[2] = 0; /* remove last ':' to get the drive mount point symlink */ + new_name = get_default_drive_device( unix_name ); } - if (!strncmp( dev, "lpt", 3 )) - { - char *name = get_default_lpt_device( dev[3] - '0' ); - if (name) - { - RtlFreeHeap( GetProcessHeap(), 0, unix_name ); - unix_name = name; - unix_len = strlen(name) + 1; - dev = NULL; /* last try */ - continue; - } - } - break; + else if (!strncmp( dev, "com", 3 )) new_name = get_default_com_device( dev[3] - '0' ); + else if (!strncmp( dev, "lpt", 3 )) new_name = get_default_lpt_device( dev[3] - '0' ); + + if (!new_name) break; + + RtlFreeHeap( GetProcessHeap(), 0, unix_name ); + unix_name = new_name; + unix_len = strlen(unix_name) + 1; + dev = NULL; /* last try */ } RtlFreeHeap( GetProcessHeap(), 0, unix_name ); return STATUS_OBJECT_NAME_NOT_FOUND; diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index b3b8e18b81a..ed354fb9648 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -284,6 +284,11 @@ NTSTATUS FILE_GetNtStatus(void) case ENOTEMPTY: return STATUS_DIRECTORY_NOT_EMPTY; case EPIPE: return STATUS_PIPE_BROKEN; case EIO: return STATUS_DEVICE_NOT_READY; +#ifdef ENOMEDIUM + case ENOMEDIUM: return STATUS_NO_MEDIA_IN_DEVICE; +#endif + case ENOTTY: + case EOPNOTSUPP:return STATUS_NOT_SUPPORTED; case ENOEXEC: /* ?? */ case ESPIPE: /* ?? */ case EEXIST: /* ?? */ diff --git a/include/config.h.in b/include/config.h.in index 8de0eddfa29..c339ea9b496 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -362,6 +362,9 @@ /* Define to 1 if you have the `mmap' function. */ #undef HAVE_MMAP +/* Define to 1 if you have the header file. */ +#undef HAVE_MNTENT_H + /* Define to 1 if the system has the type `mode_t'. */ #undef HAVE_MODE_T