| |
| |
| |
| |
| |
| |
| #include <stdint.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <grp.h> |
| #include <pwd.h> |
| #include <sys/stat.h> |
| |
| #include <tpax/tpax.h> |
| #include <tpax/tpax_specs.h> |
| #include "tpax_driver_impl.h" |
| #include "tpax_tmpfile_impl.h" |
| #include "tpax_errinfo_impl.h" |
| |
| #ifndef ssizeof |
| #define ssizeof(x) (ssize_t)(sizeof(x)) |
| #endif |
| |
| int tpax_io_create_tmpfs_snapshot( |
| const struct tpax_driver_ctx * dctx, |
| int fdat, |
| const char * path, |
| const struct stat * srcst) |
| { |
| int fdsrc; |
| int fdtmp; |
| char * ch; |
| ssize_t nread; |
| ssize_t nbytes; |
| ssize_t ret; |
| void * buf; |
| size_t buflen; |
| struct stat dstst; |
| |
| |
| tpax_driver_set_ectx( |
| dctx,0,path); |
| |
| |
| if ((fdtmp = tpax_tmpfile()) < 0) |
| return TPAX_SYSTEM_ERROR(dctx); |
| |
| |
| buf = tpax_get_driver_anon_map_addr( |
| dctx,&buflen); |
| |
| |
| if ((fdsrc = openat(fdat,path,O_CLOEXEC|O_NOCTTY|O_NOFOLLOW,0)) < 0) { |
| close(fdtmp); |
| return TPAX_SYSTEM_ERROR(dctx); |
| } |
| |
| |
| if ((fstat(fdsrc,&dstst)) < 0) { |
| close(fdsrc); |
| close(fdtmp); |
| return TPAX_SYSTEM_ERROR(dctx); |
| |
| } else if (tpax_util_stat_compare(srcst,&dstst)) { |
| close(fdsrc); |
| close(fdtmp); |
| return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); |
| } |
| |
| |
| for (nread=0; nread<srcst->st_size; ) { |
| nbytes = read(fdsrc,buf,buflen); |
| |
| while ((nbytes < 0) && (errno == EINTR)) |
| nbytes = read(fdsrc,buf,buflen); |
| |
| if (nbytes < 0) { |
| close(fdsrc); |
| close(fdtmp); |
| return TPAX_SYSTEM_ERROR(dctx); |
| |
| } else if (nbytes == 0) { |
| close(fdsrc); |
| close(fdtmp); |
| return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR); |
| |
| } else { |
| nread += nbytes; |
| } |
| |
| for (ch=buf; nbytes; ch+=ret) { |
| ret = write(fdtmp,ch,nbytes); |
| |
| while ((ret < 0) && (errno == EINTR)) |
| ret = write(fdtmp,ch,nbytes); |
| |
| if (ret < 0) { |
| close(fdsrc); |
| close(fdtmp); |
| return TPAX_SYSTEM_ERROR(dctx); |
| |
| } else { |
| nbytes -= ret; |
| } |
| } |
| } |
| |
| |
| if ((fstat(fdsrc,&dstst)) < 0) { |
| close(fdsrc); |
| close(fdtmp); |
| return TPAX_SYSTEM_ERROR(dctx); |
| |
| } else if (tpax_util_stat_compare(srcst,&dstst)) { |
| close(fdsrc); |
| close(fdtmp); |
| return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); |
| } |
| |
| |
| close(fdsrc); |
| |
| return fdtmp; |
| } |