/*
|
|
* gfsec - Secret sharing tools
|
|
* Copyright (C) 2016,2017,2018,2020 Damien Goutte-Gattat
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include "util.h"
|
|
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
#include <xmem.h>
|
|
|
|
/**
|
|
* Checks if the specified file exists.
|
|
*
|
|
* @param path The filename to check.
|
|
*
|
|
* @return 0 if the file exists, or -1 (check errno for details).
|
|
*/
|
|
int
|
|
file_exists(const char *path)
|
|
{
|
|
struct stat st;
|
|
|
|
assert(path != NULL);
|
|
|
|
return stat(path, &st);
|
|
}
|
|
|
|
/**
|
|
* Gets the size of the specified file.
|
|
*
|
|
* @param f The file object.
|
|
*
|
|
* @return The file's size, or -1 if an error occured
|
|
* (check errno for details).
|
|
*/
|
|
long
|
|
get_file_size(FILE *f)
|
|
{
|
|
long s;
|
|
|
|
assert(f != NULL);
|
|
|
|
if ( fseek(f, 0, SEEK_END) == -1
|
|
|| (s = ftell(f)) == -1
|
|
|| fseek(f, 0, SEEK_SET) == -1 )
|
|
s = -1;
|
|
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* Reads a file into memory.
|
|
*
|
|
* @param filename The path to the file to read.
|
|
* @param len The address where the file's size will be stored
|
|
* (may be NULL).
|
|
* @param max Do not read the file if its size exceeds this value;
|
|
* if zero, always read the file no matter its size.
|
|
*
|
|
* @return A newly allocated buffer containing the file's data, or
|
|
* NULL if an error occured (check errno for details).
|
|
*/
|
|
unsigned char *
|
|
read_file(const char *filename, size_t *len, size_t max)
|
|
{
|
|
FILE *f;
|
|
unsigned char *blob = NULL;
|
|
|
|
assert(filename != NULL);
|
|
|
|
if ( (f = fopen(filename, "r")) ) {
|
|
long size;
|
|
size_t nread;
|
|
|
|
if ( (size = get_file_size(f)) != -1 ) {
|
|
|
|
if ( max != 0 && (unsigned long) size > max )
|
|
errno = EFBIG;
|
|
else {
|
|
blob = xmalloc(size);
|
|
if ( (nread = fread(blob, 1, size, f)) < (unsigned long) size ) {
|
|
free(blob);
|
|
blob = NULL;
|
|
}
|
|
else if ( len )
|
|
*len = nread;
|
|
}
|
|
}
|
|
|
|
fclose(f);
|
|
}
|
|
|
|
return blob;
|
|
}
|
|
|
|
/**
|
|
* Writes a buffer into a file.
|
|
*
|
|
* @param filename The path to the file to write.
|
|
* @param contents The buffer to write.
|
|
* @param len The size of the \c contents buffer.
|
|
*
|
|
* @return The number of bytes written, or -1 if an error occured
|
|
* (check errno for details).
|
|
*/
|
|
int
|
|
write_file(const char *filename, const unsigned char *contents, size_t len)
|
|
{
|
|
FILE *f;
|
|
int rc = -1;
|
|
|
|
assert(filename != NULL);
|
|
assert(contents != NULL);
|
|
|
|
if ( (f = fopen(filename, "w")) ) {
|
|
rc = fwrite(contents, sizeof(char), len, f) == len ? 0 : -1;
|
|
fclose(f);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Gets the basename part of a path.
|
|
*
|
|
* @param path The path to extract the basename from.
|
|
*
|
|
* @return A newly allocated buffer containing the basename.
|
|
*/
|
|
char *
|
|
get_file_basename(const char *path)
|
|
{
|
|
char *last_slash, *last_dot;
|
|
unsigned n;
|
|
|
|
assert(path != NULL);
|
|
|
|
if ( (last_slash = strrchr(path, '/')) )
|
|
path = last_slash + 1;
|
|
|
|
if ( (last_dot = strrchr(path, '.')) )
|
|
n = last_dot - path;
|
|
else
|
|
n = strlen(path);
|
|
|
|
return xstrndup(path, n);
|
|
}
|
|
|
|
/**
|
|
* Creates a directory and its parents.
|
|
* This function creates the specified directory. Parent directories
|
|
* are created as needed.
|
|
*
|
|
* @param path The pathname of the directory to create.
|
|
* @param mode The permissions of the directory, as in creat(2).
|
|
*
|
|
* @return 0 if the directory was successfully created (or if it
|
|
* already existed), or -1 if an error occured.
|
|
*/
|
|
int
|
|
makedir(const char *path, int mode)
|
|
{
|
|
char *p, q;
|
|
int ret;
|
|
struct stat st_buf;
|
|
|
|
assert(path != NULL);
|
|
|
|
for ( p = (char *)(path + 1), ret = 0; *(p - 1) && ret == 0; p++ ) {
|
|
if ( *p == '/' || *p == '\0' ) {
|
|
q = *p, *p = '\0';
|
|
|
|
if ( stat(path, &st_buf) == -1 ) {
|
|
/* Path does not exist, attempt to create it. */
|
|
ret = mkdir(path, mode);
|
|
}
|
|
else if ( ! S_ISDIR(st_buf.st_mode) ) {
|
|
/* Path exists but is not a directory. */
|
|
errno = ENOTDIR;
|
|
ret = -1;
|
|
}
|
|
|
|
*p = q;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|