Я пишу эту программу, которая проверяет, является ли файл исполняемым, и если да, то проверяет, является ли он двоичным файлом 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 ответ
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), не обязательно ракушка сценарий. Не уверен, что это задумано (это ваше описание или программа, которую нужно настроить?).
спасибо большое, полезно. Но может ли новое решение, другой код, другой пример?
— Нострадамус
Да, вы можете опубликовать свое новое решение — просто задайте новый вопрос. Я посмотрю, если не буду слишком занят.
— Тоби Спейт