src/dbfs/mk.c
changeset 35 4f10421681d2
child 38 1fd4da071575
equal deleted inserted replaced
34:460f995d3769 35:4f10421681d2
       
     1 #include <stdlib.h>
       
     2 #include <assert.h>
       
     3 #include <string.h>
       
     4 
       
     5 #include "trans.h"
       
     6 #include "../lib/log.h"
       
     7 
       
     8 struct dbfs_mk_ctx {
       
     9     struct dbfs_trans base;
       
    10 
       
    11     const char *type, *data_expr;
       
    12     char *link, *name;
       
    13     uint16_t mode;
       
    14     uint32_t ino, parent;
       
    15 };
       
    16 
       
    17 // default mode for symlinks
       
    18 #define DBFS_SYMLINK_MODE 0777
       
    19 
       
    20 // max. size for an dbfs_mk INSERT query
       
    21 #define DBFS_MK_SQL_MAX 512
       
    22 
       
    23 void dbfs_mk_free (struct dbfs_trans *ctx_base) {
       
    24     struct dbfs_mk_ctx *ctx = (struct dbfs_mk_ctx *) ctx_base;
       
    25     
       
    26     free(ctx->link);
       
    27     free(ctx->name);
       
    28 }
       
    29 
       
    30 void dbfs_mk_commit (struct dbfs_trans *ctx_base) {
       
    31     struct dbfs_mk_ctx *ctx = (struct dbfs_mk_ctx *) ctx_base;
       
    32     struct fuse_entry_param e;
       
    33     int err;
       
    34     
       
    35     // build entry
       
    36     e.ino = e.attr.st_ino = ctx->ino;
       
    37     e.attr.st_mode = _dbfs_mode(ctx->type) | ctx->mode;
       
    38     e.attr.st_size = ctx->link ? strlen(ctx->link) : 0;
       
    39     e.attr.st_nlink = 1;
       
    40     e.attr_timeout = e.entry_timeout = CACHE_TIMEOUT;
       
    41 
       
    42     // reply
       
    43     if ((err = fuse_reply_entry(ctx_base->req, &e)))
       
    44         goto error;
       
    45 
       
    46     // req good
       
    47     ctx_base->req = NULL;
       
    48     
       
    49     // free
       
    50     dbfs_trans_free(ctx_base);
       
    51 
       
    52     // return
       
    53     return;
       
    54 
       
    55 error:
       
    56     dbfs_trans_fail(ctx_base, err);
       
    57 }
       
    58 
       
    59 void dbfs_mk_filetree (const struct evsql_result_info *res, void *arg) {
       
    60     struct dbfs_mk_ctx *ctx = arg;
       
    61     int err = EIO;
       
    62     
       
    63     // check results
       
    64     if (_dbfs_check_res(res, 0, 0) < 0)
       
    65         goto error;
       
    66     
       
    67     // commit
       
    68     dbfs_trans_commit(&ctx->base);
       
    69 
       
    70     // fallthrough for result_free
       
    71     err = 0;
       
    72 
       
    73 error:
       
    74     if (err)
       
    75         dbfs_trans_fail(&ctx->base, err);
       
    76 
       
    77     evsql_result_free(res);
       
    78 }
       
    79 
       
    80 void dbfs_mk_inode (const struct evsql_result_info *res, void *arg) {
       
    81     struct dbfs_mk_ctx *ctx = arg;
       
    82     struct dbfs *dbfs_ctx = fuse_req_userdata(ctx->base.req);
       
    83     int err = EIO;
       
    84     
       
    85     // check result
       
    86     if ((err = _dbfs_check_res(res, 1, 1)))
       
    87         SERROR(err = err > 0 ? ENOENT : EIO);
       
    88     
       
    89     // get ino
       
    90     if (evsql_result_uint32(res, 0, 0, &ctx->ino, 0))
       
    91         goto error;
       
    92 
       
    93     // insert file_tree entry
       
    94     const char *sql = 
       
    95         "INSERT"
       
    96         " INTO file_tree (name, parent, ino)"
       
    97         " VALUES ($1::varchar, $2::int4, $3::int4)";
       
    98     
       
    99     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
       
   100         EVSQL_PARAM ( STRING ),
       
   101         EVSQL_PARAM ( UINT32 ),
       
   102         EVSQL_PARAM ( UINT32 ),
       
   103 
       
   104         EVSQL_PARAMS_END
       
   105     };
       
   106 
       
   107     if (0
       
   108         ||  evsql_param_string(&params, 0, ctx->name)
       
   109         ||  evsql_param_uint32(&params, 1, ctx->parent)
       
   110         ||  evsql_param_uint32(&params, 2, ctx->ino)
       
   111     )
       
   112         goto error;
       
   113     
       
   114     // query
       
   115     if (evsql_query_params(dbfs_ctx->db, ctx->base.trans, sql, &params, dbfs_mk_filetree, ctx))
       
   116         goto error;
       
   117     
       
   118     // fallthrough for result_free
       
   119     err = 0;
       
   120 
       
   121 error:
       
   122     if (err)
       
   123         dbfs_trans_fail(&ctx->base, err);
       
   124 
       
   125     evsql_result_free(res);
       
   126 }
       
   127 
       
   128 void dbfs_mk_begin (struct dbfs_trans *ctx_base) {
       
   129     struct dbfs_mk_ctx *ctx = (struct dbfs_mk_ctx *) ctx_base;
       
   130     struct dbfs *dbfs_ctx = fuse_req_userdata(ctx_base->req);
       
   131     int ret;
       
   132 
       
   133     // insert inode
       
   134     char sql_buf[DBFS_MK_SQL_MAX];
       
   135     
       
   136     if ((ret = snprintf(sql_buf, DBFS_MK_SQL_MAX, 
       
   137         "INSERT"
       
   138         " INTO inodes (type, mode, data, link_path)"
       
   139         " VALUES ($1::char(3), $2::int2, %s, $3::varchar)"
       
   140         " RETURNING inodes.ino", ctx->data_expr ? ctx->data_expr : "NULL"
       
   141     )) >= DBFS_MK_SQL_MAX)
       
   142         ERROR("sql_buf is too small: %d", ret);
       
   143 
       
   144     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
       
   145         EVSQL_PARAM ( STRING ),
       
   146         EVSQL_PARAM ( UINT16 ),
       
   147         EVSQL_PARAM ( STRING ),
       
   148 
       
   149         EVSQL_PARAMS_END
       
   150     };
       
   151 
       
   152     if (0
       
   153         || evsql_param_string(&params, 0, ctx->type)
       
   154         || evsql_param_uint16(&params, 1, ctx->mode)
       
   155         || evsql_param_string(&params, 2, ctx->link)
       
   156     )
       
   157         goto error;
       
   158     
       
   159     if (evsql_query_params(dbfs_ctx->db, ctx_base->trans, sql_buf, &params, dbfs_mk_inode, ctx) == NULL)
       
   160         goto error;
       
   161     
       
   162     return;
       
   163 
       
   164 error:
       
   165     dbfs_trans_fail(ctx_base, EIO);
       
   166 }
       
   167 
       
   168 /*
       
   169  * It is assumed that name and link_path must be copied, but type remains useable
       
   170  */ 
       
   171 void dbfs_mk (struct fuse_req *req, fuse_ino_t parent, const char *name, const char *type, uint16_t mode, const char *data_expr, const char *link) {
       
   172     struct dbfs_mk_ctx *ctx = NULL;
       
   173 
       
   174     // alloc
       
   175     if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
       
   176         ERROR("calloc");
       
   177 
       
   178     // start trans
       
   179     if (dbfs_trans_init(&ctx->base, req))
       
   180         goto error;
       
   181  
       
   182     // callbacks
       
   183     ctx->base.free_fn = dbfs_mk_free;
       
   184     ctx->base.begin_fn = dbfs_mk_begin;
       
   185     ctx->base.commit_fn = dbfs_mk_commit;
       
   186    
       
   187     // state
       
   188     ctx->ino = 0;
       
   189     ctx->parent = parent;
       
   190     ctx->type = type;
       
   191     ctx->data_expr = data_expr;
       
   192     ctx->mode = mode;
       
   193 
       
   194     // copy volatile strings
       
   195     if (
       
   196             (link && (ctx->link = strdup(link)) == NULL)
       
   197         ||  (name && (ctx->name = strdup(name)) == NULL)
       
   198     )
       
   199         ERROR("strdup");
       
   200     
       
   201     // log
       
   202     INFO("[dbfs.mk %p:%p] parent=%lu, name=%s, type=%s, mode=%#04o data_expr=%s link=%s", ctx, req, parent, name, type, mode, data_expr, link);
       
   203 
       
   204     // wait
       
   205     return;
       
   206 
       
   207 error:
       
   208     if (ctx)
       
   209         dbfs_trans_fail(&ctx->base, EIO);
       
   210 }
       
   211 
       
   212 /*
       
   213  * These are all just aliases to dbfs_mk
       
   214  */ 
       
   215 void dbfs_mknod (struct fuse_req *req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev) {
       
   216     int err;
       
   217 
       
   218     if ((mode & S_IFMT) != S_IFREG)
       
   219         EERROR(err = EINVAL, "mode is not REG: %#08o", mode);
       
   220 
       
   221     dbfs_mk(req, parent, name, "REG", mode & 07777, "lo_create(0)", NULL);
       
   222 
       
   223     return;
       
   224 
       
   225 error:
       
   226     if ((err = fuse_reply_err(req, err)))
       
   227         EWARNING(err, "fuse_reply_error");
       
   228 }
       
   229 
       
   230 void dbfs_mkdir (struct fuse_req *req, fuse_ino_t parent, const char *name, mode_t mode) {
       
   231     dbfs_mk(req, parent, name, "DIR", mode, NULL, NULL);
       
   232 }
       
   233 
       
   234 
       
   235 void dbfs_symlink (struct fuse_req *req, const char *link, fuse_ino_t parent, const char *name) {
       
   236     dbfs_mk(req, parent, name, "LNK", DBFS_SYMLINK_MODE, NULL, link);
       
   237 }
       
   238