root/software/fss-parallel-tools/putils.c @ 59c738ae
| 7e8045d8 | David Sorber | /**
|
|
* Copyright © 2019, Oracle and/or its affiliates. All rights reserved.
|
|||
*
|
|||
* Licensed under the Universal Permissive License v 1.0 as shown at
|
|||
* http://oss.oracle.com/licenses/upl
|
|||
*
|
|||
*/
|
|||
#define _GNU_SOURCE
|
|||
#include "putils.h"
|
|||
#include "malloc.h"
|
|||
#include <assert.h>
|
|||
#include <errno.h>
|
|||
#include <fcntl.h>
|
|||
#include <stdio.h>
|
|||
#include <string.h>
|
|||
#include <sys/stat.h>
|
|||
#include <unistd.h>
|
|||
#include <ftw.h>
|
|||
#include "common/spew.h"
|
|||
FILE* do_creat(const char *fullname) {
|
|||
int fd = open(fullname, O_CREAT | O_WRONLY | O_TRUNC, S_IWUSR);
|
|||
if (fd == -1) {
|
|||
if (errno == EEXIST || errno == EISDIR) {
|
|||
return NULL;
|
|||
}
|
|||
fprintf(stderr, "Trying to open %s:\n", fullname);
|
|||
perror("open");
|
|||
spew(SPEW_ERROR, "Create of %s failed errno=%d (%s)",
|
|||
fullname, errno, strerror(errno));
|
|||
abort();
|
|||
}
|
|||
assert(fd >= 0);
|
|||
FILE *f = fdopen(fd, "w");
|
|||
if (!f) {
|
|||
perror("fdopen");
|
|||
spew(SPEW_ERROR, "fdopen of %s for write failed errno=%d (%s)",
|
|||
fullname, errno, strerror(errno));
|
|||
}
|
|||
assert(f);
|
|||
return f;
|
|||
}
|
|||
FILE* do_open_for_read(const char *fullname) {
|
|||
int fd = open(fullname, O_RDONLY);
|
|||
if (fd == -1) {
|
|||
fprintf(stderr, "Trying to open %s:\n", fullname);
|
|||
perror("open");
|
|||
spew(SPEW_ERROR, "Open of %s failed errno=%d (%s)",
|
|||
fullname, errno, strerror(errno));
|
|||
abort();
|
|||
}
|
|||
assert(fd >= 0);
|
|||
FILE *f = fdopen(fd, "r");
|
|||
if (!f) {
|
|||
perror("fdopen");
|
|||
spew(SPEW_ERROR, "fdopen of %s for read failed errno=%d (%s)",
|
|||
fullname, errno, strerror(errno));
|
|||
}
|
|||
assert(f);
|
|||
return f;
|
|||
}
|
|||
void do_fclose(FILE *f) {
|
|||
int r = fclose(f);
|
|||
if (r != 0) {
|
|||
perror("fclose");
|
|||
spew(SPEW_ERROR, "fclose %p failed errno=%d (%s)",
|
|||
f, errno, strerror(errno));
|
|||
}
|
|||
assert(r == 0);
|
|||
}
|
|||
void do_write(FILE *f, const char *bytes, size_t size) {
|
|||
size_t r = fwrite(bytes, 1, size, f);
|
|||
if (r != size) {
|
|||
perror("fwrite");
|
|||
spew(SPEW_ERROR, "fwrite failed errno=%d (%s)",
|
|||
errno, strerror(errno));
|
|||
}
|
|||
assert(r == size);
|
|||
}
|
|||
size_t do_read(FILE *f, char *bytes, size_t size) {
|
|||
// We might be reading from a socket or a pipe, so keep reading till we get all the bytes.
|
|||
size_t r = fread(bytes, 1, size, f);
|
|||
if (r == 0) {
|
|||
if (feof(f)) {
|
|||
return 0;
|
|||
}
|
|||
assert(ferror(f));
|
|||
fprintf(stderr, "do_read got error %d\n", ferror(f));
|
|||
spew(SPEW_ERROR, "fread failed errno=%d (%s)",
|
|||
errno, strerror(errno));
|
|||
assert(0);
|
|||
}
|
|||
if (r < size) {
|
|||
return r + do_read(f, bytes+r, size-r);
|
|||
} else {
|
|||
return r;
|
|||
}
|
|||
}
|
|||
int do_mkdir(const char *fullname) {
|
|||
if (0) fprintf(stderr, "mkdir(\"%s\");\n", fullname);
|
|||
int r = mkdir(fullname, S_IRUSR|S_IWUSR|S_IXUSR);
|
|||
if (r != 0) {
|
|||
if (errno == EEXIST) {
|
|||
return r;
|
|||
}
|
|||
// We ensure that the parent exists before we call do_mkdir,
|
|||
// so ENOENT is a real error.
|
|||
fprintf(stderr, "Trying to mkdir %s\n", fullname);
|
|||
perror("mkdir");
|
|||
spew(SPEW_ERROR, "mkdir %s failed errno=%d (%s)",
|
|||
fullname, errno, strerror(errno));
|
|||
abort();
|
|||
}
|
|||
assert(r == 0);
|
|||
return 0; //returns Success
|
|||
}
|
|||
int do_mkfifo(const char *fullname, mode_t mode) {
|
|||
int r = mkfifo(fullname, mode);
|
|||
if (r) {
|
|||
if (errno == EEXIST) {
|
|||
return r;
|
|||
}
|
|||
fprintf(stderr, "Trying to mkfifo(%s, %d)\n", fullname, mode);
|
|||
perror("mkfifo");
|
|||
spew(SPEW_ERROR, "mkfifo %s failed errno=%d (%s)",
|
|||
fullname, errno, strerror(errno));
|
|||
abort();
|
|||
}
|
|||
return 0; //returns Success
|
|||
}
|
|||
int do_link(const char *linkto, const char *fullname)
|
|||
// Effect create a hardlink. If the file already exists delete it and then
|
|||
// link.
|
|||
{
|
|||
int r = link(linkto, fullname);
|
|||
if (r && errno == EEXIST) {
|
|||
return r;
|
|||
}
|
|||
if (r) {
|
|||
fprintf(stderr, "Trying to link \"%s\" --> \"%s\"\nerrno=%d\n", fullname, linkto, errno);
|
|||
perror("link");
|
|||
spew(SPEW_ERROR, "linking \"%s\" --> \"%s\" failed errno=%d (%s)",
|
|||
fullname, linkto, errno, strerror(errno));
|
|||
abort();
|
|||
}
|
|||
return 0; //returns Success
|
|||
}
|
|||
int do_symlink(const char *contents, const char *fullname) {
|
|||
int r = symlink(contents, fullname);
|
|||
return r;
|
|||
}
|
|||
void do_unlink(const char *fullname) {
|
|||
int r = unlink(fullname);
|
|||
assert(r == 0);
|
|||
}
|
|||
void do_rmdir(const char *fullname) {
|
|||
int r = rmdir(fullname);
|
|||
assert(r == 0);
|
|||
}
|
|||
/*
|
|||
* This function is callback for nftw call that is made
|
|||
* with the intention of deleting conflicts. The function
|
|||
* deletes file or directory provided in the argument 'path'
|
|||
*/
|
|||
int delete_subtree(const char *path, const struct stat *st, int typeflag, struct FTW *d_ftw) {
|
|||
int ret = 1;
|
|||
if (typeflag == 4 || d_ftw == NULL) {
|
|||
return ret;
|
|||
}
|
|||
if (S_ISDIR(st->st_mode)) {
|
|||
ret = rmdir(path);
|
|||
} else {
|
|||
ret = unlink(path);
|
|||
}
|
|||
return ret;
|
|||
}
|
|||
/* Recursively deletes files/directories in directory path passed */
|
|||
void delete_dir_recursively(const char *path) {
|
|||
int ret = nftw(path, delete_subtree, 10, FTW_DEPTH);
|
|||
if (ret != 0) {
|
|||
spew(SPEW_ERROR, "Unable to delete subtree for %s. Aborting\n", path);
|
|||
abort();
|
|||
}
|
|||
}
|
|||
char *pathcat(const char *a, const char *b) {
|
|||
char *result = NULL;
|
|||
int r = asprintf(&result, "%s/%s", a, b);
|
|||
assert(r > 0);
|
|||
return result;
|
|||
}
|
|||
size_t parse_number_or_help(const char *numstring) {
|
|||
errno = 0;
|
|||
char *end;
|
|||
size_t result = strtoul(numstring, &end, 0);
|
|||
if (0
|
|||
|| errno != 0
|
|||
|| *end != 0)
|
|||
{
|
|||
fprintf(stderr, "Trying to parse %s as a number\n", numstring);
|
|||
spew(SPEW_DEBUG, "Trying to parse %s as a number", numstring);
|
|||
help(1);
|
|||
return 0;
|
|||
}
|
|||
return result;
|
|||
}
|
|||
void
|
|||
maybe_error(int r, const char *fun, const char *fname, const char *srcfile, int line) {
|
|||
if (r != 0) {
|
|||
fprintf(stderr, "%s:%d Could not %s(\"%s\"). errno=%d (%s)\n",
|
|||
srcfile, line, fun, fname, errno, strerror(errno));
|
|||
spew(SPEW_ERROR, "Could not %s(\"%s\"). errno=%d (%s)",
|
|||
fun, fname, errno, strerror(errno));
|
|||
exit(1);
|
|||
}
|
|||
}
|
|||
void
|
|||
maybe_error2(int r, const char *fun, const char *fname, const char *fname2, const char *srcfile, int line) {
|
|||
if (r != 0) {
|
|||
fprintf(stderr, "%s:%d Could not %s(\"%s\", \"%s\"). errno=%d (%s)\n",
|
|||
srcfile, line,
|
|||
fun, fname, fname2, errno, strerror(errno));
|
|||
spew(SPEW_ERROR, "Could not %s(\"%s\", \"%s\"). errno=%d (%s)",
|
|||
fun, fname, fname2, errno, strerror(errno));
|
|||
exit(1);
|
|||
}
|
|||
}
|