-static void append_string(char **p, const char *s)
-{
- unsigned int len = strlen(s);
- memcpy(*p, s, len);
- *p += len;
-}
-
-static void append_char(char **p, char c)
-{
- **p = c;
- *p += 1;
-}
-
-static void append_path_prefix(char **buffer, struct path_prefix *prefix)
-{
- if (!prefix)
- return;
- append_path_prefix(buffer, prefix->prev);
- append_string(buffer, prefix->name);
- append_char(buffer, '/');
-}
-
-static unsigned int path_prefix_len(struct path_prefix *prefix)
-{
- if (!prefix)
- return 0;
- return path_prefix_len(prefix->prev) + strlen(prefix->name) + 1;
-}
-
-static void append_path(char **p, int is_dir, const char *basepath,
- struct path_prefix *prefix, const char *path)
-{
- if (basepath) {
- append_string(p, basepath);
- append_char(p, '/');
- }
- append_path_prefix(p, prefix);
- append_string(p, path);
- if (is_dir)
- append_char(p, '/');
-}
-
-static unsigned int path_len(int is_dir, const char *basepath,
- struct path_prefix *prefix, const char *path)
-{
- unsigned int len = 0;
- if (basepath)
- len += strlen(basepath) + 1;
- len += path_prefix_len(prefix) + strlen(path);
- if (is_dir)
- len++;
- return len;
-}
-
-static void append_extended_header_prefix(char **p, unsigned int size,
- const char *keyword)
-{
- int len = sprintf(*p, "%u %s=", size, keyword);
- *p += len;
-}
-
-static unsigned int extended_header_len(const char *keyword,
- unsigned int valuelen)
-{
- /* "%u %s=%s\n" */
- unsigned int len = 1 + 1 + strlen(keyword) + 1 + valuelen + 1;
- if (len > 9)
- len++;
- if (len > 99)
- len++;
- return len;
-}
-
-static void append_extended_header(char **p, const char *keyword,
- const char *value, unsigned int len)
-{
- unsigned int size = extended_header_len(keyword, len);
- append_extended_header_prefix(p, size, keyword);
- memcpy(*p, value, len);
- *p += len;
- append_char(p, '\n');
-}
-
-static void write_header(const unsigned char *, char, const char *, struct path_prefix *,
- const char *, unsigned int, void *, unsigned long);
-
-/* stores a pax extended header directly in the block buffer */
-static void write_extended_header(const char *headerfilename, int is_dir,
- unsigned int flags, const char *basepath,
- struct path_prefix *prefix,
- const char *path, unsigned int namelen,
- void *content, unsigned int contentsize)
-{
- char *buffer, *p;
- unsigned int pathlen, size, linkpathlen = 0;
-
- size = pathlen = extended_header_len("path", namelen);
- if (flags & EXT_HEADER_LINKPATH) {
- linkpathlen = extended_header_len("linkpath", contentsize);
- size += linkpathlen;
- }
- write_header(NULL, TYPEFLAG_EXT_HEADER, NULL, NULL, headerfilename,
- 0100600, NULL, size);
-
- buffer = p = malloc(size);
- if (!buffer)
- die("git-tar-tree: %s", strerror(errno));
- append_extended_header_prefix(&p, pathlen, "path");
- append_path(&p, is_dir, basepath, prefix, path);
- append_char(&p, '\n');
- if (flags & EXT_HEADER_LINKPATH)
- append_extended_header(&p, "linkpath", content, contentsize);
- write_blocked(buffer, size);
- free(buffer);
-}
-