/*
* This file is part of libbdplus
* Copyright (C) 2013 VideoLAN
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* .
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "configfile.h"
#include "dirs.h"
#include "util/logging.h"
#include "util/macro.h"
#include "util/strutl.h"
#include
#include
#include
#include
#include
#ifdef _WIN32
# define mkdir(p,m) win32_mkdir(p)
#endif
#define BDPLUS_DIR "bdplus"
#define MIN_FILE_SIZE 1
#define MAX_FILE_SIZE 0xffffff
int file_mkpath(const char *path)
{
struct stat s;
int result = 1;
char *dir = str_dup(path);
char *end = dir;
if (!dir) {
return -1;
}
while (*end == '/')
end++;
while ((end = strchr(end, '/'))) {
*end = 0;
if (stat(dir, &s) != 0 || !S_ISDIR(s.st_mode)) {
BD_DEBUG(DBG_FILE, "Creating directory %s\n", dir);
if (mkdir(dir, S_IRWXU|S_IRWXG|S_IRWXO) == -1) {
BD_DEBUG(DBG_FILE | DBG_CRIT, "Error creating directory %s\n", dir);
result = 0;
break;
}
}
*end++ = '/';
}
free(dir);
return result;
}
char *file_get_cache_dir(void)
{
char *cache = file_get_cache_home();
char *dir;
if (!cache) {
return NULL;
}
dir = str_printf("%s/%s", cache, BDPLUS_DIR);
X_FREE(cache);
file_mkpath(dir);
return dir;
}
static char *_probe_config_dir(const char *base, const char *vm, const char *file)
{
char *dir = str_printf("%s/%s/%s/%s", base, BDPLUS_DIR, vm, file);
FILE *fp;
if (!dir) {
return NULL;
}
fp = fopen(dir, "r");
if (fp) {
fclose(fp);
*(strrchr(dir, '/') + 1) = 0;
BD_DEBUG(DBG_BDPLUS, "Found VM config from %s\n", dir);
return dir;
}
BD_DEBUG(DBG_BDPLUS, "VM config not found from %s\n", dir);
free(dir);
return NULL;
}
char *file_get_config_dir(const char *file)
{
char *dir = NULL;
const char *vm;
char *config_home;
const char *base;
vm = getenv("BDPLUS_VM_ID");
if (!vm) {
vm = "vm0";
}
/* try home directory */
config_home = file_get_config_home();
if (!config_home) {
return NULL;
}
dir = _probe_config_dir(config_home, vm, file);
X_FREE(config_home);
if (dir) {
return dir;
}
/* try system config dirs */
base = file_get_config_system(NULL);
while (base) {
dir = _probe_config_dir(base, vm, file);
if (dir) {
return dir;
}
base = file_get_config_system(base);
}
return NULL;
}
static char *_load_fp(FILE *fp, uint32_t *p_size)
{
char *data = NULL;
long file_size, read_size;
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
if (file_size < MIN_FILE_SIZE || file_size > MAX_FILE_SIZE) {
BD_DEBUG(DBG_FILE, "Invalid file size\n");
return NULL;
}
data = malloc(file_size + 1);
read_size = fread(data, 1, file_size, fp);
if (read_size != file_size) {
BD_DEBUG(DBG_FILE, "Error reading file\n");
free(data);
return NULL;
}
data[file_size] = 0;
if (p_size) {
*p_size = file_size;
}
return data;
}
char *file_load(const char *path, uint32_t *p_size)
{
char *mem;
FILE *fp;
if (!path) {
return NULL;
}
fp = fopen(path, "rb");
if (!fp) {
BD_DEBUG(DBG_FILE | DBG_CRIT, "Error loading %s\n", path);
return NULL;
}
mem = _load_fp(fp, p_size);
fclose(fp);
return mem;
}