+ if (hdr->user[0]) {
+ int len = strlen(hdr->user);
+ put_word(len + 3); /* size */
+ put_byte(0x53); /* user name */
+ put_bytes(hdr->user, len);
+ }
+
+ if (hdr->header_level == 1) {
+ put_word(7); /* size */
+ put_byte(0x54); /* time stamp */
+ put_longword(hdr->unix_last_modified_stamp);
+ }
+}
+
+static size_t
+write_header_level0(data, hdr, pathname)
+ LzHeader *hdr;
+ char *data, *pathname;
+{
+ int limit;
+ int name_length;
+ size_t header_size;
+
+ setup_put(data);
+ memset(data, 0, LZHEADER_STORAGE);
+
+ put_byte(0x00); /* header size */
+ put_byte(0x00); /* check sum */
+ put_bytes(hdr->method, 5);
+ put_longword(hdr->packed_size);
+ put_longword(hdr->original_size);
+ put_longword(unix_to_generic_stamp(hdr->unix_last_modified_stamp));
+ put_byte(hdr->attribute);
+ put_byte(hdr->header_level); /* level 0 */
+
+ /* write pathname (level 0 header contains the directory part) */
+ name_length = strlen(pathname);
+ if (generic_format)
+ limit = 255 - I_GENERIC_HEADER_SIZE + 2;
+ else
+ limit = 255 - I_LEVEL0_HEADER_SIZE + 2;
+
+ if (name_length > limit) {
+ warning("the length of pathname \"%s\" is too long.", pathname);
+ name_length = limit;
+ }
+ put_byte(name_length);
+ put_bytes(pathname, name_length);
+ put_word(hdr->crc);
+
+ if (generic_format) {
+ header_size = I_GENERIC_HEADER_SIZE + name_length - 2;
+ data[I_HEADER_SIZE] = header_size;
+ data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
+ } else {
+ /* write old-style extend header */
+ put_byte(EXTEND_UNIX);
+ put_byte(CURRENT_UNIX_MINOR_VERSION);
+ put_longword(hdr->unix_last_modified_stamp);
+ put_word(hdr->unix_mode);
+ put_word(hdr->unix_uid);
+ put_word(hdr->unix_gid);
+
+ /* size of extended header is 12 */
+ header_size = I_LEVEL0_HEADER_SIZE + name_length - 2;
+ data[I_HEADER_SIZE] = header_size;
+ data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
+ }
+
+ return header_size + 2;
+}
+
+static size_t
+write_header_level1(data, hdr, pathname)
+ LzHeader *hdr;
+ char *data, *pathname;
+{
+ int name_length, dir_length, limit;
+ char *basename, *dirname;
+ size_t header_size;
+ char *extend_header_top;
+ size_t extend_header_size;
+
+ basename = strrchr(pathname, LHA_PATHSEP);
+ if (basename) {
+ basename++;
+ name_length = strlen(basename);
+ dirname = pathname;
+ dir_length = basename - dirname;
+ }
+ else {
+ basename = pathname;
+ name_length = strlen(basename);
+ dirname = "";
+ dir_length = 0;
+ }
+
+ setup_put(data);
+ memset(data, 0, LZHEADER_STORAGE);
+
+ put_byte(0x00); /* header size */
+ put_byte(0x00); /* check sum */
+ put_bytes(hdr->method, 5);
+ put_longword(hdr->packed_size);
+ put_longword(hdr->original_size);
+ put_longword(unix_to_generic_stamp(hdr->unix_last_modified_stamp));
+ put_byte(0x20);
+ put_byte(hdr->header_level); /* level 1 */
+
+ /* level 1 header: write filename (basename only) */
+ limit = 255 - I_LEVEL1_HEADER_SIZE + 2;
+ if (name_length > limit) {
+ put_byte(0); /* name length */
+ }
+ else {
+ put_byte(name_length);
+ put_bytes(basename, name_length);
+ }
+
+ put_word(hdr->crc);
+
+ if (generic_format)
+ put_byte(0x00);
+ else
+ put_byte(EXTEND_UNIX);
+
+ /* write extend header from here. */
+
+ extend_header_top = put_ptr+2; /* +2 for the field `next header size' */
+ header_size = extend_header_top - data - 2;
+
+ /* write filename and dirname */
+
+ if (name_length > limit) {
+ put_word(name_length + 3); /* size */
+ put_byte(0x01); /* filename */
+ put_bytes(basename, name_length);
+ }
+
+ if (dir_length > 0) {
+ put_word(dir_length + 3); /* size */
+ put_byte(0x02); /* dirname */
+ put_bytes(dirname, dir_length);
+ }
+
+ if (!generic_format)
+ write_unix_info(hdr);
+
+ put_word(0x0000); /* next header size */
+
+ extend_header_size = put_ptr - extend_header_top;
+ /* On level 1 header, the packed size field is contains the ext-header */
+ hdr->packed_size += put_ptr - extend_header_top;
+
+ /* put `skip size' */
+ setup_put(data + I_PACKED_SIZE);
+ put_longword(hdr->packed_size);
+
+ data[I_HEADER_SIZE] = header_size;
+ data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
+
+ return header_size + extend_header_size + 2;
+}
+
+static size_t
+write_header_level2(data, hdr, pathname)
+ LzHeader *hdr;
+ char *data, *pathname;
+{
+ int name_length, dir_length;
+ char *basename, *dirname;
+ size_t header_size;
+ char *extend_header_top;
+ char *headercrc_ptr;
+ unsigned int hcrc;
+
+ basename = strrchr(pathname, LHA_PATHSEP);
+ if (basename) {
+ basename++;
+ name_length = strlen(basename);
+ dirname = pathname;
+ dir_length = basename - dirname;
+ }
+ else {
+ basename = pathname;
+ name_length = strlen(basename);
+ dirname = "";
+ dir_length = 0;
+ }
+
+ setup_put(data);
+ memset(data, 0, LZHEADER_STORAGE);
+
+ put_word(0x0000); /* header size */
+ put_bytes(hdr->method, 5);
+ put_longword(hdr->packed_size);
+ put_longword(hdr->original_size);
+ put_longword(hdr->unix_last_modified_stamp);
+ put_byte(0x20);
+ put_byte(hdr->header_level); /* level 2 */
+
+ put_word(hdr->crc);
+
+ if (generic_format)
+ put_byte(0x00);
+ else
+ put_byte(EXTEND_UNIX);
+
+ /* write extend header from here. */
+
+ extend_header_top = put_ptr+2; /* +2 for the field `next header size' */
+
+ /* write common header */
+ put_word(5);
+ put_byte(0x00);
+ headercrc_ptr = put_ptr;
+ put_word(0x0000); /* header CRC */
+
+ /* write filename and dirname */
+ /* must have this header, even if the name_length is 0. */
+ put_word(name_length + 3); /* size */
+ put_byte(0x01); /* filename */
+ put_bytes(basename, name_length);
+
+ if (dir_length > 0) {
+ put_word(dir_length + 3); /* size */
+ put_byte(0x02); /* dirname */
+ put_bytes(dirname, dir_length);
+ }
+
+ if (!generic_format)
+ write_unix_info(hdr);
+
+ put_word(0x0000); /* next header size */
+
+ header_size = put_ptr - data;
+ if ((header_size & 0xff) == 0) {
+ /* cannot put zero at the first byte on level 2 header. */
+ /* adjust header size. */
+ put_byte(0); /* padding */
+ header_size++;
+ }
+
+ /* put header size */
+ setup_put(data + I_HEADER_SIZE);
+ put_word(header_size);
+
+ /* put header CRC in extended header */
+ INITIALIZE_CRC(hcrc);
+ hcrc = calccrc(hcrc, data, (unsigned int) header_size);
+ setup_put(headercrc_ptr);
+ put_word(hcrc);
+
+ return header_size;