Project

General

Profile

Download (6.68 KB) Statistics
| Branch: | Tag: | Revision:
/**
* 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);
}
}
(16-16/29)