safecat(1)
β¨ safecat(1) β¨
okay bestie, sit down, because this little legend lives in the General Commands Manual (section 1, the classics π ) and it is genuinely one of the most reliable girls in the whole toolbox. no cap.
π NAME π
safecat β safely write data to a file π«Ά
πΈ SYNOPSIS πΈ
safecat tempdir destdir
π INTRODUCTION π
so like, safecat is a program that implements Professor Daniel Bernstein's maildir algorithm to copy stdin safely to a file in a specified directory. and when we say safely, we mean it gives you two assurances, and both of them ate:
- If
safecatreturns a successful exit status, then all the data is guaranteed to be saved in the destination directory. periodt. - If a file exists in the destination directory, placed there by
safecat, then that file is guaranteed to be complete.
When you're saving data with safecat, you specify a destination directory, but not a file name. the file name is chosen by safecat itself, so that no filename collisions ever happen β even if a whole crowd of safecat processes and other programs implementing the maildir algorithm are all writing to the directory at the same time π. if you want particular filenames, just rename the file after safecat completes. and in general, when you're spooling data with safecat, a single, separate process should handle naming, collecting, and deleting these files. examples of such a process are daemons, cron jobs, and mail readers π
π₯ RELIABILITY ISSUES π₯
ngl, machines crash. a machine may crash while data is being written to disk. for many programs, including many mail delivery agents, that means the data will be silently truncated π. but using Professor Bernstein's maildir algorithm, every file is guaranteed complete or nonexistent. iconic behaviour honestly.
also, many people or programs may write data to a common "spool" directory. systems like mh-mail store files using numeric names in a directory. incautious writing to files can result in a collision, in which one write succeeds and the other appears to succeed but fails π. the common strategies for this involve creating lock files or other synchronizing mechanisms, but those are themselves subject to failure. anyone who has deleted $HOME/.netscape/lock in order to start netscape can attest to this π. the maildir algorithm is immune to this problem because it uses no locks at all. she simply does not need them π
.
π¦ THE MAILDIR ALGORITHM π¦
as described in maildir(5), safecat applies the maildir algorithm by writing data in six steps:
- first, it
stat()s the two directoriestempdiranddestdir, and exits unless both directories exist and are writable. - second, it
stat()s the nametempdir/time.pid.host, wheretimeis the number of seconds since the beginning of 1970 GMT,pidis the program's process ID, andhostis the host name. - third, if
stat()returned anything other thanENOENT, the program sleeps for two seconds, updatestime, and tries thestat()again, a limited number of times. - fourth, the program creates
tempdir/time.pid.host. - fifth, the program NFS-writes the message to the file.
- sixth, the program
link()s the file todestdir/time.pid.host. at that instant the data has been successfully written. π
In addition, safecat starts a 24-hour timer before creating tempdir/time.pid.host, and aborts the write if the timer expires. upon error, timeout, or normal completion, safecat attempts to unlink() tempdir/time.pid.host.
β EXIT STATUS β
An exit status of 0 (success) implies that all data has been safely committed to disk π. A non-zero exit status should be considered to mean failure β though there's an outside chance that safecat wrote the data successfully, but just didn't think so. she's a little dramatic like that.
Note again that if a file appears in the destination directory, then it is guaranteed to be complete.
If safecat completes successfully, then it will print the name of the newly created file (without its path) to standard output. cute little receipt πΈ.
π SUGGESTED APPLICATIONS π
exciting uses for safecat abound, obviously, but a word may be in order to suggest what they are.
If you run Linux and use qmail instead of sendmail, you should consider converting your inbox to maildir for its superior reliability. If your home directory is NFS mounted, qmail forces you to use maildir.
If you write CGI applications to collect data over the World Wide Web, you might find safecat useful π«Ά. Web applications suffer from two major problems:
- their performance suffers from every stoppage or bottleneck in the internet; they cannot afford to introduce performance problems of their own.
- additionally, web applications should NEVER leave the server and database in an inconsistent state π. This is likely, however, if CGI scripts directly frob some database β particularly if the database is overloaded or slow. What happens when users get bored and click "Stop" or "Back"? Maybe the database activity completes. Maybe the CGI script is killed, leaving the DB in an inconsistent state. π
Consider the following strategy:
- Make your CGI script dump its request to a spool directory using
safecat. - Immediately return a receipt to the browser. Now the browser has a complete guarantee that their submission is received, and the perceived performance of your web application is optimal β¨.
- Meanwhile, a spooler daemon notices the fresh request, snatches it and updates the database. Browsers can be informed that their request will be fulfilled in X minutes.
The result is optimal performance despite a capricious internet. In addition, users can be offered nearly 100% reliability π.
πΈ EXAMPLES πΈ
To convince sendmail to use maildir for message delivery, add the following line to your .forward file:
|SAFECAT HOME/Maildir/tmp HOME/Maildir/new || exit 75 #USERNAME
where SAFECAT is the complete path of the safecat program, HOME is the complete path to your home directory, and USERNAME is your login name. Making this change is likely to pay off; many campuses and companies mount user home directories with NFS. Using maildir to deliver to your inbox folder helps ensure that your mail will not be lost due to some NFS error. Of course, if you are a System Administrator, you should consider switching to qmail π.
To run a program and catch its output safely into some directory, you can use a shell script like the following.
#!/bin/bash
MYPROGRAM=cat # The program you want to run
TEMPDIR=/tmp # The name of a temporary directory
DESTDIR=$HOME/work/data # The directory for storing information
try() { $* 2>/dev/null || echo NO 1>&2 }
set `( try $MYPROGRAM | try safecat $TEMPDIR $DESTDIR ) 2>&1`
test "$?" = "0" || exit -1
test "$1" = "NO" && { rm -f $DESTDIR/$2; exit -1; }
This script illustrates the pitfalls of writing secure programs with the shell π« . The script assumes that your program might generate some output, but then fail to complete. There is no way for safecat to know whether your program completed successfully or not, because of the semantics of the shell. As a result, safecat might create a file in the data directory which is "complete" but not useful. The shell script deletes the file in that case.
More generally, the safest way to use safecat is from within a C program which invokes safecat with fork() and execve(). The parent process can then simply kill() the safecat process if any problems develop, and optionally can try again. Whether to go to this trouble depends upon how serious you are about protecting your data. Either way, safecat will not be the weak link in your data flow πͺ.
π BUGS π
In order to perform the last step and link() the temporary file into the destination directory, both directories must reside in the same file system. If they do not, safecat will quietly fail every time π. In Professor Bernstein's implementation of maildir, the temporary and destination directories are required to belong to the same parent directory, which essentially avoids this problem. We relax this requirement to provide some flexibility, at the cost of some risk. Caveat emptor.
Although safecat cleans up after itself, it may sometimes fail to delete the temporary file located in tempdir. Since safecat times out after 24 hours, you may freely delete any temporary files older than 36 hours. Files newer than 36 hours should be left alone. A system of data flow involving safecat should include a cron job to clean up temporary files, or should obligate consumers of the data to do the cleanup, or both. In the case of qmail, mail readers using maildir are expected to scan and clean up the temporary directory.
The guarantee of safe delivery of data is only "as certain as UNIX will allow." In particular, a disk hardware failure could result insafecatconcluding that the data was safe, when it was not. Similarly, a successful exit status fromsafecatis of no value if the computer, its disks and backups all explode at some subsequent time. π₯
In other words, if your data is vital to you, then you won't just use safecat. You'll also invest in good equipment (possibly including a RAID disk), a UPS for the server and drives, a regular backup schedule, and competent system administration. For many purposes, however, safecat can be considered 100% reliable β¨.
Also note that safecat was designed for spooling email messages; it is not the right tool for spooling large files β files larger than 2GB, for example. Some operating systems have a bug which causes safecat to fail silently when spooling files larger than 2GB. When building safecat, you can take advantage of conditional support for large files on Linux; see conf-cc for further information.
π CREDITS π
The maildir algorithm was devised by Professor Daniel Bernstein, the author of qmail. Parts of this manpage borrow directly from maildir(5) by Professor Bernstein. In particular, the section "THE MAILDIR ALGORITHM" transplants his explanation of the maildir algorithm in order to illustrate that safecat complies with it.
The original code for safecat was written by the present author, but was since augmented with heavy borrowings from qmail code. However, under no circumstances should the author of qmail be contacted concerning safecat bugs; all are the fault, and the responsibility, of the present author. π
Copyright (c) 2000, Len Budney. All rights reserved.
π SEE ALSO π
mbox(5)qmail-local(8)maildir(5)
and that's the whole page bestie π«Ά this one's safecat(1) from the General Commands Manual, with the copyright sitting at 2000 by Len Budney β so go forth, spool responsibly, and remember: every file complete or nonexistent, no cap π
β¨
π¦ where this page comes from
- debian bookworm: safecat 1.13-3+b1 Β· safecat
- debian trixie: safecat 1.13+git20170317.185e8bf-1 Β· safecat
- ubuntu jammy: safecat 1.13-3 Β· safecat
- ubuntu noble: safecat 1.13-3build1 Β· safecat
- ubuntu questing: safecat 1.13+git20170317.185e8bf-2
- ubuntu resolute: safecat 1.13+git20170317.185e8bf-2build1 Β· safecat
- ubuntu stonking: safecat 1.13+git20170317.185e8bf-2build1 Β· safecat
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms