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