Esempio n. 1
0
static INT64_T chirp_fs_local_fremovexattr(int fd, const char *name)
{
#ifdef CCTOOLS_OPSYS_DARWIN
	return fremovexattr(fd, name, 0);
#else
	return fremovexattr(fd, name);
#endif
}
Esempio n. 2
0
static INT64_T chirp_fs_local_fremovexattr(int fd, const char *name)
{
	PREAMBLE("fremovexattr(%d, `%s')", fd, name);
	SETUP_FILE
#ifdef CCTOOLS_OPSYS_DARWIN
	rc = fremovexattr(lfd, name, 0);
#else
	rc = fremovexattr(lfd, name);
#endif
	PROLOGUE
}
Esempio n. 3
0
int
ceph_os_fremovexattr(int fd, const char *name)
{
	int error = -1;

#if defined(__FreeBSD__)
	error = extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, name);
#elif defined(__linux__)
	error = fremovexattr(fd, name);
#elif defined(DARWIN)
	error = fremovexattr(fd, name, 0);
#endif

	return (error);
}
Esempio n. 4
0
File: syms.c Progetto: aoool/tiering
/**
 * @brief clear_xattrs Remove all known extended attributes except e_locked.
 *
 * @return  0: all known extended attributed were removed except e_locked
 *         -1: error happen during known extended attributes removal
 *             except e_locked; ENOATTR error is not an error and ignored
 */
int clear_xattrs( int fd ) {
        int ret = 0;
        /* e_locked, if currently set, will be removed by the daemon */

        if (  ( fremovexattr( fd, xattr_str[e_stub] ) == -1 )
           && ( errno != ENOATTR ) ) {
                ret = -1;
        }

        if (  ( fremovexattr( fd, xattr_str[e_object_id] ) == -1 )
           && ( errno != ENOATTR ) ) {
                ret = -1;
        }

        return ret;
}
Esempio n. 5
0
int mslnk_remove_xattr(mslnk_t *mslnk, const char *name) {
    int status;

    status = fremovexattr(mslnk->fdattrs, name);

    return status;
}
Esempio n. 6
0
int cap_set_fd(int fildes, cap_t cap_d)
{
    struct vfs_cap_data rawvfscap;
    int sizeofcaps;
    struct stat buf;

    if (fstat(fildes, &buf) != 0) {
	_cap_debug("unable to stat file descriptor %d", fildes);
	return -1;
    }
    if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
	_cap_debug("file descriptor %d for non-regular file", fildes);
	errno = EINVAL;
	return -1;
    }

    if (cap_d == NULL) {
	_cap_debug("deleting fildes capabilities");
	return fremovexattr(fildes, XATTR_NAME_CAPS);
    } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) {
	return -1;
    }

    _cap_debug("setting fildes capabilities");

    return fsetxattr(fildes, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
}
Boolean XARemoveOperationPerform(XAOperationRef opaqueRef, int fd, CFStringRef path)
{
	Boolean bRet = 0x00;
	
	XARemoveOperationRef operationRef = (XARemoveOperationRef)opaqueRef;
	
	CFIndex bSize = CFStringGetLength(operationRef->key) + 0x01;
	
	char *key = calloc(bSize, sizeof(*key));
	
	int options = XATTR_CREATE | XATTR_REPLACE;
	
	if(CFStringGetCString(operationRef->key, key, bSize, kCFStringEncodingUTF8))
	{
		int iRet = fremovexattr(fd, key, options);
		
		if(iRet < 0x00)
		{
			bRet = 0x00;
		}
	}
	
	free(key);
	
	return(bRet);
}
Esempio n. 8
0
fsal_status_t vfs_remove_extattr_by_id(struct fsal_obj_handle *obj_hdl,
				       const struct req_op_context *opctx,
				       unsigned int xattr_id)
{
	int rc;
	char name[MAXNAMLEN];
	struct vfs_fsal_obj_handle *obj_handle = NULL;
	int fd = -1;
	fsal_errors_t fe;

	obj_handle =
	    container_of(obj_hdl, struct vfs_fsal_obj_handle, obj_handle);
	fd = (obj_hdl->type == DIRECTORY) ?
		vfs_fsal_open(obj_handle, O_DIRECTORY, &fe) :
		vfs_fsal_open(obj_handle, O_RDWR, &fe);
	if (fd < 0)
		return fsalstat(fe, -fd);

	rc = xattr_id_to_name(fd, xattr_id, name);
	if (rc) {
		close(fd);
		return fsalstat(rc, errno);
	}
	rc = fremovexattr(fd, name);

	close(fd);

	if (rc != 0)
		return fsalstat(posix2fsal_error(errno), errno);

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Esempio n. 9
0
File: mdir.c Progetto: baoboa/rozofs
int mdir_remove_xattr(mdir_t *mdir, const char *name) {
    int status;

    status = fremovexattr(mdir->fdp, name);

    return status;
}
Esempio n. 10
0
fsal_status_t vfs_remove_extattr_by_name(struct fsal_obj_handle *obj_hdl,
					 const struct req_op_context *opctx,
					 const char *xattr_name)
{
	struct vfs_fsal_obj_handle *obj_handle = NULL;
	int fd = -1;
	int rc = 0;
	fsal_errors_t fe;

	obj_handle =
	    container_of(obj_hdl, struct vfs_fsal_obj_handle, obj_handle);

	fd = (obj_hdl->type == DIRECTORY) ?
		vfs_fsal_open(obj_handle, O_DIRECTORY, &fe) :
		vfs_fsal_open(obj_handle, O_RDWR, &fe);
	if (fd < 0)
		return fsalstat(fe, -fd);

	rc = fremovexattr(fd, xattr_name);

	close(fd);

	if (rc != 0)
		return fsalstat(posix2fsal_error(errno), errno);

	return fsalstat(ERR_FSAL_NO_ERROR, 0);

}
Esempio n. 11
0
static PyObject *
pax_deletextpax(PyObject *self, PyObject *args)
{
	const char *f_name;
	int fd;

	if(!PyArg_ParseTuple(args, "s", &f_name))
	{
		PyErr_SetString(PaxError, "pax_deletextpax: PyArg_ParseTuple failed");
		return NULL;
	}

	if((fd = open(f_name, O_RDONLY)) < 0)
	{
		PyErr_SetString(PaxError, "pax_deletextpax: open() failed");
		return NULL;
	}

	if( !fremovexattr(fd, PAX_NAMESPACE) )
	{
		close(fd);
		return Py_BuildValue("");
	}
	else
	{
		close(fd);
		PyErr_SetString(PaxError, "pax_deletextpax: fremovexattr() failed");
		return NULL;
	}
}
Esempio n. 12
0
File: xattr.c Progetto: 0day-ci/ceph
int
ceph_os_fremovexattr(int fd, const char *name)
{
	int error = -1;

#if defined(__FreeBSD__)
	error = extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, name);
#elif defined(__linux__)
	error = fremovexattr(fd, name);
#elif defined(DARWIN)
	error = fremovexattr(fd, name, 0);
	/* ENOATTR and ENODATA have different values */
	if (error < 0 && errno == ENOATTR)
		errno = ENODATA;
#endif

	return (error);
}
Esempio n. 13
0
static ssize_t xattr_fremovexattr(int fd, const char *name, int options) {
    if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) {
        return -1;
    }
    if (options & XATTR_XATTR_NOFOLLOW) {
        return -1;
    } else {
        return fremovexattr(fd, name);
    }
}
Esempio n. 14
0
JNIEXPORT void JNICALL
Java_sun_nio_fs_LinuxNativeDispatcher_fremovexattr0(JNIEnv* env, jclass clazz,
    jint fd, jlong nameAddress)
{
    int res = -1;
    const char* name = jlong_to_ptr(nameAddress);

    res = fremovexattr (fd, name);
    if (res == -1)
        throwUnixException(env, errno);
}
Esempio n. 15
0
File: xattr.c Progetto: szborows/rr
int main(int argc, char* argv[]) {
  char path[PATH_MAX];
  const char* home = getenv("HOME");
  int fd;
  int ret;

  snprintf(path, sizeof(path), "%s/rr-xattr-XXXXXX", home ? home : "/tmp");
  path[sizeof(path) - 1] = 0;
  fd = mkstemp(path);
  test_assert(0 <= fd);

  ret = setxattr(path, attr_name, attr_value, sizeof(attr_value), XATTR_CREATE);
  if (ret < 0 && errno == EOPNOTSUPP) {
    atomic_printf("Extended attributes not supported on file %s, "
                  "skipping test\n",
                  path);
  } else {
    char buf[sizeof(attr_value) + 1];

    test_assert(ret == 0);

    memset(buf, '-', sizeof(buf));

    ret = fgetxattr(fd, attr_name, buf, sizeof(buf) - 5);
    test_assert(ret == -1);
    test_assert(errno == ERANGE);
    test_assert(buf[0] == '-');

    ret =
        fsetxattr(fd, attr_name, attr_value, sizeof(attr_value), XATTR_REPLACE);
    test_assert(ret == 0);

    ret = getxattr(path, attr_name, buf, sizeof(buf));
    test_assert(ret == sizeof(attr_value));
    test_assert(0 == memcmp(attr_value, buf, sizeof(attr_value)));
    test_assert(buf[sizeof(attr_value)] == '-');

    ret = fremovexattr(fd, attr_name);
    test_assert(ret == 0);

    memset(buf, '-', sizeof(buf));

    ret = getxattr(path, attr_name, buf, sizeof(buf));
    test_assert(ret == -1);
    test_assert(errno == ENODATA);
    test_assert(buf[0] == '-');
  }

  test_assert(0 == unlink(path));

  atomic_puts("EXIT-SUCCESS");
  return 0;
}
Esempio n. 16
0
int rep_fremovexattr (int filedes, const char *name)
{
#if defined(HAVE_FREMOVEXATTR)
#ifndef XATTR_ADDITIONAL_OPTIONS
	return fremovexattr(filedes, name);
#else
/* So that we do not recursivly call this function */
#undef fremovexattr
	int options = 0;
	return fremovexattr(filedes, name, options);
#endif
#elif defined(HAVE_FREMOVEEA)
	return fremoveea(filedes, name);
#elif defined(HAVE_EXTATTR_DELETE_FD)
	char *s;
	int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
		EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
	const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;

	return extattr_delete_fd(filedes, attrnamespace, attrname);
#elif defined(HAVE_ATTR_REMOVEF)
	int flags = 0;
	char *attrname = strchr(name,'.') + 1;

	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;

	return attr_removef(filedes, attrname, flags);
#elif defined(HAVE_ATTROPEN)
	int ret = -1;
	int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
	if (attrdirfd >= 0) {
		ret = solaris_unlinkat(attrdirfd, name);
		close(attrdirfd);
	}
	return ret;
#else
	errno = ENOSYS;
	return -1;
#endif
}
Esempio n. 17
0
int main (int argc, char **argv)
{
    int fd;
    int err = 0;
    char *xattr_name = NULL;
    int op = 0;

    if (argc != 4) {
        usage ();
        exit (1);
    }

    op = atoi (argv[3]);

    if ((op != 0) && (op != 1)) {
        printf ("Invalid operation specified.\n");
        usage ();
        exit (1);
    }

    xattr_name = argv[2];

    fd = open(argv[1], O_RDWR);
    if (fd == -1) {
        printf ("Failed to open file %s\n", argv[1]);
        exit (1);
    }

    if (!op) {
        err = fsetxattr (fd, xattr_name, MY_XATTR_VAL,
                         strlen (MY_XATTR_VAL) + 1, XATTR_CREATE);

        if (err) {
            printf ("Failed to set xattr %s: %m\n", xattr_name);
            exit (1);
        }

    } else {
        err = fremovexattr (fd, xattr_name);

        if (err) {
            printf ("Failed to remove xattr %s: %m\n", xattr_name);
            exit (1);
        }
    }

    close (fd);

    return 0;
}
Esempio n. 18
0
int sys_fremovexattr (int filedes, const char *name)
{
#if defined(HAVE_FREMOVEXATTR)
	return fremovexattr(filedes, name);
#elif defined(HAVE_ATTR_REMOVEF)
	int flags = 0;
	char *attrname = strchr(name,'.') +1;
	
	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;

	return attr_removef(filedes, attrname, flags);
#else
	errno = ENOSYS;
	return -1;
#endif
}
Esempio n. 19
0
int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) {
        int r;

        assert(fd >= 0);
        assert(attr >= 0 && attr < _SMACK_ATTR_MAX);

        if (!mac_smack_use())
                return 0;

        if (label)
                r = fsetxattr(fd, smack_attr_to_string(attr), label, strlen(label), 0);
        else
                r = fremovexattr(fd, smack_attr_to_string(attr));
        if (r < 0)
                return -errno;

        return 0;
}
Esempio n. 20
0
int mac_smack_apply_ip_out_fd(int fd, const char *label) {
        int r = 0;

        assert(fd >= 0);

#ifdef HAVE_SMACK
        if (!mac_smack_use())
                return 0;

        if (label)
                r = fsetxattr(fd, "security.SMACK64IPOUT", label, strlen(label), 0);
        else
                r = fremovexattr(fd, "security.SMACK64IPOUT");
        if (r < 0)
                return -errno;
#endif

        return r;
}
Esempio n. 21
0
// Test fremovexattr
void barrier_fremovexattr_test( char* file ) {
    int ret = -1;
    int fd;
    
    // Set a xattr on the file
    barrier_fsetxattr_test( file );

    fd = open( file, O_WRONLY );
    if( fd < 0 ) {
        fprintf( stderr, "Error:%s\n", strerror(errno) );
    }

    ret = fremovexattr( fd, "user.filename" );
    if( ret == 0 ) {
        fprintf( stderr, "Remove xattr on file -  %s\n", file );
    } else {
        fprintf( stderr, "Error while fremovexattr operation - %s\n", strerror(errno) );
    }
    close(fd);
}   
Esempio n. 22
0
int remove_ea(enum FILE_TYPE ft, int fd)
{
	int ret = 0;

	switch (ft) {
	case NORMAL:
		ret = fremovexattr(fd, xattr_name);
		if (ret < 0) {
			ret = errno;
			fprintf(stderr, "Failed at fremovexattr(errno:%d,%s) "
				"on %s:xattr_name=%s\n", ret, strerror(ret),
				filename, xattr_name);
			ret = -1;
		}
		break;
	case SYMLINK:
		ret = lremovexattr(filename, xattr_name);
		if (ret < 0) {
			ret = errno;
			fprintf(stderr, "Failed at lremovexattr(errno:%d,%s) "
				"on %s:xattr_name=%s\n", ret, strerror(ret),
				filename, xattr_name);
			ret = -1;
		}
		break;
	case DIRECTORY:
		ret = removexattr(filename, xattr_name);
		if (ret < 0) {
			ret = errno;
			fprintf(stderr, "Failed at removexattr(errno:%d,%s) "
				"on %s:xattr_name=%s\n", ret, strerror(ret),
				filename, xattr_name);
			ret = -1;
		}
		break;
	default:
		break;
	}

	return ret;
}
Esempio n. 23
0
Boolean XAAttributeRemoveFileDescriptor(XAAttributeRef attributeRef, int fd)
{
	Boolean bRet = 0x01;
	
	CFIndex bSize = CFStringGetLength(attributeRef->name) + 0x01;
	
	char *key = calloc(bSize, sizeof(*key));
	
	int options = XATTR_CREATE | XATTR_REPLACE;
	
	if(CFStringGetCString(attributeRef->name, key, bSize, kCFStringEncodingUTF8))
	{
		int iRet = fremovexattr(fd, key, options);
		
		if(iRet < 0x00)
		{
			bRet = 0x00;
		}
	}
	
	free(key);
	
	return(bRet);
}
Esempio n. 24
0
int
fd_based_fops_1 (char *filename)
{
        int         fd        = 0;
        int         ret       = -1;
        struct stat stbuf     = {0,};
        char        wstr[50]  = {0,};
        char        rstr[50]  = {0,};

        fd = open (filename, O_RDWR|O_CREAT);
        if (fd < 0) {
                fd = 0;
                fprintf (stderr, "open failed : %s\n", strerror (errno));
                goto out;
        }

        ret = unlink (filename);
        if (ret < 0) {
                fprintf (stderr, "unlink failed : %s\n", strerror (errno));
                goto out;
        }

        strcpy (wstr, "This is my string\n");
        ret = write (fd, wstr, strlen(wstr));
        if (ret <= 0) {
                ret = -1;
                fprintf (stderr, "write failed: %s\n", strerror (errno));
                goto out;
        }

        ret = lseek (fd, 0, SEEK_SET);
        if (ret < 0) {
                fprintf (stderr, "lseek failed: %s\n", strerror (errno));
                goto out;
        }

        ret = read (fd, rstr, strlen(wstr));
        if (ret <= 0) {
                ret = -1;
                fprintf (stderr, "read failed: %s\n", strerror (errno));
                goto out;
        }

        ret = memcmp (rstr, wstr, strlen (wstr));
        if (ret != 0) {
                ret = -1;
                fprintf (stderr, "read returning junk\n");
                goto out;
        }

        ret = ftruncate (fd, 0);
        if (ret < 0) {
                fprintf (stderr, "ftruncate failed : %s\n", strerror (errno));
                goto out;
        }

        ret = fstat (fd, &stbuf);
        if (ret < 0) {
                fprintf (stderr, "fstat failed : %s\n", strerror (errno));
                goto out;
        }

        ret = fchmod (fd, 0640);
        if (ret < 0) {
                fprintf (stderr, "fchmod failed : %s\n", strerror (errno));
                goto out;
        }

        ret = fchown (fd, 10001, 10001);
        if (ret < 0) {
                fprintf (stderr, "fchown failed : %s\n", strerror (errno));
                goto out;
        }

        ret = fsync (fd);
        if (ret < 0) {
                fprintf (stderr, "fsync failed : %s\n", strerror (errno));
                goto out;
        }

        ret = fsetxattr (fd, "trusted.xattr-test", "working", 8, 0);
        if (ret < 0) {
                fprintf (stderr, "fsetxattr failed : %s\n", strerror (errno));
                goto out;
        }

        ret = fdatasync (fd);
        if (ret < 0) {
                fprintf (stderr, "fdatasync failed : %s\n", strerror (errno));
                goto out;
        }

        ret = flistxattr (fd, NULL, 0);
        if (ret <= 0) {
                ret = -1;
                fprintf (stderr, "flistxattr failed : %s\n", strerror (errno));
                goto out;
        }

        ret = fgetxattr (fd, "trusted.xattr-test", NULL, 0);
        if (ret <= 0) {
                ret = -1;
                fprintf (stderr, "fgetxattr failed : %s\n", strerror (errno));
                goto out;
        }

        ret = fremovexattr (fd, "trusted.xattr-test");
        if (ret < 0) {
                fprintf (stderr, "fremovexattr failed : %s\n", strerror (errno));
                goto out;
        }

        ret = 0;
out:
        if (fd)
                close (fd);

        return ret;
}
Esempio n. 25
0
int fsfr_funset_attr(int fd, const char* name)
{
	return fremovexattr(fd,name)?-errno:0;
}
Esempio n. 26
0
// 0 is success -1 is failure
int xattrkv_del(int db, char *key) {
    return fremovexattr(db, key, 0);
}
Esempio n. 27
0
/*
 *  stress_xattr
 *	stress the xattr operations
 */
