Skip to content
This repository has been archived by the owner on Jan 8, 2024. It is now read-only.

Initial implementation of COPY and COPY_EACH_FILE_IN_DIR with example #47

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ string
foreach
logging
file
pipe
pipe
copy
33 changes: 33 additions & 0 deletions examples/copy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#define NOBUILD_IMPLEMENTATION
#include "../nobuild.h"

#define CFLAGS "-Wall", "-Wextra", "-std=c99", "-pedantic"

#define DEMO(expr) \
do { \
INFO(#expr); \
expr; \
} while(0)

void copy(const char *from, const char *to)
{
COPY(from, to);
}

void copy_each_file_in_dir(const char *from, const char *to)
{
COPY_EACH_FILE_IN_DIR(from, to);
}

int main(int argc, char **argv)
{
MKDIRS(PATH("examples", "copy-test"));

DEMO(copy(PATH("examples", "copy.c"), PATH("examples", "copy-test", "copy.c")));

DEMO(copy_each_file_in_dir("examples", PATH("examples", "copy-test")));

RM (PATH("examples", "copy-test"));

return 0;
}
107 changes: 107 additions & 0 deletions nobuild.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ typedef HANDLE Fd;
#define WIN32_LEAN_AND_MEAN
#include "windows.h"


struct dirent {
char d_name[MAX_PATH+1];
};
Expand Down Expand Up @@ -310,6 +311,38 @@ void path_rm(Cstr path);
closedir(dir); \
} while(0)

int copy_file(Cstr from, Cstr to);
#define COPY(from, to) copy_file(from, to)

#define COPY_EACH_FILE_IN_DIR(frompath, topath) \
do { \
struct dirent *dp = NULL; \
DIR *dir = opendir(frompath); \
if (dir == NULL) { \
PANIC("could not open directory %s: %s", \
frompath, strerror(errno)); \
} \
errno = 0; \
while ((dp = readdir(dir))) { \
const char *file = dp->d_name; \
if (strcmp(file, ".") != 0 \
&& strcmp(file, "..") != 0) \
{ \
copy_file( \
PATH(frompath, file), \
PATH(topath, file)); \
} \
\
} \
\
if (errno > 0) { \
PANIC("could not read directory %s: %s", \
frompath, strerror(errno)); \
} \
\
closedir(dir); \
} while(0)

#if defined(__GNUC__) || defined(__clang__)
// https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html
#define NOBUILD_PRINTF_FORMAT(STRING_INDEX, FIRST_TO_CHECK) __attribute__ ((format (printf, STRING_INDEX, FIRST_TO_CHECK)))
Expand Down Expand Up @@ -955,6 +988,7 @@ int path_exists(Cstr path)
#endif
}


int path_is_dir(Cstr path)
{
#ifdef _WIN32
Expand Down Expand Up @@ -1064,6 +1098,79 @@ void path_rm(Cstr path)
}
}

int copy_file(Cstr from, Cstr to)
{
INFO("COPY: %s -> %s", from, to);
#ifdef _WIN32
return CopyFileW(from, to, false);
#else
int fd_to, fd_from;
char buf[4096];
ssize_t nread;
int saved_errno;

fd_from = open(from, O_RDONLY);
if (fd_from < 0)
return -1;

fd_to = open(to, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (fd_to < 0) {
WARN("file %s already exists. Overwriting", to);
path_rm(to);

//retry opening
errno = 0;
fd_to = open(to, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (fd_to < 0) {
goto out_error;
}
}

while (nread = read(fd_from, buf, sizeof buf), nread > 0)
{
char *out_ptr = buf;
ssize_t nwritten;

do {
nwritten = write(fd_to, out_ptr, nread);

if (nwritten >= 0)
{
nread -= nwritten;
out_ptr += nwritten;
}
else if (errno != EINTR)
{
goto out_error;
}
} while (nread > 0);
}

if (nread == 0)
{
if (close(fd_to) < 0)
{
fd_to = -1;
goto out_error;
}
close(fd_from);

return 0; // Success
}

out_error:
saved_errno = errno;

close(fd_from);
if (fd_to >= 0)
close(fd_to);

errno = saved_errno;
return -1;
#endif
}


int is_path1_modified_after_path2(const char *path1, const char *path2)
{
#ifdef _WIN32
Expand Down