|
|
5874a9 |
/**************************************************************/
|
|
|
5874a9 |
/* tpax: a topological pax implementation */
|
|
|
5874a9 |
/* Copyright (C) 2020--2021 SysDeer Technologies, LLC */
|
|
|
5874a9 |
/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */
|
|
|
5874a9 |
/**************************************************************/
|
|
|
f6b26d |
|
|
|
f6b26d |
#include <stdint.h>
|
|
|
f6b26d |
#include <stdlib.h>
|
|
|
f6b26d |
#include <string.h>
|
|
|
f6b26d |
#include <unistd.h>
|
|
|
f6b26d |
#include <fcntl.h>
|
|
|
f6b26d |
#include <errno.h>
|
|
|
f6b26d |
#include <grp.h>
|
|
|
f6b26d |
#include <pwd.h>
|
|
|
f6b26d |
#include <sys/stat.h>
|
|
|
f6b26d |
|
|
|
f6b26d |
#include <tpax/tpax.h>
|
|
|
f6b26d |
#include <tpax/tpax_specs.h>
|
|
|
f6b26d |
#include "tpax_driver_impl.h"
|
|
|
f6b26d |
#include "tpax_tmpfile_impl.h"
|
|
|
f6b26d |
#include "tpax_errinfo_impl.h"
|
|
|
f6b26d |
|
|
|
f6b26d |
#ifndef ssizeof
|
|
|
f6b26d |
#define ssizeof(x) (ssize_t)(sizeof(x))
|
|
|
f6b26d |
#endif
|
|
|
f6b26d |
|
|
|
f6b26d |
int tpax_file_create_tmpfs_snapshot(
|
|
|
f6b26d |
const struct tpax_driver_ctx * dctx,
|
|
|
a2aed5 |
int fdat,
|
|
|
f6b26d |
const char * path,
|
|
|
f6b26d |
const struct stat * srcst)
|
|
|
f6b26d |
{
|
|
|
f6b26d |
int fdsrc;
|
|
|
f6b26d |
int fdtmp;
|
|
|
f6b26d |
char * ch;
|
|
|
f6b26d |
ssize_t nread;
|
|
|
f6b26d |
ssize_t nbytes;
|
|
|
f6b26d |
ssize_t ret;
|
|
|
f6b26d |
void * buf;
|
|
|
f6b26d |
size_t buflen;
|
|
|
f6b26d |
struct stat dstst;
|
|
|
f6b26d |
|
|
|
f6b26d |
/* record errors */
|
|
|
f6b26d |
tpax_driver_set_ectx(
|
|
|
f6b26d |
dctx,0,path);
|
|
|
f6b26d |
|
|
|
f6b26d |
/* tmpfile */
|
|
|
f6b26d |
if ((fdtmp = tpax_tmpfile()) < 0)
|
|
|
f6b26d |
return TPAX_SYSTEM_ERROR(dctx);
|
|
|
f6b26d |
|
|
|
f6b26d |
/* buffer */
|
|
|
67ad73 |
buf = tpax_get_driver_anon_map_addr(
|
|
|
67ad73 |
dctx,&buflen);
|
|
|
f6b26d |
|
|
|
f6b26d |
/* open */
|
|
|
a2aed5 |
if ((fdsrc = openat(fdat,path,O_CLOEXEC|O_NOCTTY|O_NOFOLLOW,0)) < 0) {
|
|
|
f6b26d |
close(fdtmp);
|
|
|
f6b26d |
return TPAX_SYSTEM_ERROR(dctx);
|
|
|
f6b26d |
}
|
|
|
f6b26d |
|
|
|
f6b26d |
/* stat compare */
|
|
|
f6b26d |
if ((fstat(fdsrc,&dstst)) < 0) {
|
|
|
f6b26d |
close(fdsrc);
|
|
|
f6b26d |
close(fdtmp);
|
|
|
f6b26d |
return TPAX_SYSTEM_ERROR(dctx);
|
|
|
f6b26d |
|
|
|
f6b26d |
} else if (tpax_stat_compare(srcst,&dstst)) {
|
|
|
f6b26d |
close(fdsrc);
|
|
|
f6b26d |
close(fdtmp);
|
|
|
f6b26d |
return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED);
|
|
|
f6b26d |
}
|
|
|
f6b26d |
|
|
|
f6b26d |
/* read/write loop */
|
|
|
f6b26d |
for (nread=0; nread<srcst->st_size; ) {
|
|
|
f6b26d |
nbytes = read(fdsrc,buf,buflen);
|
|
|
f6b26d |
|
|
|
f6b26d |
while ((nbytes < 0) && (errno == EINTR))
|
|
|
f6b26d |
nbytes = read(fdsrc,buf,buflen);
|
|
|
f6b26d |
|
|
|
f6b26d |
if (nbytes < 0) {
|
|
|
f6b26d |
close(fdsrc);
|
|
|
f6b26d |
close(fdtmp);
|
|
|
f6b26d |
return TPAX_SYSTEM_ERROR(dctx);
|
|
|
f6b26d |
|
|
|
f6b26d |
} else if (nbytes == 0) {
|
|
|
f6b26d |
close(fdsrc);
|
|
|
f6b26d |
close(fdtmp);
|
|
|
f6b26d |
return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR);
|
|
|
f6b26d |
|
|
|
f6b26d |
} else {
|
|
|
f6b26d |
nread += nbytes;
|
|
|
f6b26d |
}
|
|
|
f6b26d |
|
|
|
f6b26d |
for (ch=buf; nbytes; ch+=ret) {
|
|
|
f6b26d |
ret = write(fdtmp,ch,nbytes);
|
|
|
f6b26d |
|
|
|
f6b26d |
while ((ret < 0) && (errno == EINTR))
|
|
|
f6b26d |
ret = write(fdtmp,ch,nbytes);
|
|
|
f6b26d |
|
|
|
f6b26d |
if (ret < 0) {
|
|
|
f6b26d |
close(fdsrc);
|
|
|
f6b26d |
close(fdtmp);
|
|
|
f6b26d |
return TPAX_SYSTEM_ERROR(dctx);
|
|
|
f6b26d |
|
|
|
f6b26d |
} else {
|
|
|
f6b26d |
nbytes -= ret;
|
|
|
f6b26d |
}
|
|
|
f6b26d |
}
|
|
|
f6b26d |
}
|
|
|
f6b26d |
|
|
|
f6b26d |
/* stat compare */
|
|
|
f6b26d |
if ((fstat(fdsrc,&dstst)) < 0) {
|
|
|
f6b26d |
close(fdsrc);
|
|
|
f6b26d |
close(fdtmp);
|
|
|
f6b26d |
return TPAX_SYSTEM_ERROR(dctx);
|
|
|
f6b26d |
|
|
|
f6b26d |
} else if (tpax_stat_compare(srcst,&dstst)) {
|
|
|
f6b26d |
close(fdsrc);
|
|
|
f6b26d |
close(fdtmp);
|
|
|
f6b26d |
return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED);
|
|
|
f6b26d |
}
|
|
|
f6b26d |
|
|
|
f6b26d |
/* yay */
|
|
|
f6b26d |
close(fdsrc);
|
|
|
f6b26d |
|
|
|
f6b26d |
return fdtmp;
|
|
|
f6b26d |
}
|