comparison data/fileio/BZipFileDevice.cpp @ 1381:ce08318aad83

Fixes to usage of fdopen, avoiding double-close in particular
author Chris Cannam
date Tue, 21 Feb 2017 21:08:14 +0000
parents b3cb0edc25cd
children f204f2fcb15e
comparison
equal deleted inserted replaced
1380:bd1eb56df8d5 1381:ce08318aad83
19 19
20 #include <iostream> 20 #include <iostream>
21 21
22 #include "base/Debug.h" 22 #include "base/Debug.h"
23 23
24 #ifdef _MSC_VER
25 #include <io.h>
26 #endif
27
24 BZipFileDevice::BZipFileDevice(QString fileName) : 28 BZipFileDevice::BZipFileDevice(QString fileName) :
25 m_fileName(fileName), 29 m_fileName(fileName),
26 m_qfile(fileName), 30 m_qfile(fileName),
27 m_file(0), 31 m_file(0),
28 m_bzFile(0), 32 m_bzFile(0),
69 setErrorString(tr("Read and write modes both specified")); 73 setErrorString(tr("Read and write modes both specified"));
70 m_ok = false; 74 m_ok = false;
71 return false; 75 return false;
72 } 76 }
73 77
78 // This is all going to be a bit silly.
79 //
80 // We open the file with QFile so as not to have to worry about locale
81 // support ourselves (especially on Windows). Then we get a fd from
82 // QFile and "convert" it to a FILE* using fdopen because that is what
83 // the bz2 library needs for reading and writing an already-open file.
84 //
85 // fdopen takes over the fd it is given, and will close it when fclose
86 // is called. (We must call fclose, because it's needed to avoid
87 // leaking the file stream structure.)
88 //
89 // But QFile will also close its fd, either when we call QFile::close
90 // or on destruction -- there doesn't seem to be a way to avoid that
91 // for a file that QFile opened.
92 //
93 // So we have to add an extra dup() in to the fdopen to avoid a double
94 // close.
95 //
96 // Note that bz2 will *not* fclose the FILE* it was passed, so we
97 // don't have a problem with calling both bzWriteClose and fclose.
98
74 if (mode & WriteOnly) { 99 if (mode & WriteOnly) {
75 100
76 if (!m_qfile.open(QIODevice::WriteOnly)) { 101 if (!m_qfile.open(QIODevice::WriteOnly)) {
77 setErrorString(tr("Failed to open file for writing")); 102 setErrorString(tr("Failed to open file for writing"));
78 m_ok = false; 103 m_ok = false;
79 return false; 104 return false;
80 } 105 }
81 106
82 m_file = fdopen(m_qfile.handle(), "wb"); 107 m_file = fdopen(dup(m_qfile.handle()), "wb");
83 if (!m_file) { 108 if (!m_file) {
84 setErrorString(tr("Failed to open file handle for writing")); 109 setErrorString(tr("Failed to open file handle for writing"));
85 m_qfile.close(); 110 m_qfile.close();
86 m_ok = false; 111 m_ok = false;
87 return false; 112 return false;
112 setErrorString(tr("Failed to open file for reading")); 137 setErrorString(tr("Failed to open file for reading"));
113 m_ok = false; 138 m_ok = false;
114 return false; 139 return false;
115 } 140 }
116 141
117 m_file = fdopen(m_qfile.handle(), "rb"); 142 m_file = fdopen(dup(m_qfile.handle()), "rb");
118 if (!m_file) { 143 if (!m_file) {
119 setErrorString(tr("Failed to open file handle for reading")); 144 setErrorString(tr("Failed to open file handle for reading"));
120 m_ok = false; 145 m_ok = false;
121 return false; 146 return false;
122 } 147 }
160 185
161 if (openMode() & WriteOnly) { 186 if (openMode() & WriteOnly) {
162 unsigned int in = 0, out = 0; 187 unsigned int in = 0, out = 0;
163 BZ2_bzWriteClose(&bzError, m_bzFile, 0, &in, &out); 188 BZ2_bzWriteClose(&bzError, m_bzFile, 0, &in, &out);
164 // cerr << "Wrote bzip2 stream (in=" << in << ", out=" << out << ")" << endl; 189 // cerr << "Wrote bzip2 stream (in=" << in << ", out=" << out << ")" << endl;
165 if (bzError != BZ_OK) { 190 if (bzError != BZ_OK) {
166 setErrorString(tr("bzip2 stream write close error")); 191 setErrorString(tr("bzip2 stream write close error"));
167 } 192 }
168 fclose(m_file); 193 fclose(m_file);
169 m_qfile.close(); 194 m_qfile.close();
170 m_bzFile = 0; 195 m_bzFile = 0;
171 m_file = 0; 196 m_file = 0;
172 m_ok = false; 197 m_ok = false;