From 5dda1f7e2cb7cf52f52c31099c680ff37d3456e5 Mon Sep 17 00:00:00 2001 From: Bernhard Rosenkraenzer Date: Mon, 23 Jul 2001 18:09:41 +0000 Subject: [PATCH] Set executable permissions when creating .exe/.com files. --- files/file.c | 57 +++++++++++++++++++++++++++++++++------------------ server/file.c | 9 ++++++-- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/files/file.c b/files/file.c index cf9c8f6e382..83fdf71b78a 100644 --- a/files/file.c +++ b/files/file.c @@ -1938,6 +1938,17 @@ DWORD WINAPI GetFileType( HANDLE hFile ) } +/* check if a file name is for an executable file (.exe or .com) */ +inline static BOOL is_executable( const char *name ) +{ + int len = strlen(name); + + if (len < 4) return FALSE; + return (!strcasecmp( name + len - 4, ".exe" ) || + !strcasecmp( name + len - 4, ".com" )); +} + + /************************************************************************** * MoveFileExA (KERNEL32.@) */ @@ -1992,6 +2003,19 @@ BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag ) FILE_SetDosError(); return FALSE; } + if (is_executable( full_name1.long_name ) != is_executable( full_name2.long_name )) + { + struct stat fstat; + if (stat( full_name2.long_name, &fstat ) != -1) + { + if (is_executable( full_name2.long_name )) + /* set executable bit where read bit is set */ + fstat.st_mode |= (fstat.st_mode & 0444) >> 2; + else + fstat.st_mode &= ~0111; + chmod( full_name2.long_name, fstat.st_mode ); + } + } return TRUE; } else /* fn2 == NULL means delete source */ @@ -2045,41 +2069,34 @@ BOOL WINAPI MoveFileA( LPCSTR fn1, LPCSTR fn2 ) DOS_FULL_NAME full_name1, full_name2; struct stat fstat; - TRACE("(%s,%s)\n", fn1, fn2 ); if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE; if (DOSFS_GetFullName( fn2, TRUE, &full_name2 )) { - /* The new name must not already exist */ + /* The new name must not already exist */ SetLastError(ERROR_ALREADY_EXISTS); return FALSE; } if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE; if (full_name1.drive == full_name2.drive) /* move */ - if (rename( full_name1.long_name, full_name2.long_name ) == -1) + return MoveFileExA( fn1, fn2, MOVEFILE_COPY_ALLOWED ); + + /* copy */ + if (stat( full_name1.long_name, &fstat )) { + WARN("Invalid source file %s\n", + full_name1.long_name); FILE_SetDosError(); return FALSE; } - else return TRUE; - else /*copy */ { - if (stat( full_name1.long_name, &fstat )) - { - WARN("Invalid source file %s\n", - full_name1.long_name); - FILE_SetDosError(); - return FALSE; - } - if (S_ISDIR(fstat.st_mode)) { - /* No Move for directories across file systems */ - /* FIXME: Use right error code */ - SetLastError( ERROR_GEN_FAILURE ); - return FALSE; - } - else - return CopyFileA(fn1, fn2, TRUE); /*fail, if exist */ + if (S_ISDIR(fstat.st_mode)) { + /* No Move for directories across file systems */ + /* FIXME: Use right error code */ + SetLastError( ERROR_GEN_FAILURE ); + return FALSE; } + return CopyFileA(fn1, fn2, TRUE); /*fail, if exist */ } diff --git a/server/file.c b/server/file.c index 4c5c5f8e8d8..8a966303dc8 100644 --- a/server/file.c +++ b/server/file.c @@ -126,6 +126,7 @@ static struct file *create_file( const char *nameptr, size_t len, unsigned int a struct stat st; char *name; int fd = -1; + mode_t mode; if (!(name = mem_alloc( len + 1 ))) return NULL; memcpy( name, nameptr, len ); @@ -151,10 +152,14 @@ static struct file *create_file( const char *nameptr, size_t len, unsigned int a case GENERIC_WRITE: flags |= O_WRONLY; break; case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break; } + mode = (attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666; + + if (len >= 4 && + (!strcasecmp( name + len - 4, ".exe" ) || !strcasecmp( name + len - 4, ".com" ))) + mode |= 0111; /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */ - if ((fd = open( name, flags | O_NONBLOCK | O_LARGEFILE, - (attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666 )) == -1) + if ((fd = open( name, flags | O_NONBLOCK | O_LARGEFILE, mode )) == -1 ) goto file_error; /* refuse to open a directory */ if (fstat( fd, &st ) == -1) goto file_error;