This might lead to false positive if the tar file is written to another device.

$ ~/.sbase/bin/tar cf /mnt/backup/test.tar .config
ignoring '.config/zathura/zathurarc'

$ find .config/zathura/zathurarc /mnt/backup/test.tar -printf "%i %D %p\n"
1259 2050 .config/zathura/zathurarc
1259 2081 /mnt/backup/test.tar

Attached diff also checks st_dev, which ought to cover all cases.

Regards,
Lars.

On 20/07-13, Roberto E. Vargas Caballero wrote:
> This patch fixes this issue using the inode number of the tar
> file.
> 
> 
> 
> -- 
> Roberto E. Vargas Caballero
> ----------------------------
> k...@shike2.com
> http://www.shike2.com

> From e5b989e7899c87f316597e6b8ed39adfa97959b2 Mon Sep 17 00:00:00 2001
> From: "Roberto E. Vargas Caballero" <k...@shike2.com>
> Date: Sat, 20 Jul 2013 18:08:58 +0200
> Subject: [PATCH] Avoid infinite loop in tar
> 
> When the tar file is written in one directory archived by tar
> the function archive enters in an infinite loop due to de
> tar file written. This patch avoid this case checking the
> inode of the tar file before of adding it to the archive.
> ---
>  tar.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/tar.c b/tar.c
> index 87b7236..0f3ce33 100644
> --- a/tar.c
> +++ b/tar.c
> @@ -47,6 +47,7 @@ static void c(char *);
>  static void xt(int (*)(char*, int, char[Blksiz]));
>  
>  static FILE *tarfile;
> +static ino_t tarinode;
>  
>  static void
>  usage(void)
> @@ -117,9 +118,14 @@ main(int argc, char *argv[])
>               usage();
>  
>       if(file) {
> +             struct stat st;
> +
>               tarfile = fopen(file, (mode == 'c') ? "wb" : "rb");
>               if(!tarfile)
>                       eprintf("tar: open '%s':", file);
> +             if (lstat(file, &st) < 0)
> +                     eprintf("tar: stat '%s':", file);
> +             tarinode = st.st_ino;
>       } else {
>               tarfile = (mode == 'c') ? stdout : stdin;
>       }
> @@ -155,6 +161,10 @@ archive(const char* path, const struct stat* sta, int 
> type)
>       mode_t mode;
>  
>       lstat(path, &st);
> +     if (st.st_ino == tarinode) {
> +             fprintf(stderr, "ignoring '%s'\n", path);
> +             return 0;
> +     }
>       pw = getpwuid(st.st_uid);
>       gr = getgrgid(st.st_gid);
>  
> -- 
> 1.8.3.2
> 

--- tar-orig.c  2013-07-22 00:29:33.078595937 +0200
+++ tar.c       2013-07-22 00:30:41.786328335 +0200
@@ -48,6 +48,7 @@
 
 static FILE *tarfile;
 static ino_t tarinode;
+static dev_t tardev;
 
 static void
 usage(void)
@@ -126,6 +127,7 @@
                if (lstat(file, &st) < 0)
                        eprintf("tar: stat '%s':", file);
                tarinode = st.st_ino;
+               tardev = st.st_dev;
        } else {
                tarfile = (mode == 'c') ? stdout : stdin;
        }
@@ -161,7 +163,7 @@
        mode_t mode;
 
        lstat(path, &st);
-       if (st.st_ino == tarinode) {
+       if (st.st_ino == tarinode && st.st_dev == tardev) {
                fprintf(stderr, "ignoring '%s'\n", path);
                return 0;
        }

Reply via email to