const std::set<std::string> &global_stags,
const std::set<std::string> &global_mtags)
{
- FILE *file = NULL;
- bool temp = false;
+ FILE *file = NULL, *temp = NULL;
std::string filename = fname, tempname = fname;
if (filename.empty()) {
filename = "<stdout>";
file = stdout;
}
- else if ((file = temp_file(tempname))) {
- temp = true;
+ else if ((temp = temp_file(tempname))) {
+ file = temp;
}
else if (!(file = fopen(filename.c_str(), "w"))) {
error("cannot open output file %s", filename.c_str());
}
fclose(file);
- if (temp && rename(tempname.c_str(), fname.c_str()) != 0) {
- error("cannot rename temporary file %s to output file %s"
+ if (temp && !overwrite_file(tempname.c_str(), fname.c_str())) {
+ error("cannot rename or write temporary file %s to output file %s"
, tempname.c_str(), fname.c_str());
+ remove(tempname.c_str());
return false;
}
-
return true;
}
#include "config.h"
#include <time.h>
-#include "src/msg/msg.h"
#include "src/util/temp_file.h"
#define OPEN(fn) open(fn, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR)
#define FDOPEN(fd) fdopen(fd, "w")
#define CLOSE(fd) close(fd)
+#define UNLINK(f) unlink(f)
#elif defined(_MSC_VER) \
&& defined(HAVE_IO_H) \
#define OPEN(fn) _open(fn, _O_CREAT | _O_EXCL | _O_RDWR, _S_IREAD | _S_IWRITE)
#define FDOPEN(fd) _fdopen(fd, "w")
#define CLOSE(fd) _close(fd)
+#define UNLINK(f) _unlink(f)
#else
#define OPEN(fn) -1
#define FDOPEN(fd) NULL
#define CLOSE -1
+#define UNLINK(f) -1
#endif
}
// we don't try too hard
- if (!f) {
- error("cannot open temporary file %s", fname.c_str());
- }
return f;
}
+bool overwrite_file(const char *srcname, const char *dstname)
+{
+ // remove destination file no matter what
+ UNLINK(dstname);
+
+ // try the easy way: rename
+ if (rename(srcname, dstname) == 0) return true;
+
+ // rename failed: try write
+ FILE *src = NULL, *dst = NULL;
+ bool ok = false;
+
+ src = fopen(srcname, "r");
+ if (!src) goto end;
+
+ dst = fopen(dstname, "w");
+ if (!dst) goto end;
+
+ static const size_t BLK = 4096;
+ char buf[BLK];
+ for (;;) {
+ const size_t n = fread(buf, 1, BLK, src);
+ fwrite(buf, 1, n, dst);
+ if (n < BLK) break;
+ }
+ ok = true;
+
+end:
+ if (src) fclose(src);
+ if (dst) fclose(dst);
+ UNLINK(ok ? srcname : dstname);
+
+ return ok;
+}
+
} // namespace re2c
#undef OPEN
#undef FDOPEN
#undef CLOSE
+#undef UNLINK