/******************************************************/ /* tpax: a topological pax implementation */ /* Copyright (C) 2020 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /******************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "tpax_driver_impl.h" #include "tpax_errinfo_impl.h" #ifndef ssizeof #define ssizeof(x) (ssize_t)(sizeof(x)) #endif int tpax_file_create_memory_snapshot( const struct tpax_driver_ctx * dctx, int fdat, const char * path, const struct stat * srcst, void * addr) { int fd; char * ch; char * cap; ssize_t nread; struct stat dstst; /* record errors */ tpax_driver_set_ectx( dctx,0,path); /* memory snapshot internal limit */ if (srcst->st_size >= 0x80000000) return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_REGION_SIZE); /* open */ if ((fd = openat(fdat,path,O_CLOEXEC|O_NOCTTY|O_NOFOLLOW,0)) < 0) return TPAX_SYSTEM_ERROR(dctx); /* stat compare */ if ((fstat(fd,&dstst)) < 0) { close(fd); return TPAX_SYSTEM_ERROR(dctx); } else if (tpax_stat_compare(srcst,&dstst)) { close(fd); return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); } /* read loop */ ch = addr; cap = &ch[srcst->st_size]; while (ch < cap) { nread = read(fd,ch,cap-ch); while ((nread < 0) && (errno == EINTR)) nread = read(fd,ch,cap-ch); if (nread < 0) { close(fd); return TPAX_SYSTEM_ERROR(dctx); } else if (nread == 0) { close(fd); return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR); } else { ch += nread; } } /* stat compare */ if ((fstat(fd,&dstst)) < 0) { close(fd); return TPAX_SYSTEM_ERROR(dctx); } else if (tpax_stat_compare(srcst,&dstst)) { close(fd); return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); } /* yay */ close(fd); return 0; }