Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46070 Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
It also fixes the game Unity of Command II (same bug).
server/fd.c | 39 +++++++++++++++++++++++++++++++++++++++ server/file.c | 1 + server/file.h | 2 ++ 3 files changed, 42 insertions(+)
diff --git a/server/fd.c b/server/fd.c index 5d80e21..2530287 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1922,6 +1922,45 @@ struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, int unix_fd, s return NULL; }
+void set_unix_name_of_fd( struct fd *fd, const struct stat *fd_st ) +{ +#ifdef __linux__ + static const char procfs_fmt[] = "/proc/self/fd/%d"; + + char path[PATH_MAX], procfs_path[sizeof(procfs_fmt) - 2 /* %d */ + 11]; + struct stat path_st; + ssize_t len; + + sprintf( procfs_path, procfs_fmt, fd->unix_fd ); + len = readlink( procfs_path, path, sizeof(path) ); + if (len == -1 || len >= sizeof(path) ) + return; + path[len] = '\0'; + + /* Make sure it's an absolute path, has at least one hardlink, and the same inode */ + if (path[0] != '/' || stat( path, &path_st ) || path_st.st_nlink < 1 || + path_st.st_dev != fd_st->st_dev || path_st.st_ino != fd_st->st_ino) + return; + + if (!(fd->unix_name = mem_alloc( len + 1 ))) + return; + memcpy( fd->unix_name, path, len + 1 ); + +#elif defined(F_GETPATH) + char path[PATH_MAX]; + size_t size; + + if (fcntl( fd->unix_fd, F_GETPATH, path ) == -1 || path[0] != '/') + return; + + size = strlen(path) + 1; + if (!(fd->unix_name = mem_alloc( size ))) + return; + memcpy( fd->unix_name, path, size ); + +#endif +} + /* retrieve the object that is using an fd */ void *get_fd_user( struct fd *fd ) { diff --git a/server/file.c b/server/file.c index 71b8448..1db6c7c 100644 --- a/server/file.c +++ b/server/file.c @@ -145,6 +145,7 @@ struct file *create_file_for_fd( int fd, unsigned int access, unsigned int shari release_object( file ); return NULL; } + set_unix_name_of_fd( file->fd, &st ); allow_fd_caching( file->fd ); return file; } diff --git a/server/file.h b/server/file.h index 4341ad3..5c6054b 100644 --- a/server/file.h +++ b/server/file.h @@ -22,6 +22,7 @@ #define __WINE_SERVER_FILE_H
#include <sys/types.h> +#include <sys/stat.h>
#include "object.h"
@@ -82,6 +83,7 @@ extern struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t unsigned int access, unsigned int sharing, unsigned int options ); extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, int unix_fd, struct object *user, unsigned int options ); +extern void set_unix_name_of_fd( struct fd *fd, const struct stat *fd_st ); extern struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing, unsigned int options ); extern struct fd *get_fd_object_for_mapping( struct fd *fd, unsigned int access, unsigned int sharing );