Actually checksum xattr values, not just names
We need to call lgetxattr() and not just llistxattr().
This commit is contained in:
parent
88c9851795
commit
05c35f2cf7
|
|
@ -61,15 +61,63 @@ canonicalize_xattrs (char *xattr_string, size_t len)
|
||||||
return g_string_free (result, FALSE);
|
return g_string_free (result, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
static gboolean
|
||||||
hacktree_get_xattrs_for_directory (const char *path,
|
read_xattr_name_array (const char *path,
|
||||||
char **out_xattrs, /* out */
|
const char *xattrs,
|
||||||
gsize *out_len, /* out */
|
size_t len,
|
||||||
|
GVariantBuilder *builder,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
char *xattrs = NULL;
|
const char *p;
|
||||||
|
|
||||||
|
p = xattrs;
|
||||||
|
while (p < xattrs+len)
|
||||||
|
{
|
||||||
ssize_t bytes_read;
|
ssize_t bytes_read;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
bytes_read = lgetxattr (path, p, NULL, 0);
|
||||||
|
if (bytes_read < 0)
|
||||||
|
{
|
||||||
|
ht_util_set_error_from_errno (error, errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (bytes_read == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buf = g_malloc (bytes_read);
|
||||||
|
if (lgetxattr (path, p, buf, bytes_read) < 0)
|
||||||
|
{
|
||||||
|
ht_util_set_error_from_errno (error, errno);
|
||||||
|
g_free (buf);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_add (builder, "(@ay@ay)",
|
||||||
|
g_variant_new_bytestring (p),
|
||||||
|
g_variant_new_fixed_array (G_VARIANT_TYPE ("y"), buf, bytes_read, 1));
|
||||||
|
|
||||||
|
g_free (buf);
|
||||||
|
p = p + strlen (p) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GVariant *
|
||||||
|
hacktree_get_xattrs_for_path (const char *path,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GVariant *ret = NULL;
|
||||||
|
GVariantBuilder builder;
|
||||||
|
char *xattr_names = NULL;
|
||||||
|
char *xattr_names_canonical = NULL;
|
||||||
|
ssize_t bytes_read;
|
||||||
|
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayay)"));
|
||||||
|
|
||||||
bytes_read = llistxattr (path, NULL, 0);
|
bytes_read = llistxattr (path, NULL, 0);
|
||||||
|
|
||||||
|
|
@ -83,27 +131,25 @@ hacktree_get_xattrs_for_directory (const char *path,
|
||||||
}
|
}
|
||||||
else if (bytes_read > 0)
|
else if (bytes_read > 0)
|
||||||
{
|
{
|
||||||
xattrs = g_malloc (bytes_read);
|
const char *p;
|
||||||
if (!llistxattr (path, xattrs, bytes_read))
|
xattr_names = g_malloc (bytes_read);
|
||||||
|
if (llistxattr (path, xattr_names, bytes_read) < 0)
|
||||||
{
|
{
|
||||||
ht_util_set_error_from_errno (error, errno);
|
ht_util_set_error_from_errno (error, errno);
|
||||||
g_free (xattrs);
|
goto out;
|
||||||
xattrs = NULL;
|
}
|
||||||
|
xattr_names_canonical = canonicalize_xattrs (xattr_names, bytes_read);
|
||||||
|
|
||||||
|
if (!read_xattr_name_array (path, xattr_names_canonical, bytes_read, &builder, error))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_xattrs = canonicalize_xattrs (xattrs, bytes_read);
|
ret = g_variant_builder_end (&builder);
|
||||||
*out_len = (gsize)bytes_read;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*out_xattrs = NULL;
|
|
||||||
*out_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = TRUE;
|
|
||||||
out:
|
out:
|
||||||
g_free (xattrs);
|
if (!ret)
|
||||||
|
g_variant_builder_clear (&builder);
|
||||||
|
g_free (xattr_names);
|
||||||
|
g_free (xattr_names_canonical);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,8 +163,7 @@ hacktree_stat_and_checksum_file (int dir_fd, const char *path,
|
||||||
GChecksum *content_and_meta_sha256 = NULL;
|
GChecksum *content_and_meta_sha256 = NULL;
|
||||||
char *stat_string = NULL;
|
char *stat_string = NULL;
|
||||||
ssize_t bytes_read;
|
ssize_t bytes_read;
|
||||||
char *xattrs = NULL;
|
GVariant *xattrs = NULL;
|
||||||
char *xattrs_canonicalized = NULL;
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
DIR *temp_dir = NULL;
|
DIR *temp_dir = NULL;
|
||||||
char *basename = NULL;
|
char *basename = NULL;
|
||||||
|
|
@ -159,39 +204,9 @@ hacktree_stat_and_checksum_file (int dir_fd, const char *path,
|
||||||
}
|
}
|
||||||
|
|
||||||
stat_string = stat_to_string (&stbuf);
|
stat_string = stat_to_string (&stbuf);
|
||||||
|
xattrs = hacktree_get_xattrs_for_path (path, error);
|
||||||
/* FIXME - Add llistxattrat */
|
if (!xattrs)
|
||||||
if (!S_ISLNK(stbuf.st_mode))
|
|
||||||
bytes_read = flistxattr (fd, NULL, 0);
|
|
||||||
else
|
|
||||||
bytes_read = llistxattr (path, NULL, 0);
|
|
||||||
|
|
||||||
if (bytes_read < 0)
|
|
||||||
{
|
|
||||||
if (errno != ENOTSUP)
|
|
||||||
{
|
|
||||||
ht_util_set_error_from_errno (error, errno);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (bytes_read > 0)
|
|
||||||
{
|
|
||||||
gboolean tmp;
|
|
||||||
xattrs = g_malloc (bytes_read);
|
|
||||||
/* FIXME - Add llistxattrat */
|
|
||||||
if (!S_ISLNK(stbuf.st_mode))
|
|
||||||
tmp = flistxattr (fd, xattrs, bytes_read);
|
|
||||||
else
|
|
||||||
tmp = llistxattr (path, xattrs, bytes_read);
|
|
||||||
|
|
||||||
if (!tmp)
|
|
||||||
{
|
|
||||||
ht_util_set_error_from_errno (error, errno);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
xattrs_canonicalized = canonicalize_xattrs (xattrs, bytes_read);
|
|
||||||
}
|
|
||||||
|
|
||||||
content_sha256 = g_checksum_new (G_CHECKSUM_SHA256);
|
content_sha256 = g_checksum_new (G_CHECKSUM_SHA256);
|
||||||
|
|
||||||
|
|
@ -235,7 +250,7 @@ hacktree_stat_and_checksum_file (int dir_fd, const char *path,
|
||||||
content_and_meta_sha256 = g_checksum_copy (content_sha256);
|
content_and_meta_sha256 = g_checksum_copy (content_sha256);
|
||||||
|
|
||||||
g_checksum_update (content_and_meta_sha256, (guint8*)stat_string, strlen (stat_string));
|
g_checksum_update (content_and_meta_sha256, (guint8*)stat_string, strlen (stat_string));
|
||||||
g_checksum_update (content_and_meta_sha256, (guint8*)xattrs_canonicalized, strlen (stat_string));
|
g_checksum_update (content_and_meta_sha256, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
|
||||||
|
|
||||||
*out_stbuf = stbuf;
|
*out_stbuf = stbuf;
|
||||||
*out_checksum = content_and_meta_sha256;
|
*out_checksum = content_and_meta_sha256;
|
||||||
|
|
@ -248,8 +263,8 @@ hacktree_stat_and_checksum_file (int dir_fd, const char *path,
|
||||||
g_free (symlink_target);
|
g_free (symlink_target);
|
||||||
g_free (basename);
|
g_free (basename);
|
||||||
g_free (stat_string);
|
g_free (stat_string);
|
||||||
g_free (xattrs);
|
if (xattrs)
|
||||||
g_free (xattrs_canonicalized);
|
g_variant_unref (xattrs);
|
||||||
if (content_sha256)
|
if (content_sha256)
|
||||||
g_checksum_free (content_sha256);
|
g_checksum_free (content_sha256);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,18 @@ typedef enum {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HACKTREE_SERIALIZED_TREE_VARIANT = 1,
|
HACKTREE_SERIALIZED_TREE_VARIANT = 1,
|
||||||
HACKTREE_SERIALIZED_COMMIT_VARIANT = 2,
|
HACKTREE_SERIALIZED_COMMIT_VARIANT = 2,
|
||||||
HACKTREE_SERIALIZED_DIRMETA_VARIANT = 3
|
HACKTREE_SERIALIZED_DIRMETA_VARIANT = 3,
|
||||||
|
HACKTREE_SERIALIZED_XATTR_VARIANT = 4
|
||||||
} HacktreeSerializedVariantType;
|
} HacktreeSerializedVariantType;
|
||||||
|
|
||||||
#define HACKTREE_SERIALIZED_VARIANT_FORMAT "(uv)"
|
#define HACKTREE_SERIALIZED_VARIANT_FORMAT "(uv)"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* xattr objects:
|
||||||
|
* a(ayay) - array of (name, value) pairs, both binary data, though name is a bytestring
|
||||||
|
*/
|
||||||
|
#define HACKTREE_XATTR_GVARIANT_FORMAT "a(ayay)"
|
||||||
|
|
||||||
#define HACKTREE_DIR_META_VERSION 0
|
#define HACKTREE_DIR_META_VERSION 0
|
||||||
/*
|
/*
|
||||||
* dirmeta objects:
|
* dirmeta objects:
|
||||||
|
|
@ -48,9 +55,9 @@ typedef enum {
|
||||||
* u - uid
|
* u - uid
|
||||||
* u - gid
|
* u - gid
|
||||||
* u - mode
|
* u - mode
|
||||||
* ay - xattrs
|
* a(ayay) - xattrs
|
||||||
*/
|
*/
|
||||||
#define HACKTREE_DIRMETA_GVARIANT_FORMAT "(uuuuay)"
|
#define HACKTREE_DIRMETA_GVARIANT_FORMAT "(uuuua(ayay))"
|
||||||
|
|
||||||
#define HACKTREE_TREE_VERSION 0
|
#define HACKTREE_TREE_VERSION 0
|
||||||
/*
|
/*
|
||||||
|
|
@ -75,9 +82,7 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
#define HACKTREE_COMMIT_GVARIANT_FORMAT "(ua{sv}sssts)"
|
#define HACKTREE_COMMIT_GVARIANT_FORMAT "(ua{sv}sssts)"
|
||||||
|
|
||||||
gboolean hacktree_get_xattrs_for_directory (const char *path,
|
GVariant *hacktree_get_xattrs_for_path (const char *path,
|
||||||
char **out_xattrs,
|
|
||||||
gsize *out_len,
|
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean hacktree_stat_and_checksum_file (int dirfd, const char *path,
|
gboolean hacktree_stat_and_checksum_file (int dirfd, const char *path,
|
||||||
|
|
|
||||||
|
|
@ -402,7 +402,7 @@ import_directory_meta (HacktreeRepo *self,
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
GChecksum *ret_checksum = NULL;
|
GChecksum *ret_checksum = NULL;
|
||||||
GVariant *dirmeta = NULL;
|
GVariant *dirmeta = NULL;
|
||||||
char *xattrs = NULL;
|
GVariant *xattrs = NULL;
|
||||||
gsize xattr_len;
|
gsize xattr_len;
|
||||||
|
|
||||||
if (lstat (path, &stbuf) < 0)
|
if (lstat (path, &stbuf) < 0)
|
||||||
|
|
@ -418,16 +418,17 @@ import_directory_meta (HacktreeRepo *self,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hacktree_get_xattrs_for_directory (path, &xattrs, &xattr_len, error))
|
xattrs = hacktree_get_xattrs_for_path (path, error);
|
||||||
|
if (!xattrs)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
dirmeta = g_variant_new ("(uuuu@ay)",
|
dirmeta = g_variant_new ("(uuuu@a(ayay))",
|
||||||
HACKTREE_DIR_META_VERSION,
|
HACKTREE_DIR_META_VERSION,
|
||||||
(guint32)stbuf.st_uid,
|
(guint32)stbuf.st_uid,
|
||||||
(guint32)stbuf.st_gid,
|
(guint32)stbuf.st_gid,
|
||||||
(guint32)(stbuf.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)),
|
(guint32)(stbuf.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)),
|
||||||
g_variant_new_fixed_array (G_VARIANT_TYPE ("y"),
|
xattrs);
|
||||||
xattrs, xattr_len, 1));
|
xattrs = NULL; /* was floating */
|
||||||
g_variant_ref_sink (dirmeta);
|
g_variant_ref_sink (dirmeta);
|
||||||
|
|
||||||
if (!import_gvariant_object (self, HACKTREE_SERIALIZED_DIRMETA_VARIANT,
|
if (!import_gvariant_object (self, HACKTREE_SERIALIZED_DIRMETA_VARIANT,
|
||||||
|
|
@ -448,7 +449,8 @@ import_directory_meta (HacktreeRepo *self,
|
||||||
*out_checksum = ret_checksum;
|
*out_checksum = ret_checksum;
|
||||||
*out_variant = dirmeta;
|
*out_variant = dirmeta;
|
||||||
}
|
}
|
||||||
g_free (xattrs);
|
if (xattrs)
|
||||||
|
g_variant_unref (xattrs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1473,10 +1475,9 @@ checkout_one_directory (HacktreeRepo *self,
|
||||||
|
|
||||||
dest_path = g_build_filename (destination, dirname, NULL);
|
dest_path = g_build_filename (destination, dirname, NULL);
|
||||||
|
|
||||||
g_variant_get (dir->meta_data, "(uuuu@ay)",
|
g_variant_get (dir->meta_data, "(uuuu@a(ayay))",
|
||||||
&version, &uid, &gid, &mode,
|
&version, &uid, &gid, &mode,
|
||||||
&xattr_variant);
|
&xattr_variant);
|
||||||
xattrs = g_variant_get_fixed_array (xattr_variant, &xattr_len, 1);
|
|
||||||
|
|
||||||
if (mkdir (dest_path, (mode_t)mode) < 0)
|
if (mkdir (dest_path, (mode_t)mode) < 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ set -e
|
||||||
|
|
||||||
. libtest.sh
|
. libtest.sh
|
||||||
|
|
||||||
echo '1..3'
|
echo '1..5'
|
||||||
|
|
||||||
setup_test_repository2
|
setup_test_repository2
|
||||||
echo 'ok setup'
|
echo 'ok setup'
|
||||||
|
|
@ -30,8 +30,10 @@ hacktree checkout $ht_repo HEAD $test_tmpdir/checkout2-head
|
||||||
echo 'ok checkout cmd'
|
echo 'ok checkout cmd'
|
||||||
cd $test_tmpdir/checkout2-head
|
cd $test_tmpdir/checkout2-head
|
||||||
assert_has_file firstfile
|
assert_has_file firstfile
|
||||||
|
echo 'ok checkout firstfile'
|
||||||
assert_has_file baz/cow
|
assert_has_file baz/cow
|
||||||
assert_has_file baz/saucer
|
assert_has_file baz/saucer
|
||||||
|
echo 'ok checkout baz (2)'
|
||||||
assert_has_file baz/deeper/ohyeah
|
assert_has_file baz/deeper/ohyeah
|
||||||
assert_has_file baz/another/y
|
assert_has_file baz/another/y
|
||||||
echo 'ok checkout verify exists'
|
echo 'ok checkout verify exists'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue