Mercurial > hg > svcore
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; | 
