diff options
| author | Rajesh Amaravathi <rajesh@redhat.com> | 2011-12-06 11:35:33 +0530 | 
|---|---|---|
| committer | Anand Avati <avati@gluster.com> | 2012-01-14 04:57:59 -0800 | 
| commit | 36cedb338ec1d021e189379f30100f0d983e3e01 (patch) | |
| tree | 18f6cf77cb43bccd4f31a683e80341d47c10fa66 | |
| parent | 4e76cea78b11e9290b16c2faa85cf81b8e32b7ea (diff) | |
core/setxattr: prevent users from setting glusterfs xattrs
* Each xlator prevents the user from setting glusterfs-internal
xattrs like trusted.gfid by handling it in respective setxattr
functions. The speacial case of trusted.gfid is handled in
fuse (Not in posix because posix_setxattr is used to set gfid).
* For xlators which did not define setxattr and/or fsetxattr,
the functions have been implemented with appropriate checks.
xlator         |     fops-added
_______________|__________________________
               |
1. afr         |     fsetxattr
2. stripe      |     setxatrr and fsetxattr
3. quota       |     setxattr and fsetxattr
Change-Id: Ib62abb7067415b23a708002f884d30e8866fbf48
BUG: 765487
Signed-off-by: Rajesh Amaravathi <rajesh@redhat.com>
Reviewed-on: http://review.gluster.com/685
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Amar Tumballi <amar@gluster.com>
| -rw-r--r-- | libglusterfs/src/common-utils.h | 19 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 5 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-inode-write.c | 227 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-inode-write.h | 6 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr.c | 1 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr.h | 5 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/pump.c | 7 | ||||
| -rw-r--r-- | xlators/cluster/dht/src/dht-common.c | 8 | ||||
| -rw-r--r-- | xlators/cluster/stripe/src/stripe.c | 70 | ||||
| -rw-r--r-- | xlators/features/quota/src/quota.c | 72 | ||||
| -rw-r--r-- | xlators/mount/fuse/src/fuse-bridge.c | 6 | 
11 files changed, 406 insertions, 20 deletions
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 6045cd3efe0..4e7f981b3fe 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -176,6 +176,25 @@ extern char *gf_mgmt_list[GF_MGMT_MAXVALUE];          } while (0);                                                    \ +#define GF_IF_INTERNAL_XATTR_GOTO(pattern, dict, trav, op_errno, label) \ +        do{                                                             \ +                if (!dict) {                                            \ +                        gf_log (THIS->name, GF_LOG_ERROR,               \ +                                "setxattr dict is null");               \ +                        goto label;                                     \ +                }                                                       \ +                trav = dict->members_list;                              \ +                while (trav) {                                          \ +                        if (!fnmatch (pattern, trav->key, 0)) {         \ +                                gf_log (THIS->name, GF_LOG_ERROR,       \ +                                        "attempt to set internal"       \ +                                        " xattr: %s", trav->key);       \ +                                op_errno = EPERM;                       \ +                                goto label;                             \ +                        }                                               \ +                        trav = trav->next;                              \ +                }                                                       \ +        } while(0);                                                     \  #define GF_FILE_CONTENT_REQUESTED(_xattr_req,_content_limit) \  	(dict_get_uint64 (_xattr_req, "glusterfs.content", _content_limit) == 0) diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index 22b30fdfa2e..c247d56b705 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -940,6 +940,11 @@ afr_local_cleanup (afr_local_t *local, xlator_t *this)                          dict_unref (local->cont.setxattr.dict);          } +        { /* fsetxattr */ +                if (local->cont.fsetxattr.dict) +                        dict_unref (local->cont.fsetxattr.dict); +        } +          { /* removexattr */                  GF_FREE (local->cont.removexattr.name);          } diff --git a/xlators/cluster/afr/src/afr-inode-write.c b/xlators/cluster/afr/src/afr-inode-write.c index 48094931f2e..cd6ba5e7df8 100644 --- a/xlators/cluster/afr/src/afr-inode-write.c +++ b/xlators/cluster/afr/src/afr-inode-write.c @@ -1355,8 +1355,8 @@ afr_setxattr_unwind (call_frame_t *frame, xlator_t *this)          if (main_frame) {                  AFR_STACK_UNWIND (setxattr, main_frame, -                                  local->op_ret, local->op_errno) -                        } +                                  local->op_ret, local->op_errno); +        }          return 0;  } @@ -1365,10 +1365,10 @@ int  afr_setxattr_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                         int32_t op_ret, int32_t op_errno)  { -        afr_local_t *   local = NULL; -        afr_private_t * priv  = NULL; -        int call_count  = -1; -        int need_unwind = 0; +        afr_local_t      *local         = NULL; +        afr_private_t    *priv          = NULL; +        int               call_count    = -1; +        int               need_unwind   = 0;          local = frame->local;          priv = this->private; @@ -1406,10 +1406,10 @@ afr_setxattr_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  int  afr_setxattr_wind (call_frame_t *frame, xlator_t *this)  { -        afr_local_t *local = NULL; -        afr_private_t *priv = NULL; -        int call_count = -1; -        int i = 0; +        afr_local_t      *local         = NULL; +        afr_private_t    *priv          = NULL; +        int               call_count    = -1; +        int               i             = 0;          local = frame->local;          priv = this->private; @@ -1446,7 +1446,7 @@ afr_setxattr_wind (call_frame_t *frame, xlator_t *this)  int  afr_setxattr_done (call_frame_t *frame, xlator_t *this)  { -        afr_local_t * local = frame->local; +        afr_local_t   *local    = frame->local;          local->transaction.unwind (frame, this); @@ -1459,16 +1459,23 @@ int  afr_setxattr (call_frame_t *frame, xlator_t *this,                loc_t *loc, dict_t *dict, int32_t flags)  { -        afr_private_t * priv  = NULL; -        afr_local_t   * local = NULL; +        afr_private_t  *priv              = NULL; +        afr_local_t    *local             = NULL;          call_frame_t   *transaction_frame = NULL; -        int ret = -1; -        int op_errno = 0; +        data_pair_t    *trav              = NULL; +        int             ret               = -1; +        int             op_errno          = EINVAL;          VALIDATE_OR_GOTO (frame, out);          VALIDATE_OR_GOTO (this, out);          VALIDATE_OR_GOTO (this->private, out); +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.afr.*", dict, +                                   trav, op_errno, out); + +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.afr.*", dict, +                                   trav, op_errno, out); +          priv = this->private;          QUORUM_CHECK(setxattr,out); @@ -1511,6 +1518,196 @@ out:          return 0;  } +/* {{{ fsetxattr */ + + +int +afr_fsetxattr_unwind (call_frame_t *frame, xlator_t *this) +{ +        afr_local_t    *local         = NULL; +        call_frame_t   *main_frame    = NULL; + +        local = frame->local; + +        LOCK (&frame->lock); +        { +                if (local->transaction.main_frame) +                        main_frame = local->transaction.main_frame; +                local->transaction.main_frame = NULL; +        } +        UNLOCK (&frame->lock); + +        if (main_frame) { +                AFR_STACK_UNWIND (fsetxattr, main_frame, +                                  local->op_ret, local->op_errno); +        } +        return 0; +} + + +int +afr_fsetxattr_wind_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                        int32_t op_ret, int32_t op_errno) +{ +        afr_local_t     *local       = NULL; +        afr_private_t   *priv        = NULL; +        int              call_count  = -1; +        int              need_unwind = 0; + +        local = frame->local; +        priv = this->private; + +        LOCK (&frame->lock); +        { +                if (op_ret != -1) { +                        if (local->success_count == 0) { +                                local->op_ret = op_ret; +                        } +                        local->success_count++; + +                        if (local->success_count == priv->child_count) { +                                need_unwind = 1; +                        } +                } + +                local->op_errno = op_errno; +        } +        UNLOCK (&frame->lock); + +        if (need_unwind) +                local->transaction.unwind (frame, this); + +        call_count = afr_frame_return (frame); + +        if (call_count == 0) { +                local->transaction.resume (frame, this); +        } + +        return 0; +} + + +int +afr_fsetxattr_wind (call_frame_t *frame, xlator_t *this) +{ +        afr_local_t        *local       = NULL; +        afr_private_t      *priv        = NULL; +        int                 call_count  = -1; +        int                 i           = 0; + +        local = frame->local; +        priv = this->private; + +        call_count = afr_pre_op_done_children_count (local->transaction.pre_op, +                                                     priv->child_count); + +        if (call_count == 0) { +                local->transaction.resume (frame, this); +                return 0; +        } + +        local->call_count = call_count; + +        for (i = 0; i < priv->child_count; i++) { +                if (local->transaction.pre_op[i]) { +                        STACK_WIND_COOKIE (frame, afr_fsetxattr_wind_cbk, +                                           (void *) (long) i, +                                           priv->children[i], +                                           priv->children[i]->fops->fsetxattr, +                                           local->fd, +                                           local->cont.fsetxattr.dict, +                                           local->cont.fsetxattr.flags); + +                        if (!--call_count) +                                break; +                } +        } + +        return 0; +} + + +int +afr_fsetxattr_done (call_frame_t *frame, xlator_t *this) +{ +        afr_local_t   *local   = frame->local; + +        local->transaction.unwind (frame, this); + +        AFR_STACK_DESTROY (frame); + +        return 0; +} + +int +afr_fsetxattr (call_frame_t *frame, xlator_t *this, +               fd_t *fd, dict_t *dict, int32_t flags) +{ +        afr_private_t    *priv              = NULL; +        afr_local_t      *local             = NULL; +        call_frame_t     *transaction_frame = NULL; +        int               ret               = -1; +        int               op_errno          = EINVAL; +        data_pair_t      *trav              = NULL; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (this->private, out); + +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.afr.*", dict, +                                   trav, op_errno, out); + +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.afr.*", dict, +                                   trav, op_errno, out); + +        if (ret) +                goto out; + +        priv = this->private; + +        QUORUM_CHECK(fsetxattr,out); + +        ALLOC_OR_GOTO (local, afr_local_t, out); + +        ret = afr_local_init (local, priv, &op_errno); +        if (ret < 0) +                goto out; + +        transaction_frame = copy_frame (frame); +        if (!transaction_frame) { +                goto out; +        } + +        transaction_frame->local = local; + +        local->op_ret = -1; + +        local->cont.fsetxattr.dict  = dict_ref (dict); +        local->cont.fsetxattr.flags = flags; + +        local->transaction.fop    = afr_fsetxattr_wind; +        local->transaction.done   = afr_fsetxattr_done; +        local->transaction.unwind = afr_fsetxattr_unwind; + +        local->fd                 = fd_ref (fd); + +        local->transaction.main_frame = frame; +        local->transaction.start  = LLONG_MAX - 1; +        local->transaction.len    = 0; + +        afr_transaction (transaction_frame, this, AFR_METADATA_TRANSACTION); + +        ret = 0; +out: +        if (ret < 0) { +                if (transaction_frame) +                        AFR_STACK_DESTROY (transaction_frame); +                AFR_STACK_UNWIND (fsetxattr, frame, -1, op_errno); +        } + +        return 0; +} +  /* }}} */  /* {{{ removexattr */ diff --git a/xlators/cluster/afr/src/afr-inode-write.h b/xlators/cluster/afr/src/afr-inode-write.h index f9aa7bd36f6..a2c3520f99f 100644 --- a/xlators/cluster/afr/src/afr-inode-write.h +++ b/xlators/cluster/afr/src/afr-inode-write.h @@ -63,7 +63,11 @@ afr_fsetattr (call_frame_t *frame, xlator_t *this,  int32_t  afr_setxattr (call_frame_t *frame, xlator_t *this, -	      loc_t *loc, dict_t *dict, int32_t flags); +              loc_t *loc, dict_t *dict, int32_t flags); + +int32_t +afr_fsetxattr (call_frame_t *frame, xlator_t *this, +               fd_t *fd, dict_t *dict, int32_t flags);  int32_t  afr_removexattr (call_frame_t *frame, xlator_t *this, diff --git a/xlators/cluster/afr/src/afr.c b/xlators/cluster/afr/src/afr.c index f3c3e7e7a82..22be68a65e4 100644 --- a/xlators/cluster/afr/src/afr.c +++ b/xlators/cluster/afr/src/afr.c @@ -396,6 +396,7 @@ struct xlator_fops fops = {          .truncate    = afr_truncate,          .ftruncate   = afr_ftruncate,          .setxattr    = afr_setxattr, +        .fsetxattr   = afr_fsetxattr,          .setattr     = afr_setattr,          .fsetattr    = afr_fsetattr,          .removexattr = afr_removexattr, diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h index 8568f1fd8d6..544c9142471 100644 --- a/xlators/cluster/afr/src/afr.h +++ b/xlators/cluster/afr/src/afr.h @@ -550,6 +550,11 @@ typedef struct _afr_local {                  } setxattr;                  struct { +                        dict_t *dict; +                        int32_t flags; +                } fsetxattr; + +                struct {                          char *name;                  } removexattr; diff --git a/xlators/cluster/afr/src/pump.c b/xlators/cluster/afr/src/pump.c index 1814c8b9ddc..8044fb85bf2 100644 --- a/xlators/cluster/afr/src/pump.c +++ b/xlators/cluster/afr/src/pump.c @@ -20,6 +20,7 @@  #include <unistd.h>  #include <sys/time.h>  #include <stdlib.h> +#include <fnmatch.h>  #ifndef _CONFIG_H  #define _CONFIG_H @@ -1642,15 +1643,17 @@ pump_setxattr (call_frame_t *frame, xlator_t *this,  	afr_private_t * priv  = NULL;  	afr_local_t   * local = NULL;  	call_frame_t   *transaction_frame = NULL; - +        data_pair_t   * trav  = NULL;  	int ret = -1; -  	int op_errno = 0;  	VALIDATE_OR_GOTO (frame, out);  	VALIDATE_OR_GOTO (this, out);  	VALIDATE_OR_GOTO (this->private, out); +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.pump*", dict, +                                   trav, op_errno, out); +  	priv = this->private;          if (!priv->use_afr_in_pump) {                  STACK_WIND (frame, default_setxattr_cbk, diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c index 16bb2c9cc7d..785ecbc615c 100644 --- a/xlators/cluster/dht/src/dht-common.c +++ b/xlators/cluster/dht/src/dht-common.c @@ -1706,12 +1706,16 @@ dht_fsetxattr (call_frame_t *frame, xlator_t *this,          xlator_t     *subvol   = NULL;          dht_local_t  *local    = NULL;          int           op_errno = EINVAL; +        data_pair_t  *trav     = NULL;          VALIDATE_OR_GOTO (frame, err);          VALIDATE_OR_GOTO (this, err);          VALIDATE_OR_GOTO (fd, err);          VALIDATE_OR_GOTO (fd->inode, err); +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.dht*", xattr, +                                   trav, op_errno, err); +          local = dht_local_init (frame, NULL, fd, GF_FOP_FSETXATTR);          if (!local) {                  op_errno = ENOMEM; @@ -1806,6 +1810,7 @@ dht_setxattr (call_frame_t *frame, xlator_t *this,          char          value[4096] = {0,};          int           forced_rebalance = 0;          int           call_cnt = 0; +        data_pair_t  *trav     = NULL;          VALIDATE_OR_GOTO (frame, err); @@ -1814,6 +1819,9 @@ dht_setxattr (call_frame_t *frame, xlator_t *this,          VALIDATE_OR_GOTO (loc->inode, err);          VALIDATE_OR_GOTO (loc->path, err); +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.dht*", xattr, +                                   trav, op_errno, err); +          conf   = this->private;          local = dht_local_init (frame, loc, NULL, GF_FOP_SETXATTR);          if (!local) { diff --git a/xlators/cluster/stripe/src/stripe.c b/xlators/cluster/stripe/src/stripe.c index 01064cd51d9..15cfb8f60e9 100644 --- a/xlators/cluster/stripe/src/stripe.c +++ b/xlators/cluster/stripe/src/stripe.c @@ -32,6 +32,7 @@   *  very much necessary, or else, use it in combination with AFR, to have a   *  backup copy.   */ +#include <fnmatch.h>  #include "stripe.h"  #include "libxlator.h" @@ -4167,6 +4168,72 @@ out:  } +int +stripe_setxattr_cbk (call_frame_t *frame, void *cookie, +                     xlator_t *this, int op_ret, int op_errno) +{ +        STRIPE_STACK_UNWIND (setxattr, frame, op_ret, op_errno); +        return 0; +} + +int +stripe_setxattr (call_frame_t *frame, xlator_t *this, +                 loc_t *loc, dict_t *dict, int flags) +{ +        data_pair_t    *trav     = NULL; +        int32_t         op_errno = EINVAL; + +        VALIDATE_OR_GOTO (frame, err); +        VALIDATE_OR_GOTO (this, err); +        VALIDATE_OR_GOTO (loc, err); + +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.*stripe*", dict, +                                   trav, op_errno, err); + +        STACK_WIND (frame, stripe_setxattr_cbk, +                    FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->setxattr, +                    loc, dict, flags); +        return 0; +err: +        STRIPE_STACK_UNWIND (setxattr, frame, -1,  op_errno); +        return 0; +} + + +int +stripe_fsetxattr_cbk (call_frame_t *frame, void *cookie, +                      xlator_t *this, int op_ret, int op_errno) +{ +        STRIPE_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno); +        return 0; +} + +int +stripe_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, +                  dict_t *dict, int flags) +{ +        data_pair_t    *trav     = NULL; +        int32_t         op_ret   = -1; +        int32_t         op_errno = EINVAL; + +        VALIDATE_OR_GOTO (frame, err); +        VALIDATE_OR_GOTO (this, err); +        VALIDATE_OR_GOTO (fd, err); + +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.*stripe*", dict, +                                   trav, op_errno, err); + +        STACK_WIND (frame, stripe_fsetxattr_cbk, +                    FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->fsetxattr, +                    fd, dict, flags); +        return 0; + err: +        STRIPE_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno); +        return 0; +} +  int32_t  stripe_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                       int32_t op_ret, int32_t op_errno, gf_dirent_t *orig_entries) @@ -4918,7 +4985,8 @@ struct xlator_fops fops = {          .fsetattr    = stripe_fsetattr,          .lookup      = stripe_lookup,          .mknod       = stripe_mknod, - +        .setxattr    = stripe_setxattr, +        .fsetxattr   = stripe_fsetxattr,          .getxattr    = stripe_getxattr,          .readdirp    = stripe_readdirp,  }; diff --git a/xlators/features/quota/src/quota.c b/xlators/features/quota/src/quota.c index 3d147bdb2b4..b2f53048f84 100644 --- a/xlators/features/quota/src/quota.c +++ b/xlators/features/quota/src/quota.c @@ -17,6 +17,8 @@    <http://www.gnu.org/licenses/>.  */ +#include <fnmatch.h> +  #include "quota.h"  #include "common-utils.h"  #include "defaults.h" @@ -2650,6 +2652,72 @@ err:          return 0;  } +int +quota_setxattr_cbk (call_frame_t *frame, void *cookie, +                    xlator_t *this, int op_ret, int op_errno) +{ +        QUOTA_STACK_UNWIND (setxattr, frame, op_ret, op_errno); +        return 0; +} + +int +quota_setxattr (call_frame_t *frame, xlator_t *this, +                loc_t *loc, dict_t *dict, int flags) +{ +        data_pair_t    *trav     = NULL; +        int             op_errno = EINVAL; +        int             op_ret   = -1; + +        VALIDATE_OR_GOTO (frame, err); +        VALIDATE_OR_GOTO (this, err); +        VALIDATE_OR_GOTO (loc, err); + +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.quota*", dict, +                                   trav, op_errno, err); + +        STACK_WIND (frame, quota_setxattr_cbk, +                    FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->setxattr, +                    loc, dict, flags); +        return 0; +err: +        QUOTA_STACK_UNWIND (setxattr, frame, op_ret, op_errno); +        return 0; +} + +int +quota_fsetxattr_cbk (call_frame_t *frame, void *cookie, +                     xlator_t *this, int op_ret, int op_errno) +{ +        QUOTA_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno); +        return 0; +} + +int +quota_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, +                 dict_t *dict, int flags) +{ +        data_pair_t    *trav     = NULL; +        int32_t         op_ret   = -1; +        int32_t         op_errno = EINVAL; + +        VALIDATE_OR_GOTO (frame, err); +        VALIDATE_OR_GOTO (this, err); +        VALIDATE_OR_GOTO (fd, err); + +        GF_IF_INTERNAL_XATTR_GOTO ("trusted.glusterfs.quota*", dict, +                                   trav, op_errno, err); + +        STACK_WIND (frame, quota_fsetxattr_cbk, +                    FIRST_CHILD(this), +                    FIRST_CHILD(this)->fops->fsetxattr, +                    fd, dict, flags); +        return 0; + err: +        QUOTA_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno); +        return 0; +} +  int32_t  quota_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -2950,7 +3018,9 @@ struct xlator_fops fops = {          .fsync     = quota_fsync,          .setattr   = quota_setattr,          .fsetattr  = quota_fsetattr, -        .mknod     = quota_mknod +        .mknod     = quota_mknod, +        .setxattr  = quota_setxattr, +        .fsetxattr = quota_fsetxattr  };  struct xlator_cbks cbks = { diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index 32c80075356..8c1cd8f7568 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -2641,6 +2641,12 @@ fuse_setxattr (xlator_t *this, fuse_in_header_t *finh, void *msg)                  return;          } +        if (!strcmp (GFID_XATTR_KEY, name)) { +                send_fuse_err (this, finh, EPERM); +                GF_FREE (finh); +                return; +        } +          GET_STATE (this, finh, state);          state->size = fsi->size;          ret = fuse_loc_fill (&state->loc, state, finh->nodeid, 0, NULL);  | 
