diff --git a/include/QF/sys.h b/include/QF/sys.h index 631489d79..3b6d5aed3 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -38,6 +38,8 @@ #include #include +struct dstring_s; + extern struct cvar_s *sys_nostdout; extern struct cvar_s *sys_extrasleep; extern struct cvar_s *sys_dead_sleep; @@ -166,6 +168,37 @@ int Sys_CreatePath (const char *path); */ char *Sys_ExpandSquiggle (const char *path); +/** Open a newly created file with a guaranteed unique name. + + Uniqueness is guaranteed by adding a numeric sequence between the \a + prefix and \a suffix, with a minium of \a mindigits numeric characters + (with any required leading 0s to expand the number to \a mindigits). + + The created file has read and write permissions as modified by the OS, + and the handle can be bothe written and read. + + \param name dstring into which the name will be generated. Any + existing contents will be lost. If an error occurs, + \a name will be set to the error string. + \param prefix This includes the path to the file and any file name + prefix. The numeric sequence will be appended directly + to the prefix with no directory separator. + \param suffix Optional tail to be appended after the numeric sequence, + usually the file extension. A dot is not added + automatically, it is up to the caller to supply one. NULL + and an empty string are equivalent. + \param mindigits The minimum number of digits to include in the + generated file name. The sequence number will be padded + with 0s in order to meet this menimum. Overflow will + simply produce longer numeric sequence sub-strings. + \return File handle to the newly created file, or a negative + value if an error occured (the negative error code). + Suitable for use with read, write, fdopen, Qdopen, etc. + \note It is the caller's responsibility to close the file. +*/ +int Sys_UniqueFile (struct dstring_s *name, const char *prefix, + const char *suffix, int mindigits); + ///@} #endif//__QF_sys_h diff --git a/libs/util/sys.c b/libs/util/sys.c index 8aefe89f5..daa9adb55 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -60,6 +60,7 @@ # include #endif +#include #include #include #include @@ -1155,3 +1156,29 @@ Sys_ExpandSquiggle (const char *path) home = "."; return nva ("%s%s", home, path + 1); // skip leading ~ } + +VISIBLE int +Sys_UniqueFile (dstring_t *name, const char *prefix, const char *suffix, + int mindigits) +{ + const int flags = O_CREAT | O_EXCL | O_RDWR; + const int mode = 0644; + int64_t seq = 0; // it should take a while to run out + + if (!suffix) { + suffix = ""; + } + while (1) { + dsprintf (name, "%s%0*"PRIi64"%s", prefix, mindigits, seq, suffix); + int fd = open (name->str, flags, mode); + if (fd >= 0) { + return fd; + } + int err = errno; + if (err != EEXIST) { + dsprintf (name, "%s", strerror (err)); + return -err; + } + seq++; + } +}