2

I am trying to use GNU tar to create a tarball from a directory stored on a network drive. This network drive defaults the mode of everything stored on it to 0700 (-rwx------) and cannot be changed prior to the tarball creation.

I had used this command to change the permissions of my files stored inside the tarball:

tar -c --mode=0644 -f project.tar ./project/

The issue is that everything in the tarball has its permissions changed to 0644 (-rw-r--r--). There are no executables in this ./project/ directory, so 0644 for all files is okay, but directories end up inheriting 0644 as well. Upon extraction on another system, directories cannot be entered until the execute bit is added.

Is it possible to instruct GNU tar to change the modes of all files to 0644 and change the modes of all directories to 0755? Almost like -type f and -type d in the find command.

OS is version Debian 11 Bullseye, GNU tar is version 1.34.

1
  • 1
    In past, for distribution of packages, we copied all sources in a new directory, we set up the permissions (ev. updating times, manifests, versions), and we did a tarball from there. You have more flexibility (e.g. if you have scripts which should have executable bit, etc.) Aug 31, 2023 at 8:37

3 Answers 3

3

With GNU tar, you can do:

tar --mode a=r,u+w,a+X -cf file.tar directory

Which would get you rwxr-xr-x for files of type directory, and rw-r--r-- for every other type (including symlinks, even to directories). That's built as:

  • a=r: resets permissions to r--r--r--
  • u+w: adds w to user, so rw-r--r--
  • a+X: adds x to all, but only on files of type directory so rwxr-xr-x for directories and rw-r--r-- for any other type of file.

To get full flexibility, you can use star:

star cf file.tar -find directory \
     -type d -chmod 755 \
  -o -type l -chmod 777 \
  -o         -chmod 644

Where we get rwxr-xr-x for files of type directory, rwxrwxrwx for files of type symlink, and rw-r--r-- for any other type of file.

Or using the symbolic forms:

star cf file.tar -find directory \
     -type d -chmod a=rx,u+w \
  -o -type l -chmod a=rwx \
  -o         -chmod a=r,u+w
3
  • Does permissions for sym-link matter. My system sets all symlinks to 777. Aug 31, 2023 at 18:16
  • @ctrl-alt-delor, it matters on some such as macos, on most others it doesn't matter and on many, you can't even change it to anything other than rwxrwxrwx Aug 31, 2023 at 18:45
  • Do you know why. I think it changed, as I remember seeing other modes. I am wondering if it was because the mode was useless, AND we needed the bits to specify other file types. Sep 3, 2023 at 16:07
3

You can use relative permissions like with chmod, not just a fixed mode with --mode. Check the manual, not just the man page.

You can use use a+r to grant everyone read permission and a+X to grant execution permission if it was present anywhere.

tar -c --mode=a+rX …

However, if the filesystem makes all files executable, that will result in having all files executable in the archive. I don't think there's a way to adjust files differently with GNU tar. (Actually, no there is: +X also makes directories executable if they're readable, so a=r,u+w,a+X works.)

Pax doesn't have any way to adjust permissions at all.

I think the simplest approach is to use bindfs to create a view of the filesystem with different metadata. This is a FUSE filesystem, so it can be installed and used without administrator privileges as long as your system has FUSE itself installed. Bindfs offers more flexibility than GNU tar's --mode. Another benefit is that it can used with programs that don't have something similar to tar --mode. You can use the --perms option to change permissions:

mkdir -p views/project
bindfs --no-allow-other -p a+rD project views/project
tar -C views -cf project.tar project
fusermount -u views/project
rmdir views/project

Python has a tarfile module which makes it relatively convenient to write code. I think it supports iterative archiving so you wouldn't need to store the whole archive in memory at once. But you'd still have to write quite a bit of code.

8
  • 1
    oh bindfs is a good idea! I'm still a bit confused that nobody wrote a "edit these fixed fields in tar file headers" tool that I'm aware of. Aug 31, 2023 at 8:52
  • 1
    @leetbacoon note that Gilles' approach wasn't primarily the bindfs approach, but simply adding file by file with its individual permissions set correctly! Aug 31, 2023 at 14:03
  • 1
    for example, (assuming this won't be so many files it exceeds your command line maximum), tar -cf archive.tar --no-recursion --mode 0755 **/* in zsh would first store all directories (in bottom-up order), then tar -rf archive.tar --mode 0644 **/*(^/Odon) would append all files. Aug 31, 2023 at 14:13
  • 1
    @leetbacoon My bad, I hadn't noticed that you do need to treat regular files differently from directories. Then bindfs is my recommended solution. Aug 31, 2023 at 17:29
  • 1
    remove x before adding X. to get x only on directories. Aug 31, 2023 at 18:21
1

You could work around tar's inability to change attributes according to rules by – not using tar.

mksquashfs has a mini-language for actions built in, which can applied to archive entries as they come along, according to some filtering rules; the whole thing is documented here. It's quite simple: the syntax is action@condition, so for us:

mksquashfs ./project/ project.squashfs -no-strip -action 'chmod(0755)@type(d)' -action 'chmod(644)@type(f)' 

will make all directory entries have 0755 permissions, and all files have 0644 permisions. You might have fifos, sockets, symlinks in your folder, so maybe instead of "directories" and "files", the better categorization would be "directories" and "everything not a directory"; then, throw in some compression that's probably faster than your network is, for free:

mksquashfs ./project/ project.squashfs \
          -no-strip \
          -action 'chmod(0755)@type(d)' \
          -action 'chmod(644)@!type(d)' \
          -comp zstd -Xcompression-level 10

Usage of this archive:

  1. can be extracted using unsquashfs project.squashfs (and probably your favorite graphical archive manager, as well)
  2. (on Linux) can be mounted readonly (as root) using mount -o loop gr-ieee802-11.squash /home/marcus/mnt/
  3. (on Linux) can be mounted readonly by any user using a modern desktop environment: udisksctl loop-setup -f project.squashfs (and if that doesn't automount, udisksctl mount -b or clicking on the newly appeared drive in your file manager.
2
  • This sounds very interesting & could be great for future/personal archives, but in my particular case, POSIX-compliant tarballs are necessary due to them being simple, time-proven and, well, POSIX compliant (my tar command really uses --posix, btw, but this option was omitted from my Q for brevity). I'm not discrediting squashfs in any way; I see it in Linux distros a lot and it seems nice. From my research it doesn't appear POSIX-compliant which is unfortunately a dealbreaker (please tell me if I'm wrong). Thank you for your answer, I'm sure to use it in the future! :)
    – leetbacoon
    Aug 31, 2023 at 13:55
  • 1
    @leetbacoon no need to be so sorry about it :) I can understand that if the requirement is "make a POSIX tar", then you need a POSIX tar :) (you could convert a squashfs archive through sqfs2tar to a tar, or by just mounting it and tar'ing the directory, but that's quite a convoluted approach :). (tar being time-proven, hm yes, but how many million devices boot from a tar file rather than a squashfs root image? I'd argue the format "tar" isn't really good, it just is there.) Aug 31, 2023 at 14:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .