Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using stat to check if a file is executable in C

Tags:

c

stat

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?

like image 963
Joseph Kahn Avatar asked Oct 27 '12 08:10

Joseph Kahn


People also ask

How do you tell if a file is an executable in C?

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.

What does stat () do in C?

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.

What is executable file in C?

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.


3 Answers

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;
}   
like image 181
md5 Avatar answered Nov 16 '22 02:11

md5


Try:

((stat(path[j], &sb) >= 0) && (sb.st_mode > 0) && (S_IEXEC & sb.st_mode)

like image 40
alk Avatar answered Nov 16 '22 02:11

alk


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

like image 20
Nilesh Awate Avatar answered Nov 16 '22 02:11

Nilesh Awate