files.extract_tar¶
files.extract_tar unpacks a gzip tar archive into a directory. It deletes the old content of that directory first, and it deletes the archive.
A failed request can leave the directory empty or partly filled. The section After a failure says what stays.
Request¶
| Parameter | Required | Meaning |
|---|---|---|
archivePath |
yes | The gzip tar archive. The daemon makes no test of this path. After it opened the file, it deletes it. That applies to a file that is not an archive too. |
destDir |
yes | The directory to fill. The daemon deletes what is there. It must be an absolute path. It cannot be a file system root, the home directory, or a directory that holds the home directory. A directory under the home directory is accepted. The home test compares the paths as text and does not resolve symbolic links: see D2. |
Path handling has the rules for a leading ~ in both parameters.
What the request does¶
The daemon does these steps in this order:
- It opens the archive and reads the gzip header.
- It prepares
destDir:- It creates the directories above
destDirthat do not exist, with mode0700. - It opens the directory that holds
destDir. - It deletes
destDirwith all its content. IfdestDiris a file or a symbolic link, the daemon deletes that file or link. It does not delete the target of a link, atdestDiror inside it. - It creates
destDiragain as a new empty directory with mode0700. - It opens
destDir.
- It creates the directories above
- It writes each entry of the archive into
destDir. - It deletes what the archive put at
.syncedat the top ofdestDir. Then it writes an empty file.syncedthere. - It deletes the archive. It does that after a failure too, once the archive was open.
The rules for the entries:
- The daemon writes regular files and directories only. Each other kind of entry fails the request, for example a symbolic link, a hard link or a device.
- A directory gets the mode
0700. A file gets0700if its mode in the archive has the execute bit of the owner, and0600if it does not. No other mode bit of the archive applies, so no setuid, setgid or sticky bit arrives. On Linux and macOS the umask of the daemon applies to these modes. - A second file entry with the name of an earlier one replaces that file. The new file has the mode of the last entry (Linux and macOS). On a volume that ignores letter case it has the name of the last entry too (Windows and macOS).
fileCountcounts each entry. - An entry cannot leave
destDir. A name that leavesdestDirat a step fails the request, also when it comes back.../eviland../dest/x.txtare examples. A..that stays inside is accepted, for examplea/../b.txt. A name that starts with/lands insidedestDir. - The marker replaces what the archive put at
.syncedat the top. A file entry with that name ends empty with mode0600. A directory entry with that name goes with all its content.fileCountstill counts the files of the archive there. A.syncedbelow another directory is a normal entry.
Response¶
Success:
fileCount is the number of regular files that the daemon wrote. It does not count directories, and it does not count the marker that the daemon writes.
Failure:
Read success. A failure has no errorCode member, so the error text is the one description of the cause. A failure answers fileCount 0, also after the daemon wrote files, with one exception. The exception is the marker step: the daemon cannot remove the entry at .synced, or it cannot write the marker file. The answer then holds the number of files written before. No measurement of the reference covers that case.
error starts with |
Cause |
|---|---|
destDir must be an absolute, non-root path: |
destDir is relative, or it is a file system root. |
destDir must not be or contain the home directory: |
destDir is the home directory, or a directory that holds it. The daemon tests the text of the path first. Later it tests the directory at the last name of destDir by identity. |
open archive: |
The daemon cannot open the archive. For example, it does not exist. |
gzip: |
The daemon cannot read a gzip header. |
tar read: |
The daemon cannot read the next entry. Gzip data that is not a tar archive gives this text at the first entry. Gzip data with no content is an archive with no entries: the request succeeds with fileCount 0, and destDir is then empty but for the marker. |
open parent: |
The daemon cannot open the directory that holds destDir, or cannot search it. The text is open parent: open <path of that directory>: <reason>. |
clean destDir: |
The daemon cannot delete the old destDir, or an entry in it. The text is clean destDir: RemoveAll <name>: <reason>. |
mkdir parent: mkdir <path>: |
The daemon cannot create a directory above destDir. <path> is the whole path of that directory. This text has no entry name: mkdir parent <entry>: below is another failure. |
mkdir destDir: |
The daemon cannot create destDir. The text is mkdir destDir: mkdirat <name>: <reason>. |
clean destDir: "<name>" is not the entry that the path names, and the same after mkdir destDir: |
The path of destDir and its last name inside the parent directory do not name one entry. The daemon deletes nothing then. On Windows a path with the \\?\ prefix and a dot or a space after its last name gives this text. 89cb6289 extracts into a folder with the exact name there, and 5fd08069 into the folder with no dot or space. |
open destDir: |
The daemon cannot open the new destDir, or cannot search it. A daemon umask of 0400 gives open destDir: openat <name>: permission denied on Linux and macOS. On Linux and macOS a daemon umask of 0100 gives open destDir: "<name>" could not be examined (statat .: permission denied). <name> is the last part of destDir. If another process replaced destDir after the daemon created it, the text is open destDir: "<name>" changed while it was opened, or open destDir: openat <name>: path escapes from parent. |
unsafe path in archive: <entry> |
The name of the entry leaves destDir. On Windows a device name such as NUL and a name with : give this text too. |
unsupported tar entry type <c>: <entry> |
The entry is not a regular file or a directory. <c> is the type character of tar, for example 2 for a symbolic link and 1 for a hard link. |
mkdir parent <entry>: |
The daemon cannot create the directory for a file. A file entry a and then an entry a/b give mkdir parent a/b: mkdirat a: file exists. |
mkdir <entry>: |
The daemon cannot create the directory of a directory entry. A file entry a and then a directory entry a/ give mkdir a/: mkdirat a: file exists. |
create <entry>: |
The daemon cannot create the file. A directory entry d and then a file entry d give create d: openat d: file exists on Linux and macOS, and create d: openat d: is a directory on Windows. |
write <entry>: |
The daemon cannot copy the content of a file. For example, the archive is cut inside the file, or its compressed data is damaged. |
extraction size limit exceeded |
Only with -max-extract-bytes: the files written are larger than the limit. |
write .synced: |
The daemon cannot remove the entry at .synced, or it cannot write the marker file. |
<entry> is the name of the entry as the archive has it, not the path on disk. unsafe path in archive: and unsupported tar entry type end with that name. The two destDir must texts end with the path in quotes. The text after each other prefix comes from the operating system or from a library. The examples are those of Linux and macOS. After mkdir parent <entry>:, mkdir <entry>: and create <entry>: that text names the place below destDir, not the whole path.
The method has two JSON-RPC errors:
| Code | Text | Cause |
|---|---|---|
-32602 |
Invalid params |
The request has no params member, or params or a member of it has the wrong type. See the rules for params. |
-32602 |
archivePath and destDir are required |
One of the two is absent or empty. |
After a failure¶
No failure restores the old content of destDir. The table says what stays of the archive and of destDir.
| Failure | The archive | destDir |
|---|---|---|
A JSON-RPC error, or a refusal of destDir (destDir must ...) |
Stays. | Not changed. |
| The home refusal from the test by identity | Deleted. | Not changed. |
open archive: |
Not changed. | Not changed. |
gzip: |
Deleted. | Not changed. |
open parent: |
Deleted. | Not changed. Directories above destDir that did not exist can be new. |
clean destDir: |
Deleted. | The old destDir stays. The entries that the daemon was able to delete are gone. With the text is not the entry that the path names, nothing is deleted. |
mkdir parent: mkdir <path>: |
Deleted. | Not changed in the measured rows. |
mkdir destDir: |
Deleted. | The old content is deleted, and there is no destDir. |
open destDir: |
Deleted. | The old content is deleted. destDir is empty. |
| Each later failure | Deleted. | The old content is deleted. The entries written before the failure stay. A file that the daemon wrote in part can stay too. The daemon writes no marker. |
Do not read a .synced file as the result of the last request. After open archive: and after gzip:, an old marker stays with the old content. An archive can also hold an entry with that name, and that entry stays after a later failure.
The daemon ignores a failure of the delete of the archive. So an archive that it cannot delete stays. If archivePath is an empty directory, the daemon on Linux deletes that directory and answers gzip:. The home test does not apply to archivePath. So if archivePath is the home directory and that directory is empty, the daemon deletes it.
With -max-extract-bytes, the daemon deletes the file that went over the limit. The files written before it stay.
The size limit¶
By default there is no limit on the size of the extracted files. An operator can set one. Start the daemon with the flag -max-extract-bytes <n>, or set the key max-extract-bytes in claustrum.conf. The limit is on the sum of the file contents. See D3.
Differences by system¶
| Linux and macOS | Windows | |
|---|---|---|
| A file system root | / |
A drive root such as C:\, or the root of a share such as \\server\share\. |
The modes 0600 and 0700 |
Applied, less the umask. | They do not limit access to the owner. |
An absolute destDir |
Starts with /. |
Has a drive or a share. \dir and C:dir are relative. |
\ in the name of an entry |
A character of the name. | A separator. |
| The home test | Letter case counts. | Letter case does not count. |
Differences from the reference¶
claustrum is built to answer as the reference daemon does. These entries of the divergence catalog apply to this method:
- D2: claustrum refuses a
destDirthat is the home directory or holds it. The reference deletes the home directory for"destDir": "~". - D3: the optional size limit. It is off by default.
The reference pin is 89cb6289. This method follows 5fd08069. The examples in the table of the error texts are from 5fd08069 too.
The test for a replaced destDir is claustrum's own, and it is part of D2. No measurement says what the reference does there. The test of the two views of destDir before the delete is claustrum's own too, and it is part of D2. Both reference builds extract there (Windows VM).
The refusal of a file system root is not in the catalog. claustrum refuses a root because step 2 deletes destDir with all its content. No measurement says what the reference does with a root, so the refusal is neither parity nor a divergence.