142 linhas
2.6 KiB
C
142 linhas
2.6 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright (c) 2017-2019 by Löwenware Ltd
|
|
* Please, refer LICENSE file for legal information
|
|
*
|
|
******************************************************************************/
|
|
|
|
/**
|
|
* @file file.c
|
|
* @author Ilja Kartašov <ik@lowenware.com>
|
|
* @brief
|
|
*
|
|
* @see https://lowenware.com/
|
|
*/
|
|
#include <stdio.h>
|
|
#include <sys/sendfile.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
#include <sys/stat.h>
|
|
#include "file.h"
|
|
|
|
|
|
bool
|
|
cstuff_file_exists(const char *file)
|
|
{
|
|
return ( access( file, F_OK ) != -1 ) ? true : false;
|
|
}
|
|
|
|
|
|
CStuffRetcode
|
|
cstuff_file_copy(const char *src, const char *dest)
|
|
{
|
|
CStuffRetcode rc = CSTUFF_SYSCALL_ERROR;
|
|
int fd_src = open(src, O_RDWR), fd_dest, len;
|
|
struct stat src_stat;
|
|
|
|
if (!(fd_src < 0)) {
|
|
if (lockf(fd_src, F_LOCK, 0) != -1) {
|
|
if (!stat(src, &src_stat)) {
|
|
fd_dest = open(dest, O_CREAT | O_WRONLY | O_TRUNC);
|
|
if (!(fd_dest < 0)) {
|
|
len = sendfile(fd_dest, fd_src, NULL, src_stat.st_size);
|
|
if (len == src_stat.st_size) {
|
|
rc = CSTUFF_SUCCESS;
|
|
} else {
|
|
fprintf(stderr, "sendfile error (%d != %d): %s\n", len,
|
|
(int)src_stat.st_size, strerror(errno));
|
|
}
|
|
close(fd_dest);
|
|
} else {
|
|
fprintf(stderr, "dest open() error\n");
|
|
}
|
|
} else {
|
|
fprintf(stderr, "src stat() error\n");
|
|
}
|
|
if (lockf(fd_src, F_TEST, 0) == 0){
|
|
lockf(fd_src, F_ULOCK, 0);
|
|
}
|
|
} else {
|
|
fprintf(stderr, "src lockf() error\n");
|
|
}
|
|
close(fd_src);
|
|
} else {
|
|
fprintf(stderr, "src open() error\n");
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
CStuffRetcode
|
|
cstuff_file_move(const char *src, const char *dest)
|
|
{
|
|
CStuffRetcode rc;
|
|
|
|
if (!(rc = cstuff_file_copy(src, dest))) {
|
|
if (unlink(src) != 0)
|
|
return CSTUFF_SYSCALL_ERROR;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
CStuffRetcode
|
|
cstuff_file_get_lines(const char *src, CStuffFileGetLine get_line, void *ctx)
|
|
{
|
|
FILE *f = NULL;
|
|
size_t sz = 256;
|
|
char *line;
|
|
ssize_t rs;
|
|
CStuffRetcode result = CSTUFF_SUCCESS;
|
|
|
|
if (!(line = malloc(sz)))
|
|
goto e_malloc;
|
|
|
|
if (!(f = fopen(src, "r")))
|
|
goto e_syscall;
|
|
|
|
while ((rs = getdelim(&line, &sz, '\n', f)) != -1) {
|
|
if (!get_line(line, rs, ctx)) {
|
|
continue;
|
|
} else {
|
|
goto e_input;
|
|
}
|
|
}
|
|
|
|
switch(errno) {
|
|
case 0:
|
|
break;
|
|
|
|
case ENOMEM:
|
|
goto e_malloc;
|
|
|
|
default:
|
|
goto e_syscall;
|
|
}
|
|
goto finally;
|
|
|
|
e_input:
|
|
result = CSTUFF_INPUT_ERROR;
|
|
goto finally;
|
|
|
|
e_malloc:
|
|
result = CSTUFF_MALLOC_ERROR;
|
|
goto finally;
|
|
|
|
e_syscall:
|
|
result = CSTUFF_SYSCALL_ERROR;
|
|
goto finally;
|
|
|
|
finally:
|
|
if (line)
|
|
free(line);
|
|
if (f)
|
|
fclose(f);
|
|
return result;
|
|
}
|