libi2ncommon: (tomj) switched oftmpstream to string
[libi2ncommon] / src / oftmpstream.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/stat.h>
5
6 #include <oftmpstream.hxx>
7
8 using namespace std;
9
10 void fdoutbuf::set_fd(int _fd) {
11     fd = _fd;
12 }
13
14 int 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
27 std::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
36 oftmpstream::oftmpstream () : ostream(0) {
37     fd = -1;
38     rdbuf(&buf);
39     is_open = false;
40 }
41
42 oftmpstream::oftmpstream (const std::string &name) : ostream(0) {
43     fd = -1;
44     rdbuf(&buf);
45     is_open = false;
46
47     open(name);
48 }
49
50 oftmpstream::~oftmpstream () {
51     close();
52 }
53
54 void oftmpstream::open (const string &name)
55 {
56     if (is_open)
57         close();
58
59     realname = name;
60     tmpname=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
81 void 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 }