src/dbfs/link.c
changeset 33 c71f3053c714
parent 32 90e14e0df133
child 34 460f995d3769
equal deleted inserted replaced
32:90e14e0df133 33:c71f3053c714
       
     1 #include <stdlib.h>
       
     2 #include <assert.h>
       
     3 #include <string.h>
       
     4 
     1 #include "dbfs.h"
     5 #include "dbfs.h"
       
     6 #include "trans.h"
     2 
     7 
     3 #include "../lib/log.h"
     8 #include "../lib/log.h"
     4 
     9 
     5 void _dbfs_readlink_res (const struct evsql_result_info *res, void *arg) {
    10 void _dbfs_readlink_res (const struct evsql_result_info *res, void *arg) {
     6     struct fuse_req *req = arg;
    11     struct fuse_req *req = arg;
    15         
    20         
    16     // get our data
    21     // get our data
    17     if (0
    22     if (0
    18         ||  evsql_result_uint32(res, 0, 0, &ino,        0 ) // inodes.ino
    23         ||  evsql_result_uint32(res, 0, 0, &ino,        0 ) // inodes.ino
    19         ||  evsql_result_string(res, 0, 1, &type,       0 ) // inodes.type
    24         ||  evsql_result_string(res, 0, 1, &type,       0 ) // inodes.type
    20         ||  evsql_result_string(res, 0, 2, &link,       1 ) // inodes.symlink
    25         ||  evsql_result_string(res, 0, 2, &link,       1 ) // inodes.link_path
    21     )
    26     )
    22         EERROR(err = EIO, "invalid db data");
    27         EERROR(err = EIO, "invalid db data");
    23     
    28     
    24     // is it a symlink?
    29     // is it a symlink?
    25     if (_dbfs_mode(type) != S_IFLNK)
    30     if (_dbfs_mode(type) != S_IFLNK)
    45     
    50     
    46     INFO("[dbfs.readlink %p] ino=%lu", req, ino);
    51     INFO("[dbfs.readlink %p] ino=%lu", req, ino);
    47 
    52 
    48     const char *sql =
    53     const char *sql =
    49         "SELECT"
    54         "SELECT"
    50         " inodes.ino, inodes.type, inodes.symlink"
    55         " inodes.ino, inodes.type, inodes.link_path"
    51         " FROM inodes"
    56         " FROM inodes"
    52         " WHERE inodes.ino = $1::int4";
    57         " WHERE inodes.ino = $1::int4";
    53 
    58 
    54     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
    59     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
    55         EVSQL_PARAM ( UINT32 ),
    60         EVSQL_PARAM ( UINT32 ),
    75 error:
    80 error:
    76     if ((err = fuse_reply_err(req, err)))
    81     if ((err = fuse_reply_err(req, err)))
    77         EWARNING(err, "fuse_reply_err");
    82         EWARNING(err, "fuse_reply_err");
    78 
    83 
    79 }
    84 }
       
    85 
       
    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