opendir не получает содержимое буфера char * на C языке? - PullRequest
2 голосов
/ 06 января 2020

Я пытаюсь прочитать файлы из данного каталога, используя функции opendir / readdir из C в Linux, если файлы соответствуют определенным параметрам например, размер и тип будут скопированы в определенный каталог, каталог, из которого читаются файлы, и место назначения и размер считываются из файла ". ini" , проблема заключается в том, что я использую opendir с ie opendir (argv [1]) проблем нет, но если я получу значение из ". Ini" файла в символ *, который называется ie search_path и передать его opendir как opendir (search_path) код не работает, и я получаю сообщение "Нет такого файла или каталога", вот код:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>

#include "minIni.h"


#define sizearray(a) (sizeof(a) / sizeof((a)[0]))

/*Default values for minIni library function ini_gets*/
#define DEFAULT_FILE_SIZE "100000"
#define DEFAULT_FIREFOX_CACHE "~/.cache/mozilla/firefox/43ty8soo.default-release/cache2/entries/"
#define DEFAULT_CHROMIUM_CACHE "~/.cache/chromium/Default/Cache/"
#define DEFAULT_DEST_DIR "/home/newbee/found/"

/*Utility functions*/
void error(const char *s);
int OSCopyFile(const char *, const char *);
int interesting(char *);
int filesize(char *);
int get_config(char *browser, int *min_filesize, char *cache_dir, char *dest);

