src/dbfs/link.c
changeset 35 4f10421681d2
parent 34 460f995d3769
child 36 56427f22e969
equal deleted inserted replaced
34:460f995d3769 35:4f10421681d2
     1 #include <stdlib.h>
       
     2 #include <assert.h>
       
     3 #include <string.h>
       
     4 
       
     5 #include "dbfs.h"
     1 #include "dbfs.h"
     6 #include "trans.h"
       
     7 
     2 
     8 #include "../lib/log.h"
     3 #include "../lib/log.h"
     9 
     4 
    10 void _dbfs_readlink_res (const struct evsql_result_info *res, void *arg) {
     5 void _dbfs_readlink_res (const struct evsql_result_info *res, void *arg) {
    11     struct fuse_req *req = arg;
     6     struct fuse_req *req = arg;
    81     if ((err = fuse_reply_err(req, err)))
    76     if ((err = fuse_reply_err(req, err)))
    82         EWARNING(err, "fuse_reply_err");
    77         EWARNING(err, "fuse_reply_err");
    83 
    78 
    84 }
    79 }
    85 
    80 
    86 struct dbfs_symlink_ctx {
       
    87     struct dbfs_trans base;
       
    88 
       
    89     char *link, *name;
       
    90     uint32_t ino, parent;
       
    91 };
       
    92 
       
    93 #define DBFS_SYMLINK_MODE 0777
       
    94 
       
    95 void dbfs_symlink_free (struct dbfs_trans *ctx_base) {
       
    96     struct dbfs_symlink_ctx *ctx = (struct dbfs_symlink_ctx *) ctx_base;
       
    97     
       
    98     free(ctx->link);
       
    99     free(ctx->name);
       
   100 }
       
   101 
       
   102 void dbfs_symlink_commit (struct dbfs_trans *ctx_base) {
       
   103     struct dbfs_symlink_ctx *ctx = (struct dbfs_symlink_ctx *) ctx_base;
       
   104     struct fuse_entry_param e;
       
   105     int err;
       
   106     
       
   107     // build entry
       
   108     e.ino = e.attr.st_ino = ctx->ino;
       
   109     e.attr.st_mode = S_IFLNK | DBFS_SYMLINK_MODE;
       
   110     e.attr.st_size = strlen(ctx->link);
       
   111     e.attr.st_nlink = 1;
       
   112     e.attr_timeout = e.entry_timeout = CACHE_TIMEOUT;
       
   113 
       
   114     // reply
       
   115     if ((err = fuse_reply_entry(ctx_base->req, &e)))
       
   116         goto error;
       
   117 
       
   118     // req good
       
   119     ctx_base->req = NULL;
       
   120     
       
   121     // free
       
   122     dbfs_trans_free(ctx_base);
       
   123 
       
   124     // return
       
   125     return;
       
   126 
       
   127 error:
       
   128     dbfs_trans_fail(ctx_base, err);
       
   129 }
       
   130 
       
   131 void dbfs_symlink_filetree (const struct evsql_result_info *res, void *arg) {
       
   132     struct dbfs_symlink_ctx *ctx = arg;
       
   133     int err = EIO;
       
   134     
       
   135     // check results
       
   136     if (_dbfs_check_res(res, 0, 0) < 0)
       
   137         goto error;
       
   138     
       
   139     // commit
       
   140     dbfs_trans_commit(&ctx->base);
       
   141 
       
   142     // fallthrough for result_free
       
   143     err = 0;
       
   144 
       
   145 error:
       
   146     if (err)
       
   147         dbfs_trans_fail(&ctx->base, err);
       
   148 
       
   149     evsql_result_free(res);
       
   150 }
       
   151 
       
   152 void dbfs_symlink_inode (const struct evsql_result_info *res, void *arg) {
       
   153     struct dbfs_symlink_ctx *ctx = arg;
       
   154     struct dbfs *dbfs_ctx = fuse_req_userdata(ctx->base.req);
       
   155     int err = EIO;
       
   156     
       
   157     // check result
       
   158     if ((err = _dbfs_check_res(res, 1, 1)))
       
   159         SERROR(err = err > 0 ? ENOENT : EIO);
       
   160     
       
   161     // get ino
       
   162     if (evsql_result_uint32(res, 0, 0, &ctx->ino, 0))
       
   163         goto error;
       
   164 
       
   165     // insert file_tree entry
       
   166     const char *sql = 
       
   167         "INSERT"
       
   168         " INTO file_tree (name, parent, ino)"
       
   169         " VALUES ($1::varchar, $2::int4, $3::int4)";
       
   170     
       
   171     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
       
   172         EVSQL_PARAM ( STRING ),
       
   173         EVSQL_PARAM ( UINT32 ),
       
   174         EVSQL_PARAM ( UINT32 ),
       
   175 
       
   176         EVSQL_PARAMS_END
       
   177     };
       
   178 
       
   179     if (0
       
   180         ||  evsql_param_string(&params, 0, ctx->name)
       
   181         ||  evsql_param_uint32(&params, 1, ctx->parent)
       
   182         ||  evsql_param_uint32(&params, 2, ctx->ino)
       
   183     )
       
   184         goto error;
       
   185     
       
   186     // query
       
   187     if (evsql_query_params(dbfs_ctx->db, ctx->base.trans, sql, &params, dbfs_symlink_filetree, ctx))
       
   188         goto error;
       
   189     
       
   190     // fallthrough for result_free
       
   191     err = 0;
       
   192 
       
   193 error:
       
   194     if (err)
       
   195         dbfs_trans_fail(&ctx->base, err);
       
   196 
       
   197     evsql_result_free(res);
       
   198 }
       
   199 
       
   200 void dbfs_symlink_begin (struct dbfs_trans *ctx_base) {
       
   201     struct dbfs_symlink_ctx *ctx = (struct dbfs_symlink_ctx *) ctx_base;
       
   202     struct dbfs *dbfs_ctx = fuse_req_userdata(ctx_base->req);
       
   203 
       
   204     // insert inode
       
   205     const char *sql = 
       
   206         "INSERT"
       
   207         " INTO inodes (type, mode, link_path)"
       
   208         " VALUES ('LNK', $1::int2, $2::varchar)"
       
   209         " RETURNING inodes.ino"; 
       
   210     
       
   211     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
       
   212         EVSQL_PARAM ( UINT16 ),
       
   213         EVSQL_PARAM ( STRING ),
       
   214 
       
   215         EVSQL_PARAMS_END
       
   216     };
       
   217 
       
   218     if (0
       
   219         || evsql_param_uint16(&params, 0, DBFS_SYMLINK_MODE)
       
   220         || evsql_param_string(&params, 1, ctx->link)
       
   221     )
       
   222         goto error;
       
   223     
       
   224     if (evsql_query_params(dbfs_ctx->db, ctx_base->trans, sql, &params, dbfs_symlink_inode, ctx) == NULL)
       
   225         goto error;
       
   226     
       
   227     return;
       
   228 
       
   229 error:
       
   230     dbfs_trans_fail(ctx_base, EIO);
       
   231 }
       
   232 
       
   233 void dbfs_symlink (struct fuse_req *req, const char *link, fuse_ino_t parent, const char *name) {
       
   234     struct dbfs_symlink_ctx *ctx = NULL;
       
   235 
       
   236     // alloc
       
   237     if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
       
   238         ERROR("calloc");
       
   239 
       
   240     // start trans
       
   241     if (dbfs_trans_init(&ctx->base, req))
       
   242         goto error;
       
   243  
       
   244     // callbacks
       
   245     ctx->base.free_fn = dbfs_symlink_free;
       
   246     ctx->base.begin_fn = dbfs_symlink_begin;
       
   247     ctx->base.commit_fn = dbfs_symlink_commit;
       
   248    
       
   249     // state
       
   250     ctx->ino = 0;
       
   251     ctx->parent = parent;
       
   252     if (!((ctx->link = strdup(link)) && (ctx->name = strdup(name))))
       
   253         ERROR("strdup");
       
   254     
       
   255     // log
       
   256     INFO("[dbfs.symlink %p:%p] link=%s, parent=%lu, name=%s", ctx, req, link, parent, name);
       
   257 
       
   258     // wait
       
   259     return;
       
   260 
       
   261 error:
       
   262     if (ctx)
       
   263         dbfs_trans_fail(&ctx->base, EIO);
       
   264 }
       
   265 
       
   266