int stress_xattr(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	pid_t pid = getpid();
	int ret, fd, rc = EXIT_FAILURE;
	char filename[PATH_MAX];

	ret = stress_temp_dir_mk(name, pid, instance);
	if (ret < 0)
		return exit_status(-ret);

	(void)stress_temp_filename(filename, sizeof(filename),
		name, pid, instance, mwc32());
	(void)umask(0077);
	if ((fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) {
		rc = exit_status(errno);
		pr_fail_err(name, "open");
		goto out;
	}
	(void)unlink(filename);

	do {
		int i, j;
		int ret;
		char attrname[32];
		char value[32];
		ssize_t sz;
		char *buffer;

		for (i = 0; i < 4096; i++) {
			snprintf(attrname, sizeof(attrname), "user.var_%d", i);
			snprintf(value, sizeof(value), "orig-value-%d", i);

			ret = fsetxattr(fd, attrname, value, strlen(value), XATTR_CREATE);
			if (ret < 0) {
				if (errno == ENOTSUP) {
					pr_inf(stderr, "%s stressor will be "
						"skipped, filesystem does not "
						"support xattr.\n", name);
				}
				if (errno == ENOSPC || errno == EDQUOT)
					break;
				pr_fail_err(name, "fsetxattr");
				goto out_close;
			}
		}
		for (j = 0; j < i; j++) {
			snprintf(attrname, sizeof(attrname), "user.var_%d", j);
			snprintf(value, sizeof(value), "value-%d", j);

			ret = fsetxattr(fd, attrname, value, strlen(value),
				XATTR_REPLACE);
			if (ret < 0) {
				if (errno == ENOSPC || errno == EDQUOT)
					break;
				pr_fail_err(name, "fsetxattr");
				goto out_close;
			}
		}
		for (j = 0; j < i; j++) {
			char tmp[sizeof(value)];

			snprintf(attrname, sizeof(attrname), "user.var_%d", j);
			snprintf(value, sizeof(value), "value-%d", j);

			ret = fgetxattr(fd, attrname, tmp, sizeof(tmp));
			if (ret < 0) {
				pr_fail_err(name, "fgetxattr");
				goto out_close;
			}
			if (strncmp(value, tmp, ret)) {
				pr_fail(stderr, "%s: fgetxattr values "
					"different %.*s vs %.*s\n",
					name, ret, value, ret, tmp);
				goto out_close;
			}
		}
		/* Determine how large a buffer we required... */
		sz = flistxattr(fd, NULL, 0);
		if (sz < 0) {
			pr_fail_err(name, "flistxattr");
			goto out_close;
		}
		buffer = malloc(sz);
		if (buffer) {
			/* ...and fetch */
			sz = flistxattr(fd, buffer, sz);
			free(buffer);

			if (sz < 0) {
				pr_fail_err(name, "flistxattr");
				goto out_close;
			}
		}
		for (j = 0; j < i; j++) {
			snprintf(attrname, sizeof(attrname), "user.var_%d", j);
			
			ret = fremovexattr(fd, attrname);
			if (ret < 0) {
				pr_fail_err(name, "fremovexattr");
				goto out_close;
			}
		}
		(*counter)++;
	} while (opt_do_run && (!max_ops || *counter < max_ops));

	rc = EXIT_SUCCESS;
out_close:
	(void)close(fd);
out:
	(void)stress_temp_dir_rm(name, pid, instance);
	return rc;
}
Esempio n. 28
0
int smack_remove_label_for_file(int fd, const char *xattr)
{
    return fremovexattr(fd, xattr);
}
Esempio n. 29
0
int hashcache(unsigned char digest[32], int fd, unsigned int flags)
{
	bool ask_recomp = flags & HC_RECOMPUTE;
	bool ask_comp = !(flags & HC_NOCOMPUTE);
	bool ask_update = !(flags & HC_NOUPDATE);
	bool ask_del = flags & HC_DELETE;

	struct stat st;

	if (-1 == fstat(fd, &st))
		return -ERR_SYSTEM;

	if (!S_ISREG(st.st_mode))
		return -ERR_NOFILE;

	uint64_t ino = st.st_ino;
	uint64_t size = st.st_size;
	uint64_t mt = st.st_mtime;

	uint32_t generation = 0;

	if (0 != ioctl(fd, FS_IOC_GETVERSION, &generation))
		if (errno != ENOTTY)	// unsupported
			return -ERR_SYSTEM;

	// not sure we need generation, also see racy-git

	unsigned char str[64] = { 0 };
	memcpy(str +  0, "HC01", 4);
	memcpy(str +  4, &generation, 4);
	memcpy(str +  8, &ino, 8);
	memcpy(str + 16, &mt, 8);
	memcpy(str + 24, &size, 8);

	unsigned char buf[64] = { 0 };
	bool have_attr = true;

	if (64 != fgetxattr(fd, attribute, buf, 64)) {

	 	// maybe handle wrong size by ignoring it

		if (errno != ENOATTR)
			return -ERR_SYSTEM;

		have_attr = false;
	}

	bool is_upd = have_attr && (0 == memcmp(str, buf, 32));

	// decide what to do

	bool do_comp = ask_recomp || (!(have_attr && is_upd) && ask_comp);
	bool do_update = ask_update && do_comp;
	bool do_delete = have_attr && (ask_del || (!do_comp && !is_upd && ask_update));

	memcpy(str + 32, buf + 32, 32);

	if (do_comp) {

		void* addr;
		if (MAP_FAILED == (addr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0)))
			return -ERR_SYSTEM;

		sha256(addr, size, str + 32);

		if (-1 == munmap(addr, size))
			return -ERR_SYSTEM;
	}

	bool mismatch = do_comp && have_attr && (0 != memcmp(str + 32, buf + 32, 32));

	// reconsider update
	do_update &= !(is_upd && !mismatch);

	if (do_update)
		if (-1 == fsetxattr(fd, attribute, str, sizeof(str), 0))
			return -ERR_SYSTEM;

	if (do_delete)
		if (-1 == fremovexattr(fd, attribute))
			return -ERR_SYSTEM;

	memcpy(digest, str + 32, 32);

	if (mismatch)
		return -ERR_MISMATCH;

	unsigned int rflags = 0;

	if (!have_attr)
		rflags |= HC_RET_NOATTR;

	if (do_comp)
		rflags |= HC_RET_COMP;

	if (!is_upd)
		rflags |= HC_RET_STALE;

	return rflags;
}