int main(int argc, char * argv[]){
  if (argc < 2) {
    fprintf(stderr, "Usage: %s <browser-name>\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  /*the only argument to the program is the browser in which cache*/
  /*we want the exploration.*/
  char *browser_name = argv[1];

  /*Here i call get_config, that function returns the minimum size for*/
  /*the files (min_file_size), where to search (cache), and where to*/
  /*put the files that met the requirements (dest_dir_conf).*/
  char *cache = malloc(PATH_MAX);
  char *dest_dir_conf = malloc(PATH_MAX);
  int min_file_size;
  int result_config = get_config(
      browser_name, &min_file_size, cache, dest_dir_conf);

  if (result_config != 1)
    exit(EXIT_FAILURE);

  DIR *dir;
  struct dirent *ent;
  printf("[DEBUG] %s\n", cache);
  /*And there is the problem, no matters if i pass the 'cache' variable*/
  /*or if i harcoded a string here, opendir failed and error is:*/
      /*No such file or directory*/
  chdir(cache);
  dir = opendir(cache);

  if (dir == NULL)
    error("Error");

  char *dest = NULL;
  int count = 0;

  while ((ent = readdir(dir)) != NULL) {
    if ((strcmp(ent->d_name, ".") != 0) && (strcmp(ent->d_name, "..") != 0)) {
      /*The interesting function determine if the file is of a given type and*/
      /*return 1 if true, and 0 if not.*/
      if ((interesting(ent->d_name))
          && (filesize(ent->d_name) >= min_file_size)) {
        dest = malloc(strlen(dest_dir_conf) + strlen(ent->d_name));
        strcpy(dest, dest_dir_conf);
        strcat(dest, ent->d_name);
        OSCopyFile(ent->d_name, dest);
        count++;
      }
    }
  }
  closedir(dir);
  printf("[Job finish, %d files was copied.]\n", count);

  return EXIT_SUCCESS;
}

/** errors info. **/
void error(const char *s) {
  perror(s);
  exit(EXIT_FAILURE);
}

/** get the file size. **/
int filesize(char *archivo) {
  FILE *fp;
  long fsize;

  fp = fopen(archivo, "r");
  if (fp) {
    fseek(fp, 0L, SEEK_END);
    fsize = ftell(fp);
    fclose(fp);
    return fsize;
  } 
  return -1;
}

/** copy files. **/
int OSCopyFile(const char *source, const char *destination) {
  int input, output;
  if ((input = open(source, O_RDONLY)) == -1)
    return -1;
  if ((output = creat(destination, 0660)) == -1) {
    close(input);
    return EXIT_FAILURE;
  }

#if defined(__APPLE__) || defined(__FreeBSD__)
  int result = fcopyfile(input, output, 0, COPYFILE_ALL);
#else
  off_t bytesCopied = 0;
  struct stat fileinfo = {0};
  fstat(input, &fileinfo);
  int result = sendfile(output, input, &bytesCopied, fileinfo.st_size);
#endif

  close(input);
  close(output);

  return result;
}

/** determine if the file is interesting (for me, at least ;) ). **/
int interesting(char *filename) {
  uint16_t type;
  FILE *f = fopen(filename, "r");
  if (!f) {
    printf("Error opening file '%s'.\n", filename);
    return 0;
  }

  fread(&type, sizeof(uint16_t), 1, f);
  fclose(f);

  switch (type) {
    case 0xD8FF:      // jpg
    case 0x5089:      // png
    case 0x4D42:      // bmp
    case 0x4952:      // webp
    case 0x4947:      // gif
    case 0x3F3C:      // possible svg.
    case 0x0000:      // possible mp4.
    case 0x5025:      // pdf.
      return 1;
    default:          // not interesting.
      return 0;
  }
}

/*Gets the configuration from a INI file*/
int get_config(
    char *browser, int *min_filesize, char *cache_dir, char *dest) {
  const char ini_file[] = "config.ini";
  char filesize_conf[100];
  long entry_length;

  entry_length = ini_gets("settings", "image_size_bytes", DEFAULT_FILE_SIZE,
      filesize_conf, sizearray(filesize_conf), ini_file);
  *min_filesize = atoi(filesize_conf);

  if (strcmp(browser, "firefox") == 0)
    entry_length = ini_gets("settings", "firefox_cache",
        DEFAULT_FIREFOX_CACHE, cache_dir, 255, ini_file);
  else if (strcmp(browser, "chromium") == 0)
    entry_length = ini_gets("settings", "chromium_cache",
        DEFAULT_CHROMIUM_CACHE, cache_dir, 255, ini_file);
  else {
    fprintf(stderr,
        "There is no configuration for %s browser.\n", browser);
    exit(EXIT_FAILURE);
  }

  entry_length = ini_gets("settings", "destination_dir", DEFAULT_DEST_DIR,
      dest, 255, ini_file);

  if (entry_length <= 0)
    return 0;

  return 1;
}

И есть проблема, не имеет значения, если я передам переменную 'cache' или если я здесь запрограммировал строку, opendir завершился ошибкой и ошибка : Нет такого файла или каталога

  dir = opendir(cache);

Код для чтения ". Ini" файлов из * 103 5 *https://www.compuphase.com/minini.htm, я немного новичок в этом, но я быстро учусь, поэтому, пожалуйста, помогите мне с этим.

1 Ответ

2 голосов
/ 06 января 2020

когда я использую opendir с ie opendir (argv [1]), проблем не возникает

Это потому, что argv[1] содержит расширенную версию ~/.cache/... благодаря оценке вызывающей оболочки до запускается исполняемый файл.

Но передача пути, подобного ~/.cache/... к opendir, не работает: C библиотека не оценивает ~ к пользовательскому каталогу или переменным среды.

Вы можете сделать его совместимым, явно протестировав ~ и заменив на getenv("HOME"), что-то вроде этого довольно небезопасного (но работающего) кода:

const char *s = "~/.cache/.something";
...
char aux[1024];
if (s[0]=='~')
{
   sprintf(aux,"%s%s",getenv("HOME"),s+1);
   s = aux;
}

теперь, если s начинается с ~, если будет оцениваться и заменяться на (будет указывать на) aux.

, если переменная должна быть возвращена вызывающей стороне, лучше использовать malloc для выделения строки, даже если замена не требуется (и free позже). Дело не в этом, но правильная обработка строк в C всегда сложна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...