libi2ncommon: (reinhard) changes for g++ 4.3.1
[libi2ncommon] / src / oftmpstream.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/stat.h>
5 #include <errno.h>
6 #include <string.h>
7
8 #include <oftmpstream.hxx>
9
10 using namespace std;
11
12 void fdoutbuf::set_fd(int _fd) {
13     fd = _fd;
14 }
15
16 int fdoutbuf::overflow (int_type c) {
17     if (fd == -1)
18         return c;
19
20     if (c != EOF) {
21         char z = c;
22         if (write (fd, &z, 1) != 1) {
23             return EOF;
24         }
25     }
26     return c;
27 }
28 // write multiple characters
29 std::streamsize fdoutbuf::xsputn (const char* s,
30                                   std::streamsize num) {
31     if (fd == -1)
32         return (num);
33     
34     return write(fd,s,num);
35 }
36
37
38 oftmpstream::oftmpstream ()
39 : ostream(0)
40 , file_mode(0644)
41 {
42     fd = -1;
43     rdbuf(&buf);
44     is_open = false;
45 }
46
47 oftmpstream::oftmpstream (const std::string &name)
48 : ostream(0)
49 , file_mode(0644)
50 {
51     fd = -1;
52     rdbuf(&buf);
53     is_open = false;
54
55     open(name);
56 }
57
58 oftmpstream::~oftmpstream () {
59     close();
60 }
61
62 std::string oftmpstream::get_filename()
63 {
64     return realname;
65 }
66
67 std::string oftmpstream::get_tmp_filename()
68 {
69     return tmpname;
70 }
71
72 void oftmpstream::open (const string &name)
73 {
74     if (is_open)
75         close();
76
77     realname = name;
78     tmpname=name+".XXXXXX";
79     file_mode= 0644;
80
81     char* chbuf=new char[tmpname.size()+1];
82     tmpname.copy(chbuf,tmpname.size()+1);
83     chbuf[tmpname.size()]=0;
84     fd=mkstemp(chbuf);
85     tmpname=chbuf;
86     delete[] chbuf;
87
88     if (fd==-1)
89     {
90         string err="error creating temporary file "+tmpname;
91         err+=": ";
92         err+=strerror(errno);
93         throw ios_base::failure(err);
94     }
95     
96     buf.set_fd(fd);
97     is_open = true;
98 }
99
100 void oftmpstream::close()
101 {
102     if (!is_open)
103         return;
104
105     fsync(fd);
106     fchmod (fd, file_mode);    // fix/change mkstemp permissions
107     ::close (fd);
108
109     if (rename (tmpname.c_str(), realname.c_str()) != 0)
110     {
111         string err="error renaming temporary file "+tmpname;
112         err+=" to "+realname;
113         err+=": ";
114         err+=strerror(errno);
115         throw ios_base::failure(err);
116     }
117
118     fd = -1;
119     is_open = false;
120     file_mode= 0644;
121 }
122
123
124 /**
125  * @brief set file mode for the final file.
126  * @param mode the fin al file mode.
127  *
128  * When called after open(), it determines the file mode which should
129  * be used for the resulting file.
130  */
131 void oftmpstream::set_file_mode(int mode)
132 {
133     file_mode= mode;
134 } // eo oftmpstream::set_file_mode(int)