From: "Gabriel Ivăncescu" Subject: [PATCH resend] server: Try to retrieve the unix name on handles created from file descriptors. Message-Id: <70d7f27dc6a415a1f230c91ccfa64d6cc63952f6.1600698021.git.gabrielopcode@gmail.com> Date: Mon, 21 Sep 2020 17:27:00 +0300 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46070 Signed-off-by: Gabriel Ivăncescu --- 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 a88ba39..b882600 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2006,6 +2006,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 38260cf..1d1714d 100644 --- a/server/file.c +++ b/server/file.c @@ -144,6 +144,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 b02c9fe..f0df3d6 100644 --- a/server/file.h +++ b/server/file.h @@ -22,6 +22,7 @@ #define __WINE_SERVER_FILE_H #include +#include #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 ); -- 2.21.0