Set executable permissions when creating .exe/.com files.
This commit is contained in:
parent
ff584e4d9c
commit
5dda1f7e2c
37
files/file.c
37
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,7 +2069,6 @@ 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;
|
||||
|
@ -2057,13 +2080,9 @@ BOOL WINAPI MoveFileA( LPCSTR fn1, LPCSTR fn2 )
|
|||
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)
|
||||
{
|
||||
FILE_SetDosError();
|
||||
return FALSE;
|
||||
}
|
||||
else return TRUE;
|
||||
else /*copy */ {
|
||||
return MoveFileExA( fn1, fn2, MOVEFILE_COPY_ALLOWED );
|
||||
|
||||
/* copy */
|
||||
if (stat( full_name1.long_name, &fstat ))
|
||||
{
|
||||
WARN("Invalid source file %s\n",
|
||||
|
@ -2077,9 +2096,7 @@ BOOL WINAPI MoveFileA( LPCSTR fn1, LPCSTR fn2 )
|
|||
SetLastError( ERROR_GEN_FAILURE );
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
return CopyFileA(fn1, fn2, TRUE); /*fail, if exist */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue