TheChymera / mkstage4

Bash Utility for Creating Stage 4 Tarballs
GNU General Public License v3.0
104 stars 22 forks source link

Exclude stage4 filename doesn't work #3

Closed dave-kennedy closed 8 years ago

dave-kennedy commented 8 years ago

This part doesn't work so well if the target is / and the filename starts with / too:

 93 if [ "$TARGET" == "/" ]                                                          
 94 then                                                                             
 95   EXCLUDES+=" --exclude=$STAGE4_FILENAME"                                        
 96 fi

For example, I usually back up to a drive at /mnt/backup, so I run the script like this:

# ./mkstage4.sh -s /mnt/backup/2016-01-26

The full command then is:

cd / && tar -cjpP --ignore-failed-read -f /mnt/backup/2016-01-26.tar.bz2 * --exclude=proc/* --exclude=sys/* --exclude=tmp/* --exclude=mnt/*/* --exclude=var/lock/* --exclude=var/log/* --exclude=var/run/* --exclude=.bash_history --exclude=lost+found --exclude=usr/portage/* --exclude=/mnt/backup/2016-01-26.tar.bz2

In this case, the filename will be ignored because of --exclude=mnt/*/*. But if you take out --exclude=mnt/*/* you'll start getting errors like this:

/mnt/backup/2016-01-26.tar.bz2: file changed as we read it

I think the reason is because of the leading /. tar apparently doesn't understand that filename is the same as /filename when run from the root directory.

TheChymera commented 8 years ago

I don't think I understand what the issue is with

cd / && tar -cjpP --ignore-failed-read -f /mnt/backup/2016-01-26.tar.bz2 * --exclude=proc/* --exclude=sys/* --exclude=tmp/* --exclude=mnt/*/* --exclude=var/lock/* --exclude=var/log/* --exclude=var/run/* --exclude=.bash_history --exclude=lost+found --exclude=usr/portage/* --exclude=/mnt/backup/2016-01-26.tar.bz2

Could you explain again what is not working with this use case?

dave-kennedy commented 8 years ago

Actually, what happened was I messed up this line:

 85 --exclude=mnt/*/* \

tar was told to exclude the pattern /mnt/backup/2016-01-26.tar.bz2 but the filename was mnt/backup/2016-01-26.tar.bz2. The leading / in the pattern was not matched by the actual filename, so it attempted to copy the archive to itself and would have eventually filled my drive.

I can submit a pull request if it helps clarify.

TheChymera commented 8 years ago

If you already have a plan how to solve this, sure! I am thinking perhaps we can include another line like

--exclude=/mnt/*/* \
dave-kennedy commented 8 years ago

That wouldn't work either. Let me give you an example. Assume the only thing in / is mnt/ with the following structure:

mnt/
    backup/
        old-archive.tar

When you run cd / && tar -c -f archive.tar * it will create an archive with the following file paths:

mnt/
mnt/backup/
mnt/backup/old-archive.tar

The --exclude option matches a pattern against a file path, so --exclude mnt/ will exclude the folder and everything in it. --exclude mnt/* will include the folder and exclude everything in it. But --exclude /mnt/ won't match any file path due to the leading /, so it won't exclude anything, nor will --exclude /mnt/*.

TheChymera commented 8 years ago

--exclude mnt/* will include the folder and exclude everything in it.

Would then not -exclude=mnt/*/* include your mnt folder and all your mount points, but exclude any of the actual files - exactly what you wanted. No?

dave-kennedy commented 8 years ago

Yes. My point is that this does nothing:

 93 if [ "$TARGET" == "/" ]                                                          
 94 then                                                                             
 95   EXCLUDES+=" --exclude=$STAGE4_FILENAME"                                        
 96 fi

unless the leading / is removed.

Of course if $STAGE4_FILENAME is under a directory that is excluded it doesn't matter.

TheChymera commented 8 years ago

Ah, I got it, ok, feel free to correct that bit of code, and thank you.