libi2ncommon: (gerd) initial submission, not in use yet
[libi2ncommon] / src / oftmpstream.cpp
CommitLineData
e93545dd
GE
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <sys/stat.h>
5
6#include <oftmpstream.hxx>
7
8using namespace std;
9
10void fdoutbuf::set_fd(int _fd) {
11 fd = _fd;
12}
13
14int fdoutbuf::overflow (int_type c) {
15 if (fd == -1)
16 return c;
17
18 if (c != EOF) {
19 char z = c;
20 if (write (fd, &z, 1) != 1) {
21 return EOF;
22 }
23 }
24 return c;
25}
26// write multiple characters
27std::streamsize fdoutbuf::xsputn (const char* s,
28 std::streamsize num) {
29 if (fd == -1)
30 return (num);
31
32 return write(fd,s,num);
33}
34
35
36oftmpstream::oftmpstream () : ostream(0) {
37 fd = -1;
38 rdbuf(&buf);
39 is_open = false;
40}
41
42oftmpstream::oftmpstream (const char *name) : ostream(0) {
43 fd = -1;
44 rdbuf(&buf);
45 is_open = false;
46
47 open(name);
48}
49
50oftmpstream::~oftmpstream () {
51 close();
52}
53
54void oftmpstream::open (const char *name)
55{
56 if (is_open)
57 close();
58
59 realname = name;
60 tmpname=string(name)+".XXXXXX";
61
62 char* chbuf=new char[tmpname.size()+1];
63 tmpname.copy(chbuf,tmpname.size()+1);
64 chbuf[tmpname.size()]=0;
65 fd=mkstemp(chbuf);
66 tmpname=chbuf;
67 delete[] chbuf;
68
69 if (fd==-1)
70 {
71 string err="error creating temporary file "+tmpname;
72 err+=": ";
73 err+=strerror(errno);
74 throw ios_base::failure(err);
75 }
76
77 buf.set_fd(fd);
78 is_open = true;
79}
80
81void oftmpstream::close()
82{
83 if (!is_open)
84 return;
85
86 fsync(fd);
87 fchmod (fd, 0644); // fix mkstemp permissions
88 ::close (fd);
89
90 if (rename (tmpname.c_str(), realname.c_str()) != 0)
91 {
92 string err="error renaming temporary file "+tmpname;
93 err+=" to "+realname;
94 err+=": ";
95 err+=strerror(errno);
96 throw ios_base::failure(err);
97 }
98
99 fd = -1;
100 is_open = false;
101}