Pārlūkot izejas kodu

libdpkg: Add tar format detection support

Recognize old tar, GNU tar and ustar formats. Abort on ustar with non
empty Prefix field, as we don't properly handle the long names yet.
Failure for PAX archive is already being handled when acting on the
typeflag.
Guillem Jover 17 gadi atpakaļ
vecāks
revīzija
22408d0c3d
4 mainītis faili ar 33 papildinājumiem un 1 dzēšanām
  1. 9 0
      ChangeLog
  2. 1 0
      debian/changelog
  3. 15 1
      lib/tarfn.c
  4. 8 0
      lib/tarfn.h

+ 9 - 0
ChangeLog

@@ -1,3 +1,12 @@
+2009-02-27  Guillem Jover  <guillem@debian.org>
+
+	* lib/tarfn.h (enum tar_format): New type.
+	(struct TarInfo): Add new format member.
+	* lib/tarfn.c (TAR_MAGIC_USTAR, TAR_MAGIC_GNU): New macros.
+	(struct TarHeader): Add new Prefix member.
+	(DecodeTarHeader): Detect tar formats based on the magic values.
+	Abort on tar_format_ustar and an non-empty Prefix.
+
 2009-02-27  Guillem Jover  <guillem@debian.org>
 
 	* lib/fields.c (f_boolean): Use PKGPFIELD to assign to the correct

+ 1 - 0
debian/changelog

@@ -61,6 +61,7 @@ dpkg (1.15.0) UNRELEASED; urgency=low
   * Add new option --iosched to start-stop-daemon to be able to set the
     IO scheduling class and priority. Closes: #443535
     Thanks to Chris Coulson <chrisccoulson@googlemail.com>.
+  * Add tar format detection support to the internal extractor.
 
   [ Raphael Hertzog ]
   * Enhance dpkg-shlibdeps's error message when a library can't be found to

+ 15 - 1
lib/tarfn.c

@@ -18,6 +18,9 @@
 #include <dpkg.h>
 #include <dpkg-priv.h>
 
+#define TAR_MAGIC_USTAR "ustar\0" "00"
+#define TAR_MAGIC_GNU   "ustar "  " \0"
+
 struct TarHeader {
 	char Name[100];
 	char Mode[8];
@@ -33,6 +36,7 @@ struct TarHeader {
 	char GroupName[32];
 	char MajorDevice[8];
 	char MinorDevice[8];
+	char Prefix[155];	/* Only valid on ustar. */
 };
 typedef struct TarHeader	TarHeader;
 
@@ -81,12 +85,22 @@ DecodeTarHeader(char * block, TarInfo * d)
 	long			sum;
 	long			checksum;
 
+	if (memcmp(h->MagicNumber, TAR_MAGIC_GNU, 6) == 0)
+		d->format = tar_format_gnu;
+	else if (memcmp(h->MagicNumber, TAR_MAGIC_USTAR, 6) == 0)
+		d->format = tar_format_ustar;
+	else
+		d->format = tar_format_old;
+
 	if ( *h->UserName )
 		passwd = getpwnam(h->UserName);
 	if ( *h->GroupName )
 		group = getgrnam(h->GroupName);
 
-	d->Name = StoC(h->Name, sizeof(h->Name));
+	if (d->format == tar_format_ustar && h->Prefix[0] != '\0')
+		abort();
+	else
+		d->Name = StoC(h->Name, sizeof(h->Name));
 	d->LinkName = StoC(h->LinkName, sizeof(h->LinkName));
 	d->Mode = (mode_t)OtoL(h->Mode, sizeof(h->Mode));
 	d->Size = (size_t)OtoL(h->Size, sizeof(h->Size));

+ 8 - 0
lib/tarfn.h

@@ -12,6 +12,13 @@
 #include <unistd.h>
 #include <sys/types.h>
 
+enum tar_format {
+	tar_format_old,
+	tar_format_gnu,
+	tar_format_ustar,
+	tar_format_pax,
+};
+
 enum TarFileType {
 	NormalFile0 = '\0',	/* For compatibility with decades-old bug */
 	NormalFile1 = '0',
@@ -27,6 +34,7 @@ enum TarFileType {
 typedef enum TarFileType	TarFileType;
 
 struct	TarInfo {
+	enum tar_format	format;		/* Tar archive format. */
 	void *		UserData;	/* User passed this in as argument */
 	char *		Name;		/* File name */
 	mode_t		Mode;		/* Unix mode, including device bits. */