| |
| |
| |
| |
| |
| |
| #include <stdint.h> |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <fcntl.h> |
| #include <sys/stat.h> |
| |
| #include <tpax/tpax.h> |
| #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) { |
| 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; |
| |
| 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); |
| } |
| } |
| |
| ctx->path = path; |
| 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); |
| } |
| } |