Parcourir la source

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 il y a 17 ans
Parent
commit
22408d0c3d
4 fichiers modifiés avec 33 ajouts et 1 suppressions
  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. */