diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index 60aa5b5b7ba..145fc008a92 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -158,6 +158,17 @@ static inline BOOL is_invalid_dos_char( WCHAR ch ) return strchrW( invalid_chars, ch ) != NULL; } +/* check if the device can be a mounted volume */ +static inline int is_valid_mounted_device( struct stat *st ) +{ +#if defined(linux) || defined(__sun__) + return S_ISBLK( st->st_mode ); +#else + /* disks are char devices on *BSD */ + return S_ISCHR( st->st_mode ); +#endif +} + /*********************************************************************** * get_default_com_device * @@ -565,6 +576,25 @@ static char *get_device_mount_point( dev_t dev ) endmntent( f ); } RtlLeaveCriticalSection( &dir_section ); +#elif defined(__APPLE__) + struct statfs *entry; + struct stat st; + int i, size; + + RtlEnterCriticalSection( &dir_section ); + + size = getmntinfo( &entry, MNT_NOWAIT ); + for (i = 0; i < size; i++) + { + if (stat( entry[i].f_mntfromname, &st ) == -1) continue; + if (S_ISBLK(st.st_mode) && st.st_rdev == dev) + { + ret = RtlAllocateHeap( GetProcessHeap(), 0, strlen(entry[i].f_mntfromname) + 1 ); + if (ret) strcpy( ret, entry[i].f_mntfromname ); + break; + } + } + RtlLeaveCriticalSection( &dir_section ); #else static int warned; if (!warned++) FIXME( "unmounting devices not supported on this platform\n" ); @@ -1760,13 +1790,17 @@ NTSTATUS DIR_unmount_device( HANDLE handle ) struct stat st; char *mount_point = NULL; - if (fstat( unix_fd, &st ) == -1 || !S_ISBLK(st.st_mode)) + if (fstat( unix_fd, &st ) == -1 || !is_valid_mounted_device( &st )) status = STATUS_INVALID_PARAMETER; else { if ((mount_point = get_device_mount_point( st.st_rdev ))) { +#ifdef __APPLE__ + static const char umount[] = "diskutil unmount >/dev/null 2>&1 "; +#else static const char umount[] = "umount >/dev/null 2>&1 "; +#endif char *cmd = RtlAllocateHeap( GetProcessHeap(), 0, strlen(mount_point)+sizeof(umount)); if (cmd) { diff --git a/server/fd.c b/server/fd.c index 5f172a9ee21..e422eeae846 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1780,6 +1780,16 @@ void no_cancel_async( struct fd *fd ) set_error( STATUS_OBJECT_TYPE_MISMATCH ); } +static inline int is_valid_mounted_device( struct stat *st ) +{ +#if defined(linux) || defined(__sun__) + return S_ISBLK( st->st_mode ); +#else + /* disks are char devices on *BSD */ + return S_ISCHR( st->st_mode ); +#endif +} + /* close all Unix file descriptors on a device to allow unmounting it */ static void unmount_device( struct fd *device_fd ) { @@ -1792,7 +1802,7 @@ static void unmount_device( struct fd *device_fd ) if (unix_fd == -1) return; - if (fstat( unix_fd, &st ) == -1 || !S_ISBLK( st.st_mode )) + if (fstat( unix_fd, &st ) == -1 || !is_valid_mounted_device( &st )) { set_error( STATUS_INVALID_PARAMETER ); return;