For homework I have to write a C program and one of the things it has to do is check to see a file exists and if it is executable by the owner.
Using (stat(path[j], &sb) >= 0
I'm able to see if the file indicated by path[j] exists.
I've looked through man pages, a lot of questions and answers on stackoverflow, and several websites but I'm not able to wrap my head around exactly how to check if a file is executable using stat.
I thought it would be as simple as ((stat(path[j], &sb) >= 0) && (sb.st_mode > 0) && (S_IEXEC)
but as far as I can tell by testing it, it seems to ignore the fact that these files aren't executable.
I think that perhaps stat doesn't work the way I think it does. Assuming I use stat, how can I go about fixing this?
You just have to use S_IXUSR ( S_IEXEC is an old synonym of S_IXUSR ) to check if you have execute permission. Bitwise AND operator ( & ) checks whether the bits of S_IXUSR are set or not. (sb. st_mode & S_IXUSR) just making sure I got it.
The stat() function gets status information about a specified file and places it in the area of memory pointed to by the buf argument. If the named file is a symbolic link, stat() resolves the symbolic link.
An executable file (EXE file) is a computer file that contains an encoded sequence of instructions that the system can execute directly when the user clicks the file icon. Executable files commonly have an EXE file extension, but there are hundreds of other executable file formats.
You can indeed use stat
to do this. You just have to use S_IXUSR
(S_IEXEC
is an old synonym of S_IXUSR
) to check if you have execute permission. Bitwise AND
operator (&
) checks whether the bits of S_IXUSR
are set or not.
if (stat(file, &sb) == 0 && sb.st_mode & S_IXUSR)
/* executable */
else
/* non-executable */
Example:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (argc > 1) {
struct stat sb;
printf("%s is%s executable.\n", argv[1], stat(argv[1], &sb) == 0 &&
sb.st_mode & S_IXUSR ?
"" : " not");
}
return 0;
}
Try:
((stat(path[j], &sb) >= 0) && (sb.st_mode > 0) && (S_IEXEC & sb.st_mode)
We can leverage the libmagic.so library which comes along with the file(1) utility. It can detect all executable like ELF, bash/python/perl scripts etc
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "magic.h"
int
main(int argc, char **argv)
{
struct magic_set *ms;
const char *result;
char *desired;
size_t desired_len;
int i;
FILE *fp;
ms = magic_open(MAGIC_RAW);
if (ms == NULL) {
(void)fprintf(stderr, "ERROR opening MAGIC_NONE: out of memory\n");
return -1;
}
if (magic_load(ms, NULL) == -1) {
(void)fprintf(stderr, "ERROR loading with NULL file: %s\n", magic_error(ms));
return 11;
}
if (argc > 1) {
if (argc != 2) {
(void)fprintf(stderr, "Usage: ./a.out </path/to/file>\n");
} else {
if ((result = magic_file(ms, argv[1])) == NULL) {
(void)fprintf(stderr, "ERROR loading file %s: %s\n", argv[1], magic_error(ms));
return -1;
} else {
if (strstr(result, (const char *)"executable")) {
printf("%s: is executable\n", argv[1], result);
}
}
}
}
magic_close(ms);
return 0;
}
$ gcc test.c -I/path/to/magic.h /usr/lib/libmagic.so.1
./a.out /bin/ls
./a.out a.out
./a.out test.c
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With