X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fcreate.c;h=9164ab9bbda6c5412476dd677771a22225da4f9c;hb=8c0a6b24b21e67649d34c517c81312fd34fd7fc7;hp=b3e4d73e9d172fb7c1dd4fe71addaef359db181f;hpb=fe4ee38fce628e37fb3d5f562d0ca21840760b66;p=chaz%2Ftar diff --git a/src/create.c b/src/create.c index b3e4d73..9164ab9 100644 --- a/src/create.c +++ b/src/create.c @@ -353,6 +353,15 @@ write_eot (void) set_next_block_after (pointer); } +/* Copy at most LEN bytes from SRC to DST. Terminate with NUL unless + SRC is LEN characters long */ +static void +tar_copy_str (char *dst, const char *src, size_t len) +{ + dst[len-1] = 0; + strncpy (dst, src, len); +} + /* Write a "private" header */ static union block * start_private_header (const char *name, size_t size) @@ -362,8 +371,7 @@ start_private_header (const char *name, size_t size) memset (header->buffer, 0, sizeof (union block)); - strncpy (header->header.name, name, NAME_FIELD_SIZE); - header->header.name[NAME_FIELD_SIZE - 1] = '\0'; + tar_copy_str (header->header.name, name, NAME_FIELD_SIZE); OFF_TO_CHARS (size, header->header.size); time (&t); @@ -386,9 +394,7 @@ write_short_name (struct tar_stat_info *st) { union block *header = find_next_block (); memset (header->buffer, 0, sizeof (union block)); - - strncpy (header->header.name, st->file_name, NAME_FIELD_SIZE); - header->header.name[NAME_FIELD_SIZE - 1] = '\0'; + tar_copy_str (header->header.name, st->file_name, NAME_FIELD_SIZE); return header; } @@ -451,7 +457,7 @@ write_ustar_long_name (const char *name) } i = split_long_name (name, length); - if (i == 0) + if (i == 0 || length - i -1 > NAME_FIELD_SIZE) { WARN ((0, 0, _("%s: file name is too long (cannot be split); not dumped"), @@ -463,7 +469,7 @@ write_ustar_long_name (const char *name) header = find_next_block (); memset (header->buffer, 0, sizeof (header->buffer)); memcpy (header->header.prefix, name, i); - memcpy (header->header.name, name + i + 1, length - i); + memcpy (header->header.name, name + i + 1, length - i - 1); return header; } @@ -570,7 +576,7 @@ write_extended (union block *old_header, char type) static union block * write_header_name (struct tar_stat_info *st) { - if (NAME_FIELD_SIZE <= strlen (st->file_name)) + if (NAME_FIELD_SIZE < strlen (st->file_name)) return write_long_name (st); else return write_short_name (st); @@ -588,8 +594,6 @@ start_header (const char *name, struct tar_stat_info *st) union block *header; name = safer_name_suffix (name, 0); - if (name[0] == '.' && name[1] == 0) /*FIXME!!!*/ - return NULL; assign_string (&st->file_name, name); header = write_header_name (st); @@ -1217,15 +1221,6 @@ dump_file (char *p, int top_level, dev_t parent_device) block_ordinal = current_block_ordinal (); current_stat_info.stat.st_size = 0; /* force 0 size on dir */ - /* FIXME: If people could really read standard archives, this - should be: - - header - = start_header (standard_option ? p : namebuf, ¤t_stat_info); - - but since they'd interpret DIRTYPE blocks as regular - files, we'd better put the / on the name. */ - header = start_header (namebuf, ¤t_stat_info); if (!header) return; @@ -1358,17 +1353,15 @@ dump_file (char *p, int top_level, dev_t parent_device) block_ordinal = current_block_ordinal (); assign_string (¤t_stat_info.link_name, link_name); - if (NAME_FIELD_SIZE <= strlen (link_name)) + if (NAME_FIELD_SIZE < strlen (link_name)) write_long_link (¤t_stat_info); current_stat_info.stat.st_size = 0; header = start_header (p, ¤t_stat_info); if (!header) return; - strncpy (header->header.linkname, link_name, NAME_FIELD_SIZE); - - /* Force null termination. */ - header->header.linkname[NAME_FIELD_SIZE - 1] = 0; + tar_copy_str (header->header.linkname, link_name, + NAME_FIELD_SIZE); header->header.typeflag = LNKTYPE; finish_header (header, block_ordinal); @@ -1487,8 +1480,8 @@ dump_file (char *p, int top_level, dev_t parent_device) sizeleft = current_stat_info.stat.st_size; - /* Don't bother opening empty, world readable files. Also do not open - files when archive is meant for /dev/null. */ + /* Don't bother opening empty, world readable files. Also do not + open files when archive is meant for /dev/null. */ if (dev_null_output || (sizeleft == 0 @@ -1528,8 +1521,7 @@ dump_file (char *p, int top_level, dev_t parent_device) isextended = header->oldgnu_header.isextended; else isextended = 0; - if (isextended) - abort(); + save_typeflag = header->header.typeflag; finish_header (header, block_ordinal); if (isextended) @@ -1699,7 +1691,7 @@ dump_file (char *p, int top_level, dev_t parent_device) } buffer[size] = '\0'; assign_string (¤t_stat_info.link_name, buffer); - if (size >= NAME_FIELD_SIZE) + if (size > NAME_FIELD_SIZE) write_long_link (¤t_stat_info); block_ordinal = current_block_ordinal (); @@ -1707,8 +1699,7 @@ dump_file (char *p, int top_level, dev_t parent_device) header = start_header (p, ¤t_stat_info); if (!header) return; - strncpy (header->header.linkname, buffer, NAME_FIELD_SIZE); - header->header.linkname[NAME_FIELD_SIZE - 1] = '\0'; + tar_copy_str (header->header.linkname, buffer, NAME_FIELD_SIZE); header->header.typeflag = SYMTYPE; finish_header (header, block_ordinal); /* nothing more to do to it */ @@ -1753,8 +1744,10 @@ dump_file (char *p, int top_level, dev_t parent_device) if (type != FIFOTYPE) { - MAJOR_TO_CHARS (major (current_stat_info.stat.st_rdev), header->header.devmajor); - MINOR_TO_CHARS (minor (current_stat_info.stat.st_rdev), header->header.devminor); + MAJOR_TO_CHARS (major (current_stat_info.stat.st_rdev), + header->header.devmajor); + MINOR_TO_CHARS (minor (current_stat_info.stat.st_rdev), + header->header.devminor); } finish_header (header, block_ordinal);