Erlang Thursday – erl_tar:create/2

Today’s Erlang Thursday is on erl_tar:create/2.

erl_tar:create/2 creates a tar file with a given filename and adds the given list of filenames to the archive.

erl_tar:create/2 takes two arguments, the first is a filename to write to, and the second argument is a list of filenames to add to the tar file.

First, we will open up a new OS shell session and create some files to add to a new tar file.

$ echo "foo" > foo.txt
$ echo "bar" > bar.txt
$ echo "baz" > baz.txt
$ ls
bar.txt  baz.txt  foo.txt  test.tar

Now that we have some files to archive, we can open up a new erl session, and create a new tar file named test.tar.

erl_tar:create("test.tar", ["foo.txt", "bar.txt", "baz.txt"]).
% ok

That looks like it worked; so let’s go to a OS shell, and inspect the resulting file for the filename we gave to erl_tar:create/3.

$ tar -tf test.tar
foo.txt
bar.txt
baz.txt

And yes, tar can read that file and tells us that the three files we added are indeed part of the tar file.

erl_tar:create/3

Erlang also provides erl_tar:create/3 that takes a options list as it’s last argument.

We will create a new file, with the same contents, and pass in that we want this tar file to be compressed, and to be verbose with what it is doing as well.

erl_tar:create("options.tar.gz", 
               ["foo.txt", "bar.txt", "baz.txt"],
               [compressed, verbose]).
% a foo.txt
% a bar.txt
% a baz.txt
% ok

Again, let’s switch back to our OS shell, and inspect the resulting file.

$ tar -tf options.tar.gz
foo.txt
bar.txt
baz.txt

And let’s test it to see if it was considered compressed by gzip.

$ gzip --test options.tar.gz
$

And there we go, gzip considers this a compressed file with integrity. So let’s take a look at the size difference between the two tar files we created.

$ ls -l test.tar options.tar.gz
-rw-r--r--  1 -------  -----    154 Sep XX HH:MM options.tar.gz
-rw-r--r--  1 -------  -----  10240 Sep XX HH:MM test.tar

And looking at the filesize we can see that it is definately compressed, as options.tar.gz is two orders of magnitude smaller than test.tar.

Creating a file that already exists

As we just created test.tar and saw it had the contents, let’s see what happens when we call create on a file that already exists, by passing the same filename with a empty list of files.

erl_tar:create("test.tar", []).
% ok

And we take a look at the contents, we can see the original tar has been replaced.

$ tar -tf test.tar
$

This tells us that erl_tar:create/2 will create a tar file and overwrite the existing file, and doesn’t error out if the file already exists (assuming the user the shell is running has access to write to that file/directory).

Creating a tar for a path that doesn’t exist

If we give a bad path for a file, we can see that erl_tar:create/2 will return a error tuple, with the filename and reason for the failure.

erl_tar:create('/path/does/not/exist.tar', []).
% {error,{'/path/does/not/exist.tar',enoent}}

Other Potential Gotchas

First, the documentation states that it takes filename()s as arguments, but the documentation page for erl_tar does not specify on that page what a filename data type is.

If you use atom()s for the filename, you are going to get an error like the one below that I was getting at first, before using string()s for the filenames.

erl_tar:create('test.tar', ['foo.txt', 'bar.txt', 'baz.txt']).
** exception error: no function clause matching filename:join([]) (filename.erl, line 392)
     in function  erl_tar:split_filename/4 (erl_tar.erl, line 423)
     in call from erl_tar:create_header/3 (erl_tar.erl, line 352)
     in call from erl_tar:add1/4 (erl_tar.erl, line 305)
     in call from erl_tar:foreach_while_ok/2 (erl_tar.erl, line 940)
     in call from erl_tar:create/3 (erl_tar.erl, line 114)

Second, according to the Limitations section of the erl_tar documentation page, filenames should be less than 100 characters for maximum compatability across different systems and version of the tar program.

Lastly, it is on us the user to include the file extension when specifing the filename, as erl_tar:compress/2 does not manage the extension for us.

–Proctor