]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tools: add a function to create a tar file header
authorWilly Tarreau <w@1wt.eu>
Wed, 18 Mar 2026 07:24:43 +0000 (08:24 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 18 Mar 2026 14:30:34 +0000 (15:30 +0100)
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.

include/haproxy/tools.h
src/tools.c

index 22a20a856ccde57e204507ed6cac68382f406e91..e311512119ecfd2b610bf802b4d3c14cb84fc16c 100644 (file)
@@ -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);
index 112b57e82148ef8176195ec8b2d17ef402c3bb64..5ad0c95aec239fabbd316335f2418097eb7f9fa8 100644 (file)
@@ -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 <fname>
+ * of size <size> and mode <mode>. An optional prefix directory name can be
+ * passed in <pfx>, and an optional symlink destination may be passed in
+ * <link>. NULL is accepted for <pfx> and <link> 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