You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gentoo-overlay/app-arch/tarsync/files/tarsync-0.2.1-symlink.patch

140 lines
4.0 KiB

From 6654d41a14da2fc521e889f01669f0dbb89aef15 Mon Sep 17 00:00:00 2001
From: Zac Medico <zmedico@gentoo.org>
Date: Tue, 5 Oct 2021 23:21:53 -0700
Subject: [PATCH] Symlink support
Bug: https://bugs.gentoo.org/815823
Signed-off-by: Zac Medico <zmedico@gentoo.org>
---
main.c | 37 +++++++++++++++++++++++++++++++++++--
tar.c | 16 ++++++++++++++--
tar.h | 2 ++
3 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/main.c b/main.c
index 2c2da3e..448a9d0 100644
--- a/main.c
+++ b/main.c
@@ -257,7 +257,14 @@ main(int argc, char **argv)
// no need to seek. cfile handles resetting streams as needed
for(x=0; x < missing_count; x++) {
- if(copy_whole_file(&tar_cfh, missing[x]) != 0) {
+ if (missing[x]->type == SYMTYPE) {
+ if(copy_symlink(&tar_cfh, missing[x]) != 0) {
+ v0printf("failed transfering symlink %s\n", missing[x]->fullname);
+ exit(9);
+ }
+ continue;
+ }
+ else if(copy_whole_file(&tar_cfh, missing[x]) != 0) {
v0printf("failed transfering file %s\n", missing[x]->fullname);
exit(9);
}
@@ -673,6 +680,8 @@ int
check_existing_node(const struct dirent *de, const tar_entry *t, struct stat *st)
{
int type;
+ unsigned char linkname[TAR_LINKNAME_LEN];
+ ssize_t linkname_len;
type = convert_lstat_type_tar_type(de->d_name, st);
if(type < 0)
return -1;
@@ -682,6 +691,15 @@ check_existing_node(const struct dirent *de, const tar_entry *t, struct stat *st
return 2;
if(REGTYPE == type && (st->st_size != t->size || (check_mtime && t->mtime != st->st_mtime)))
return 3;
+ if (SYMTYPE == type) {
+ if ((linkname_len = readlink(de->d_name, linkname, TAR_LINKNAME_LEN)) == -1) {
+ return -1;
+ }
+ if(strncmp((const char *)linkname, (const char *)t->linkname, linkname_len) != 0) {
+ remove_node(de->d_name, st);
+ return 3;
+ }
+ }
return 0;
}
@@ -703,7 +721,22 @@ enforce_owner(const char *path, const tar_entry *t, struct stat *st)
}
return 0;
}
-
+
+int
+copy_symlink(cfile *tar_cfh, const tar_entry *ttent)
+{
+ v1printf("creating %s\n", ttent->fullname);
+
+ if (symlink(ttent->linkname, ttent->fullname) != 0) {
+ v0printf("failed creating symlink %s -> %s\n", ttent->fullname, ttent->linkname);
+ return -1;
+ }
+ if(lchown(ttent->fullname, ttent->uid, ttent->gid) != 0) {
+ v0printf("failed chown'ing %s\n", ttent->fullname);
+ return -1;
+ }
+ return 0;
+}
int
copy_whole_file(cfile *tar_cfh, const tar_entry *ttent)
diff --git a/tar.c b/tar.c
index 42dc8e7..514e5fb 100644
--- a/tar.c
+++ b/tar.c
@@ -214,8 +214,7 @@ read_entry(cfile *src_cfh, off_u64 start, tar_entry *entry)
case AREGTYPE:
entry->type = REGTYPE; break;
case SYMTYPE:
- v0printf("symlinks not supported\n");
- entry->type = TTAR_UNSUPPORTED_TYPE; break;
+ entry->type = SYMTYPE; break;
case LNKTYPE:
v0printf("hardlinks not supported!\n");
entry->type = TTAR_UNSUPPORTED_TYPE; break;
@@ -242,6 +241,17 @@ read_entry(cfile *src_cfh, off_u64 start, tar_entry *entry)
if(get_uid(block + TAR_UNAME_LOC, &entry->uid))
entry->uid = octal_str2long(block + TAR_UID_LOC, TAR_UID_LOC);
+ if (entry->type == SYMTYPE) {
+ name_len = strnlen((char *)block + TAR_LINKNAME_LOC, TAR_LINKNAME_LEN);
+ if((entry->linkname = (char *)malloc(name_len + 1)) == NULL){
+ v0printf("unable to allocate needed memory, bailing\n");
+ return MEM_ERROR;
+ }
+ memcpy(entry->linkname, block + TAR_LINKNAME_LOC, name_len);
+ entry->linkname[name_len] = '\0';
+ entry->linkname_len = name_len;
+ }
+
// if(entry->end % 512)
// entry->end += 512 - (entry->end % 512);
return 0;
@@ -256,6 +266,8 @@ convert_lstat_type_tar_type(const char *path, struct stat *st)
if(S_ISREG(st->st_mode)) {
if(st->st_nlink == 1)
return REGTYPE;
+ } else if(S_ISLNK(st->st_mode)) {
+ return SYMTYPE;
} else if(S_ISDIR(st->st_mode))
return DIRTYPE;
diff --git a/tar.h b/tar.h
index e9d9ee9..95f957c 100644
--- a/tar.h
+++ b/tar.h
@@ -78,6 +78,8 @@ typedef struct {
off_u64 size;
unsigned int fullname_len;
char *fullname;
+ unsigned int linkname_len;
+ char *linkname;
time_t mtime;
uid_t uid;
gid_t gid;
--
2.32.0