From: Willy Tarreau Date: Wed, 18 Mar 2026 07:24:43 +0000 (+0100) Subject: MINOR: tools: add a function to create a tar file header X-Git-Tag: v3.4-dev7~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c1dfea3ab3283b712240256b704c442b5b96d42c;p=thirdparty%2Fhaproxy.git MINOR: tools: add a function to create a tar file header The purpose here is to create a tar file header in memory from a known file name, prefix, size and mode. It will be used to prepare archives of libs in use for improved debugging, but may probably be useful for other purposes due to its simplicity. --- diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index 22a20a856..e31151211 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -1147,6 +1147,7 @@ void dump_hex(struct buffer *out, const char *pfx, const void *buf, int len, int int may_access(const void *ptr); const void *resolve_sym_name(struct buffer *buf, const char *pfx, const void *addr); const void *resolve_dso_name(struct buffer *buf, const char *pfx, const void *addr); +void make_tar_header(char *output, const char *pfx, const char *fname, const char *link, size_t size, mode_t mode); const char *get_exec_path(void); void *get_sym_curr_addr(const char *name); void *get_sym_next_addr(const char *name); diff --git a/src/tools.c b/src/tools.c index 112b57e82..5ad0c95ae 100644 --- a/src/tools.c +++ b/src/tools.c @@ -5809,6 +5809,71 @@ const void *resolve_dso_name(struct buffer *buf, const char *pfx, const void *ad return NULL; } +/* make a simplistic tar header (512 bytes) into output for file name + * of size and mode . An optional prefix directory name can be + * passed in , and an optional symlink destination may be passed in + * . NULL is accepted for and if unused. Note that here we + * may abuse the link destination that is normally not used with regular files + * to place a magic. + */ +void make_tar_header(char *output, const char *pfx, const char *fname, const char *link, size_t size, mode_t mode) +{ + uint i, csum; + + union { + uchar buffer[512]; /* raw data */ + struct { /* byte offset */ + char name[100]; /* 0 */ + char mode[8]; /* 100 : octal */ + char uid[8]; /* 108 : octal */ + char gid[8]; /* 116 : octal */ + char size[12]; /* 124 : octal */ + char mtime[12]; /* 136 : octal */ + char chksum[8]; /* 148 : sum of the header's bytes */ + char typeflag; /* 156 : '0' = regular file */ + char linkname[100]; /* 157 */ + char magic_ver[8]; /* 257 : "ustar \0" or "ustar\0""00" */ + char uname[32]; /* 265 */ + char gname[32]; /* 297 */ + char devmajor[8]; /* 329 */ + char devminor[8]; /* 337 */ + char prefix[155]; /* 345 */ + char pad12[12]; /* 500 */ + } hdr; + } blk = { + .hdr = { + .name = "", + .mode = "", + .uid = "0000000", + .gid = "0000000", + .size = "00000000000", + .mtime = "00000000000", + .chksum = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, + .typeflag = '0', // regular file + .magic_ver = { 'u', 's', 't', 'a', 'r', '\0', '0', '0' }, + .uname = "root", + .gname = "root", + .devmajor = "0", + .devminor = "0", + }, + }; + + strlcpy2(blk.hdr.linkname, link ? link : NULL, sizeof(blk.hdr.linkname)); + strlcpy2(blk.hdr.prefix, pfx ? pfx : NULL, sizeof(blk.hdr.prefix)); + strlcpy2(blk.hdr.name, fname, sizeof(blk.hdr.name)); + snprintf(blk.hdr.size, sizeof(blk.hdr.size), "%llo", (ullong)size); + snprintf(blk.hdr.mode, sizeof(blk.hdr.mode), "%07o", (uint)mode & 0x1FFFFF); + + /* cksum: 6 octal bytes followed by NUL then space. Computed with cksum + * preset to 8 spaces. + */ + for (i = csum = 0; i < 512; i++) + csum += blk.buffer[i]; + + snprintf(blk.hdr.chksum, sizeof(blk.hdr.chksum), "%06o", csum); + memcpy(output, &blk, sizeof(blk)); +} + /* On systems where this is supported, let's provide a possibility to enumerate * the list of object files. The output is appended to a buffer initialized by * the caller, with one name per line. A trailing zero is always emitted if data