hackedteam/vector-ipa

View on GitHub
src/file.c

Summary

Maintainability
Test Coverage
/*
    MODULE -- data handling module

    Copyright (C) Alberto Ornaghi

    $Id: file.c 3010 2010-10-18 12:51:24Z alor $
*/

#include <main.h>
#include <file.h>

#include <libgen.h>

#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>

/* protos */

char * get_full_path(const char *dir, const char *file);
char * get_local_path(const char *dir, const char *file);
char * get_path(const char *dir, const char *file);
FILE * open_data(char *dir, char *file, char *mode);
FILE * create_file(char *full_path, char *mode);

int file_open(char *path);
int file_read(int fd, void **buf, int len);
int file_close(int fd);
int file_relative_path(char *fullpath, char *base_path, char **relative_path);
int file_absolute_path(char *base_path, char *relative_path, char **fullpath);
int file_is_type(char *path, char *base_path, int flag);
off_t file_get_size(char *path, char *base_path);
char *file_substitute_path(char *fullpath, char *fromstring, char *tostring, char **result);

/*******************************************/

/*
 * add the prefix to a given filename
 */

char * get_full_path(const char *dir, const char *file)
{
   char *filename;
   int len = 256;

   SAFE_CALLOC(filename, len, sizeof(char));

   if (!strcmp(dir, "etc"))
      snprintf(filename, len, "%s/%s", INSTALL_SYSCONFDIR, file);

   if (!strcmp(dir, "vectors"))
       snprintf(filename, len, "%s/%s/%s", INSTALL_SYSCONFDIR, dir, file);

   DEBUG_MSG(D_VERBOSE, "get_full_path -- [%s] %s", dir, filename);

   return filename;
}

/*
 * add the local path to a given filename
 */

char * get_local_path(const char *dir, const char *file)
{
   char *filename;
   char *self_root = ".";

   SAFE_CALLOC(filename, strlen(self_root) + strlen("/share/vectors/") + strlen(file) + 1, sizeof(char));

   if (!strcmp(dir, "etc"))
      sprintf(filename, "%s/share/%s", self_root, file);

   if (!strcmp(dir, "vectors"))
      sprintf(filename, "%s/share/vectors/%s", self_root, file);

   DEBUG_MSG(D_VERBOSE, "get_local_path -- %s", filename);

   return filename;
}

/*
 * return the path of the file
 * search first globally, then locally
 */
char * get_path(const char *dir, const char *file)
{
   FILE *fd;
   char *filename = NULL;

   filename = get_full_path(dir, file);

   DEBUG_MSG(D_DEBUG, "get_path: %s", filename);

   fd = fopen(filename, FOPEN_READ_BIN);
   if (fd == NULL) {
      SAFE_FREE(filename);
      filename = get_local_path(dir, file);

      DEBUG_MSG(D_DEBUG, "get_path: dropping to %s", filename);
   } else {
      fclose(fd);
   }

   return filename;
}


/*
 * opens a file in the share directory.
 * first look in the installation path, then locally.
 */

FILE * open_data(char *dir, char *file, char *mode)
{
   FILE *fd;
   char *filename = NULL;

   filename = get_full_path(dir, file);

   DEBUG_MSG(D_INFO, "open_data %s", filename);

   fd = fopen(filename, mode);
   if (fd == NULL) {
      SAFE_FREE(filename);
      filename = get_local_path(dir, file);

      DEBUG_MSG(D_INFO, "open_data dropping to %s", filename);

      fd = fopen(filename, mode);
      /* don't check the fd, it is done by the caller */
   }

   SAFE_FREE(filename);

   return fd;
}

FILE * create_file(char *full_path, char *mode)
{
   FILE *fd;
   char *p;
   int ret;
   char *temp = strdup(full_path);
   char path[256];

   DEBUG_MSG(D_INFO, "create_file: [%s]", full_path);

   /* get only the directory path */
   temp = dirname(temp);

   /* save the current working dir */
   p = getcwd(path, sizeof(path));

   /* start always from the root */
   ret = chdir("/");

   /* create the complete subtree */
   for (p = strsep(&temp, "/"); p != NULL; p = strsep(&temp, "/")) {
      mkdir(p, 0755);
      ret = chdir(p);
   }

   /* restore the old working dir */
   ret = chdir(path);

   SAFE_FREE(temp);

   /* open the file and return the filedesc */
   fd = fopen(full_path, mode);

   if (fd == NULL)
      DEBUG_MSG(D_ERROR, "create_file: cannot create [%s]", full_path);

   return fd;
}

int file_open(char *path)
{
   int fd;

   fd = open(path, O_RDONLY);
   if (fd < 0)
      FATAL_ERROR("error opening file %s", path);

   return fd;
}

int file_read(int fd, void **buf, int len)
{
    int n = 0;

    while (n < len) {
        int ret;

        ret = read(fd, *buf + n, len - n);
        if (ret == -1)
            return -1;

        n += ret;
    }

    return n;
}

int file_close(int fd)
{
   int ret;

   ret = close(fd);
   if (ret == -1)
      FATAL_ERROR("%s: error closing file");

   return ESUCCESS;
}

int file_relative_path(char *fullpath, char *base_path, char **relative_path)
{
    char *laststr;

   if (!fullpath || !relative_path)
      FATAL_ERROR("%s: wrong parameters [fullpath %p][relative_path %p]",
        __func__,
        fullpath,
        relative_path
        );

    laststr = strstr(fullpath, base_path) + strlen(base_path);

    if (laststr[0] == '/')
        laststr++;

   SAFE_STRDUP(*relative_path, laststr);

    DEBUG_MSG(D_INFO, "%s [relative_path %s]", __func__, *relative_path);

   return ESUCCESS;
}

int file_absolute_path(char *base_path, char *relative_path, char **fullpath)
{
   if ( !fullpath )
      FATAL_ERROR("%s: NULL argument [fullpath %p]", __func__, fullpath);

   if ( !base_path )
      FATAL_ERROR("%s: NULL argument [basepath %p]", __func__, base_path);

   if ( !relative_path )
      FATAL_ERROR("%s: NULL argument [relative_path %p]", __func__, relative_path);

   if (base_path[0] != '/') {
      DEBUG_MSG(D_ERROR, "%s: base path argument does not begin with '/' [base_path %s]", __func__, base_path);
      return -EINVALID;
   }

   SAFE_CALLOC(*fullpath, 1, strlen(base_path) + strlen(relative_path) + 3);
   sprintf(*fullpath, "%s/%s", base_path, relative_path);

   return ESUCCESS;
}

int file_is_type(char *path, char *base_path, int flag)
{
    struct stat *s;
    char *fullpath;
    int ret;

    SAFE_CALLOC(s, 1, sizeof(struct stat));

    if (base_path) {
        ret = file_absolute_path(base_path, path, &fullpath);
        if (ret != ESUCCESS)
            return -EFAILURE;
    } else
        fullpath = path;

    ret = stat(fullpath, s);
    if (ret < 0) {
        // DEBUG_MSG(D_ERROR, "%s error performing stat on %s [%s]", __func__, fullpath, strerror(errno));
        return -EINVALID;
    }

    if (fullpath != path)
        SAFE_FREE(fullpath);

    if (s->st_mode & flag) {
        SAFE_FREE(s);
        return ESUCCESS;
    }

    SAFE_FREE(s);
    return -EFAILURE;
}

off_t file_get_size(char *path, char *base_path)
{
   struct stat *s;
   char *fullpath;
   int ret;
   off_t size;

   SAFE_CALLOC(s, 1, sizeof(struct stat));

   if (base_path) {
      ret = file_absolute_path(base_path, path, &fullpath);
      if (ret != ESUCCESS)
     return -EFAILURE;
   } else
      fullpath = path;

   ret = stat(fullpath, s);
   if (ret < 0) {
      DEBUG_MSG(D_ERROR, "error performing stat on %s", fullpath);
      return -EINVALID;
   }

   if (fullpath != path)
      SAFE_FREE(fullpath);

   size = s->st_size;

   SAFE_FREE(s);

   return size;
}

char *file_substitute_path(char *fullpath, char *fromstring, char *tostring, char **result)
{
    u_int size;
    char *fsptr; // fromstring pointer

    // size of final string, without null termination
    size = strlen(fullpath) - strlen(fromstring) + strlen(tostring);

    SAFE_CALLOC(*result, 1, size + 1);

    fsptr = strstr(fullpath, fromstring);
    strlcpy(*result, fullpath, fsptr - fullpath);
    strlcpy(*result + ( fsptr - fullpath - 1), tostring, strlen(tostring));
    strlcpy(*result + ( fsptr - fullpath + strlen(tostring)), fsptr + strlen(fromstring), strlen(fsptr + strlen(fromstring)));

    return *result;
}


/* EOF */

// vim:ts=3:expandtab