src/dbfs/link.c
changeset 56 9dfc861273e5
parent 42 40a3b13ffc9d
child 57 527d23bf6441
equal deleted inserted replaced
42:40a3b13ffc9d 56:9dfc861273e5
     1 #include "dbfs.h"
       
     2 
       
     3 /*
       
     4  * Handling simple ino-related ops, like lookup, readlink, unlink and link
       
     5  */
       
     6 
       
     7 #include "../lib/log.h"
       
     8 #include "../lib/misc.h"
       
     9 
       
    10 /*
       
    11  * Used for lookup and link
       
    12  */
       
    13 void dbfs_entry_res (const struct evsql_result_info *res, void *arg) {
       
    14     struct fuse_req *req = arg;
       
    15     struct fuse_entry_param e; ZINIT(e);
       
    16     int err = 0;
       
    17     
       
    18     uint32_t ino;
       
    19     
       
    20     // check the results
       
    21     if ((err = _dbfs_check_res(res, 1, 5)))
       
    22         SERROR(err = (err ==  1 ? ENOENT : EIO));
       
    23     
       
    24     // get the data
       
    25     if (0
       
    26         ||  evsql_result_uint32(res, 0, 0, &ino,        0 ) // inodes.ino
       
    27     )
       
    28         EERROR(err = EIO, "invalid db data");
       
    29         
       
    30     INFO("\t[dbfs.lookup] -> ino=%u", ino);
       
    31     
       
    32     // stat attrs
       
    33     if ((err = _dbfs_stat_info(&e.attr, res, 0, 1)))
       
    34         goto error;
       
    35 
       
    36     // other attrs
       
    37     e.ino = e.attr.st_ino = ino;
       
    38     e.attr_timeout = CACHE_TIMEOUT;
       
    39     e.entry_timeout = CACHE_TIMEOUT;
       
    40         
       
    41     // reply
       
    42     if ((err = -fuse_reply_entry(req, &e)))
       
    43         EERROR(err, "fuse_reply_entry");
       
    44 
       
    45 error:
       
    46     if (err && (err = -fuse_reply_err(req, err)))
       
    47         EWARNING(err, "fuse_reply_err");
       
    48 
       
    49     // free
       
    50     evsql_result_free(res);
       
    51 }
       
    52 
       
    53 void dbfs_lookup (struct fuse_req *req, fuse_ino_t parent, const char *name) {
       
    54     struct dbfs *ctx = fuse_req_userdata(req);
       
    55     struct evsql_query *query;
       
    56     int err;
       
    57 
       
    58     INFO("[dbfs.lookup] parent=%lu name=%s", parent, name);
       
    59     
       
    60     // query and params
       
    61     const char *sql = 
       
    62         "SELECT"
       
    63         " inodes.ino, " DBFS_STAT_COLS
       
    64         " FROM file_tree INNER JOIN inodes ON (file_tree.ino = inodes.ino)"
       
    65         " WHERE file_tree.parent = $1::int4 AND file_tree.name = $2::varchar";
       
    66     
       
    67     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
       
    68         EVSQL_PARAM ( UINT32 ),
       
    69         EVSQL_PARAM ( STRING ),
       
    70 
       
    71         EVSQL_PARAMS_END
       
    72     };
       
    73     
       
    74     // build params
       
    75     if (0
       
    76         ||  evsql_param_uint32(&params, 0, parent)
       
    77         ||  evsql_param_string(&params, 1, name)
       
    78     )
       
    79         EERROR(err = EIO, "evsql_param_*");
       
    80 
       
    81     // query
       
    82     if ((query = evsql_query_params(ctx->db, NULL, sql, &params, dbfs_entry_res, req)) == NULL)
       
    83         EERROR(err = EIO, "evsql_query_params");
       
    84 
       
    85     // handle interrupts
       
    86     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
       
    87     
       
    88     // wait
       
    89     return;
       
    90 
       
    91 error:
       
    92     if ((err = -fuse_reply_err(req, err)))
       
    93         EWARNING(err, "fuse_reply_err");
       
    94 }
       
    95 
       
    96 void _dbfs_readlink_res (const struct evsql_result_info *res, void *arg) {
       
    97     struct fuse_req *req = arg;
       
    98     int err = 0;
       
    99     
       
   100     uint32_t ino;
       
   101     const char *type, *link;
       
   102 
       
   103     // check the results
       
   104     if ((err = _dbfs_check_res(res, 1, 3)))
       
   105         SERROR(err = (err ==  1 ? ENOENT : EIO));
       
   106         
       
   107     // get our data
       
   108     if (0
       
   109         ||  evsql_result_uint32(res, 0, 0, &ino,        0 ) // inodes.ino
       
   110         ||  evsql_result_string(res, 0, 1, &type,       0 ) // inodes.type
       
   111         ||  evsql_result_string(res, 0, 2, &link,       1 ) // inodes.link_path
       
   112     )
       
   113         EERROR(err = EIO, "invalid db data");
       
   114     
       
   115     // is it a symlink?
       
   116     if (_dbfs_mode(type) != S_IFLNK)
       
   117         EERROR(err = EINVAL, "wrong type: %s", type);
       
   118     
       
   119     INFO("\t[dbfs.readlink %p] -> ino=%lu, type=%s, link=%s", req, (unsigned long int) ino, type, link);
       
   120     
       
   121     // reply
       
   122     if ((err = -fuse_reply_readlink(req, link)))
       
   123         EERROR(err, "fuse_reply_readlink");
       
   124 
       
   125 error:
       
   126     if (err && (err = -fuse_reply_err(req, err)))
       
   127         EWARNING(err, "fuse_reply_err");
       
   128 
       
   129     // free
       
   130     evsql_result_free(res);
       
   131 }
       
   132 
       
   133 void dbfs_readlink (struct fuse_req *req, fuse_ino_t ino) {
       
   134     struct dbfs *ctx = fuse_req_userdata(req);
       
   135     struct evsql_query *query;
       
   136     int err;
       
   137     
       
   138     INFO("[dbfs.readlink %p] ino=%lu", req, ino);
       
   139 
       
   140     const char *sql =
       
   141         "SELECT"
       
   142         " inodes.ino, inodes.type, inodes.link_path"
       
   143         " FROM inodes"
       
   144         " WHERE inodes.ino = $1::int4";
       
   145 
       
   146     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
       
   147         EVSQL_PARAM ( UINT32 ),
       
   148 
       
   149         EVSQL_PARAMS_END
       
   150     };
       
   151 
       
   152     // build params
       
   153     if (0
       
   154         ||  evsql_param_uint32(&params, 0, ino)
       
   155     )
       
   156         SERROR(err = EIO);
       
   157         
       
   158     // query
       
   159     if ((query = evsql_query_params(ctx->db, NULL, sql, &params, _dbfs_readlink_res, req)) == NULL)
       
   160         SERROR(err = EIO);
       
   161 
       
   162     // handle interrupts
       
   163     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
       
   164     
       
   165     // wait
       
   166     return;
       
   167 
       
   168 error:
       
   169     if ((err = -fuse_reply_err(req, err)))
       
   170         EWARNING(err, "fuse_reply_err");
       
   171 
       
   172 }
       
   173 
       
   174 #define SETERR(err_var, err_val, bool_val) ((err_var) = bool_val ? (err_val) : 0)
       
   175 
       
   176 void dbfs_unlink_res (const struct evsql_result_info *res, void *arg) {
       
   177     struct fuse_req *req = arg;
       
   178     int err = 0;
       
   179     
       
   180     // check the results
       
   181     // XXX: reply with ENOTEMPTY if it fails due to this inode being a dir
       
   182     if ((err = dbfs_check_result(res, 1, 0)))
       
   183         goto error;
       
   184         
       
   185     INFO("\t[dbfs.unlink %p] -> OK", req);
       
   186     
       
   187     // reply
       
   188     if ((err = -fuse_reply_err(req, 0)))
       
   189         EERROR(err, "fuse_reply_err");
       
   190 
       
   191 error:
       
   192     if (err && (err = -fuse_reply_err(req, err)))
       
   193         EWARNING(err, "fuse_reply_err");
       
   194 
       
   195     // free
       
   196     evsql_result_free(res);
       
   197 }
       
   198 
       
   199 void dbfs_unlink (struct fuse_req *req, fuse_ino_t parent, const char *name) {
       
   200     struct dbfs *ctx = fuse_req_userdata(req);
       
   201     struct evsql_query *query;
       
   202     int err;
       
   203     
       
   204     INFO("[dbfs.unlink %p] parent=%lu, name=%s", req, parent, name);
       
   205 
       
   206     const char *sql =
       
   207         "DELETE"
       
   208         " FROM file_tree"
       
   209         " WHERE parent = $1::int4 AND name = $2::varchar";
       
   210 
       
   211     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
       
   212         EVSQL_PARAM ( UINT32 ),
       
   213         EVSQL_PARAM ( STRING ),
       
   214 
       
   215         EVSQL_PARAMS_END
       
   216     };
       
   217 
       
   218     // build params
       
   219     if (0
       
   220         ||  evsql_param_uint32(&params, 0, parent)
       
   221         ||  evsql_param_string(&params, 1, name)
       
   222     )
       
   223         SERROR(err = EIO);
       
   224         
       
   225     // query
       
   226     if ((query = evsql_query_params(ctx->db, NULL, sql, &params, dbfs_unlink_res, req)) == NULL)
       
   227         SERROR(err = EIO);
       
   228 
       
   229     // handle interrupts
       
   230     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
       
   231     
       
   232     // wait
       
   233     return;
       
   234 
       
   235 error:
       
   236     if ((err = -fuse_reply_err(req, err)))
       
   237         EWARNING(err, "fuse_reply_err");
       
   238 }
       
   239 
       
   240 void dbfs_link (struct fuse_req *req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname) {
       
   241     struct dbfs *ctx = fuse_req_userdata(req);
       
   242     struct evsql_query *query;
       
   243     int err;
       
   244     
       
   245     INFO("[dbfs.link %p] ino=%lu, newparent=%lu, newname=%s", req, ino, newparent, newname);
       
   246 
       
   247     const char *sql =
       
   248         "SELECT ino, type, mode, size, nlink FROM dbfs_link($1::int4, $2::int4, $3::varchar)";
       
   249 
       
   250     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
       
   251         EVSQL_PARAM ( UINT32 ),
       
   252         EVSQL_PARAM ( UINT32 ),
       
   253         EVSQL_PARAM ( STRING ),
       
   254 
       
   255         EVSQL_PARAMS_END
       
   256     };
       
   257 
       
   258     // build params
       
   259     if (0
       
   260         ||  evsql_param_uint32(&params, 0, ino)
       
   261         ||  evsql_param_uint32(&params, 1, newparent)
       
   262         ||  evsql_param_string(&params, 2, newname)
       
   263     )
       
   264         SERROR(err = EIO);
       
   265         
       
   266     // query
       
   267     if ((query = evsql_query_params(ctx->db, NULL, sql, &params, dbfs_entry_res, req)) == NULL)
       
   268         SERROR(err = EIO);
       
   269 
       
   270     // handle interrupts
       
   271     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
       
   272     
       
   273     // wait
       
   274     return;
       
   275 
       
   276 error:
       
   277     if ((err = -fuse_reply_err(req, err)))
       
   278         EWARNING(err, "fuse_reply_err");   
       
   279 }