From: Ralf Habacker ralf.habacker@freenet.de
--- server/fd.c | 68 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 26 deletions(-)
diff --git a/server/fd.c b/server/fd.c index e844441f55b..36fe4296edd 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1951,48 +1951,47 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam fd->unix_fd = open( name, O_RDONLY | (flags & ~(O_TRUNC | O_CREAT | O_EXCL)), *mode ); }
- /* POSIX requires that open(2) throws EOPNOTSUPP when `path` is a Unix - * socket. *BSD throws EOPNOTSUPP in this case and the additional case of - * O_SHLOCK or O_EXLOCK being passed when `path` resides on a filesystem - * without lock support. - * - * Contrary to POSIX, Linux returns ENXIO in this case, so we also check - * that error code here. */ - if (errno == EOPNOTSUPP || errno == ENXIO) - { - if (!stat(name, &st) && S_ISSOCK(st.st_mode) && (options & FILE_DELETE_ON_CLOSE)) - goto skip_open_fail; - } - if (fd->unix_fd == -1) { + if (stat( name, &st )) + { + file_set_error(); + goto error; + } + /* check for trailing slash on file path */ if ((errno == ENOENT || (errno == ENOTDIR && !(options & FILE_DIRECTORY_FILE))) && name[strlen(name) - 1] == '/') + { set_error( STATUS_OBJECT_NAME_INVALID ); + goto error; + } + + /* POSIX requires that open(2) throws EOPNOTSUPP when `path` is a Unix + * socket. *BSD throws EOPNOTSUPP in this case and the additional case of + * O_SHLOCK or O_EXLOCK being passed when `path` resides on a filesystem + * without lock support. + * + * Contrary to POSIX, Linux returns ENXIO in this case, so we also check + * that error code here. */ + else if ((errno == EOPNOTSUPP || errno == ENXIO) && S_ISSOCK(st.st_mode) && (options & FILE_DELETE_ON_CLOSE)) + ; else + { file_set_error(); - goto error; + goto error; + } } }
-skip_open_fail: fd->nt_name = dup_nt_name( root, nt_name, &fd->nt_namelen ); fd->unix_name = NULL; - if ((path = dup_fd_name( root, name ))) - { - fd->unix_name = realpath( path, NULL ); - free( path ); - } - - closed_fd->unix_fd = fd->unix_fd; - closed_fd->disp_flags = 0; - closed_fd->unix_name = fd->unix_name; + /* st was set from the file name if the file could not be opened */ if (fd->unix_fd != -1) fstat( fd->unix_fd, &st ); *mode = st.st_mode;
- /* only bother with an inode for normal files, directories, and socket files */ - if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISSOCK(st.st_mode)) + /* only bother with an inode for normal files and directories */ + if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) { unsigned int err; struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd ); @@ -2057,6 +2056,23 @@ skip_open_fail: ftruncate( fd->unix_fd, 0 ); } } + else if (S_ISSOCK(st.st_mode)) + { + if ((path = dup_fd_name( root, name ))) + { + fd->unix_name = realpath( path, NULL ); + free( path ); + } + + closed_fd->unix_fd = -1; + closed_fd->unix_name = fd->unix_name; + fd->closed->disp_flags = (options & FILE_DELETE_ON_CLOSE) ? + FILE_DISPOSITION_DELETE : 0; + fd->inode = 0; + fd->closed = closed_fd; + fd->cacheable = 1; + closed_fd = NULL; + } else /* special file */ { if (options & FILE_DELETE_ON_CLOSE) /* we can't unlink special files */