Проверить тип исполняемого файла

Я пишу эту программу, которая проверяет, является ли файл исполняемым, и если да, то проверяет, является ли он двоичным файлом ELF или сценарием оболочки.

#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>

int Search_in_File(char *fname, char *str);

int main(int argc, char **argv)
{
    if(argc < 2){
        printf("The path to the file isn");
        return 1;
    }

    struct stat fileStat;

    if(stat(argv[1],&fileStat) < 0){
        printf("errorn");
        return 1;
    }

    if(S_ISREG(fileStat.st_mode)){
        if(fileStat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
        {
            printf("The file is executable ");
            Search_in_File(argv[1], "#!");
            Search_in_File(argv[1], "ELF");
        }
        else
        {
            printf("The file is not executable.n");
        }
    }
    else
        printf("Not a filen");
    return 0;
}

int Search_in_File(char *fname, char *str) {
    FILE *fp;
    char temp[512];

    if((fp = fopen(fname, "r")) == NULL) {
        return(-1);
    }

    while(fgets(temp, 512, fp) != NULL) {
        if((strstr(temp, str)) != NULL) {
            if(strcmp(str, "#!")==0)
                printf("shell type.");
            else if(strcmp(str, "ELF")==0)
                printf(" ELF.");
        }
    }
    printf("n");
    if(fp) {
        fclose(fp);
    }
    return(0);
}

1 ответ
1

if(argc < 2){
    printf("The path to the file isn");
    return 1;
}

Сообщение об ошибке незакончено (достаточно, чтобы missing отсутствует), и он должен перейти в stderr, нет stdout.

if(stat(argv[1],&fileStat) < 0){
    printf("errorn");
    return 1;
}

Мы снова пишем не в тот поток. И мы могли бы сделать более информативное сообщение, например perror(argv[1]).

        Search_in_File(argv[1], "#!");
        Search_in_File(argv[1], "ELF");

Каждый из этих двух вызовов открывает файл для чтения. Возможно, лучше открыть файл только один раз. Почему мы каждый раз игнорируем возвращаемое значение?

while(fgets(temp, 512, fp) != NULL) {
    if((strstr(temp, str)) != NULL) {
        ⋮
    }
}

Этот код не будет соответствовать, если строка поиска охватывает 512-байтовую границу. Но почему мы все равно ищем весь файл? Эти магические строки имеют значение только в качестве первых символов и ничего не говорят нам, если они встречаются позже в файле. Мы могли бы сделать это намного проще:

if (fread(temp, 4, 1, fp) == 1
    && strncmp(temp, str, strlen(str)) == 0) {
    ⋮
}
        if(strcmp(str, "#!")==0)
            printf("shell type.");
        else if(strcmp(str, "ELF")==0)
            printf(" ELF.");

Вместо сопоставления строк str аргумент, почему бы просто не передать дополнительный аргумент, определяющий строку для печати? Тогда есть только одно место, где можно изменить, когда вы добавляете новый тест.

if(fp) {
    fclose(fp);
}

На данный момент мы знаем, что fp не равно нулю, поскольку мы уже вернулись, если это не так.

О, и исполняемый файл, который начинается с #! может быть интерпретируемым исполняемым файлом любого типа (например, скриптом Python или Sed), не обязательно ракушка сценарий. Не уверен, что это задумано (это ваше описание или программа, которую нужно настроить?).

  • спасибо большое, полезно. Но может ли новое решение, другой код, другой пример?

    — Нострадамус


  • Да, вы можете опубликовать свое новое решение — просто задайте новый вопрос. Я посмотрю, если не буду слишком занят.

    — Тоби Спейт

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *