/**************************************************************/ /* tpax: a topological pax implementation */ /* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /**************************************************************/ #include #include #include #include #include #include #include #include "tpax_driver_impl.h" #include "tpax_errinfo_impl.h" #include "tpax_readlink_impl.h" static int tpax_free_unit_ctx_impl(struct tpax_unit_ctx_impl * ctx, int ret) { if (ctx) { if (ctx->pathbuf) free(ctx->pathbuf); free(ctx); } return ret; } int tpax_lib_get_unit_ctx( const struct tpax_driver_ctx * dctx, int fdat, const char * path, struct tpax_unit_ctx ** pctx) { int ret; struct tpax_unit_ctx_impl * ctx; size_t pathlen; if (!dctx) return TPAX_CUSTOM_ERROR( dctx,TPAX_ERR_NULL_CONTEXT); else if (!(ctx = calloc(1,sizeof(*ctx)))) return TPAX_BUFFER_ERROR(dctx); tpax_driver_set_ectx( dctx,0,path); if (dctx->cctx->drvflags & TPAX_DRIVER_EXEC_MODE_WRITE_COPY) { ret = fstatat( fdat,path,&ctx->st, AT_SYMLINK_NOFOLLOW); if (ret < 0) { free(ctx); return TPAX_SYSTEM_ERROR(dctx); } } if (S_ISLNK(ctx->st.st_mode)) { if (tpax_readlinkat( fdat,path,ctx->linkbuf, sizeof(ctx->linkbuf)) < 0) { free(ctx); return TPAX_SYSTEM_ERROR(dctx); } } if (dctx->cctx->drvflags & TPAX_DRIVER_PURE_PATH_OUTPUT) { if (!(pathlen = strlen(path))) return TPAX_CUSTOM_ERROR( dctx, TPAX_ERR_FORBIDDEN_PATH); if (!(ctx->pathbuf = calloc(1,++pathlen))) return TPAX_BUFFER_ERROR(dctx); ret = tpax_util_path_copy( ctx->pathbuf,path,pathlen, dctx->cctx->drvflags, &pathlen); if (ret < 0) return TPAX_CUSTOM_ERROR( dctx, TPAX_ERR_FLOW_ERROR); ctx->path = ctx->pathbuf; ctx->patharg = path; } else { ctx->path = path; ctx->patharg = path; ctx->pathbuf = 0; } ctx->link = ctx->linkbuf[0] ? ctx->linkbuf : 0; ctx->uctx.path = &ctx->path; ctx->uctx.link = &ctx->link; ctx->uctx.st = &ctx->st; *pctx = &ctx->uctx; return 0; } void tpax_lib_free_unit_ctx(struct tpax_unit_ctx * ctx) { struct tpax_unit_ctx_impl * ictx; uintptr_t addr; if (ctx) { addr = (uintptr_t)ctx - offsetof(struct tpax_unit_ctx_impl,uctx); ictx = (struct tpax_unit_ctx_impl *)addr; tpax_free_unit_ctx_impl(ictx,0); } }