/*! Opens the file handle \a fh using the open mode \a flags. */ bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh) { Q_Q(QFSFileEngine); this->fh = fh; fd = -1; // Seek to the end when in Append mode. if (openMode & QIODevice::Append) { int ret; do { ret = QT_FSEEK(fh, 0, SEEK_END); } while (ret != 0 && errno == EINTR); if (ret != 0) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(int(errno))); this->openMode = QIODevice::NotOpen; this->fh = 0; return false; } } return true; }
/*! \internal */ bool QFSFileEnginePrivate::seekFdFh(qint64 pos) { Q_Q(QFSFileEngine); // On Windows' stdlib implementation, the results of calling fread and // fwrite are undefined if not called either in sequence, or if preceded // with a call to fflush(). if (lastIOCommand != QFSFileEnginePrivate::IOFlushCommand && !q->flush()) return false; if (pos < 0 || pos != qint64(QT_OFF_T(pos))) return false; if (fh) { // Buffered stdlib mode. int ret; do { ret = QT_FSEEK(fh, QT_OFF_T(pos), SEEK_SET); } while (ret != 0 && errno == EINTR); if (ret != 0) { q->setError(QFile::ReadError, qt_error_string(int(errno))); return false; } } else { // Unbuffered stdio mode. if (QT_LSEEK(fd, QT_OFF_T(pos), SEEK_SET) == -1) { qWarning() << "QFile::at: Cannot set file position" << pos; q->setError(QFile::PositionError, qt_error_string(errno)); return false; } } return true; }
/*! \internal */ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len) { Q_Q(QFSFileEngine); if (len < 0 || len != qint64(size_t(len))) { q->setError(QFile::ReadError, qt_error_string(EINVAL)); return -1; } qint64 readBytes = 0; bool eof = false; if (fh) { // Buffered stdlib mode. size_t result; bool retry = true; do { result = fread(data + readBytes, 1, size_t(len - readBytes), fh); eof = feof(fh); if (retry && eof && result == 0) { // On OS X, this is needed, e.g., if a file was written to // through another stream since our last read. See test // tst_QFile::appendAndRead QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET); // re-sync stream. retry = false; continue; } readBytes += result; } while (!eof && (result == 0 ? errno == EINTR : readBytes < len)); } else if (fd != -1) { // Unbuffered stdio mode. SignedIOType result; do { // calculate the chunk size // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks // we limit to the size of the signed type, otherwise we could get a negative number as a result quint64 wantedBytes = quint64(len) - quint64(readBytes); UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max(); if (chunkSize > wantedBytes) chunkSize = wantedBytes; result = QT_READ(fd, data + readBytes, chunkSize); } while (result > 0 && (readBytes += result) < len); eof = !(result == -1); } if (!eof && readBytes == 0) { readBytes = -1; q->setError(QFile::ReadError, qt_error_string(errno)); } return readBytes; }
/*! \internal */ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len) { Q_Q(QFSFileEngine); if (len < 0 || len != qint64(size_t(len))) { q->setError(QFile::ReadError, qt_error_string(EINVAL)); return -1; } qint64 readBytes = 0; bool eof = false; if (fh) { // Buffered stdlib mode. size_t result; bool retry = true; do { result = fread(data + readBytes, 1, size_t(len - readBytes), fh); eof = feof(fh); if (retry && eof && result == 0) { // On Mac OS, this is needed, e.g., if a file was written to // through another stream since our last read. See test // tst_QFile::appendAndRead QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET); // re-sync stream. retry = false; continue; } readBytes += result; } while (!eof && (result == 0 ? errno == EINTR : readBytes < len)); } else if (fd != -1) { // Unbuffered stdio mode. #ifdef Q_OS_WIN int result; #else ssize_t result; #endif do { result = QT_READ(fd, data + readBytes, size_t(len - readBytes)); } while ((result == -1 && errno == EINTR) || (result > 0 && (readBytes += result) < len)); eof = !(result == -1); } if (!eof && readBytes == 0) { readBytes = -1; q->setError(QFile::ReadError, qt_error_string(errno)); } return readBytes; }
/* \internal */ qint64 QFSFileEnginePrivate::nativeSize() const { Q_Q(const QFSFileEngine); QFSFileEngine *thatQ = const_cast<QFSFileEngine *>(q); // ### Don't flush; for buffered files, we should get away with ftell. thatQ->flush(); // Always retrive the current information metaData.clearFlags(QFileSystemMetaData::SizeAttribute); #if defined(Q_OS_WINCE) // Buffered stdlib mode. if (fh) { QT_OFF_T oldPos = QT_FTELL(fh); QT_FSEEK(fh, 0, SEEK_END); qint64 fileSize = (qint64)QT_FTELL(fh); QT_FSEEK(fh, oldPos, SEEK_SET); if (fileSize == -1) { fileSize = 0; thatQ->setError(QFile::UnspecifiedError, qt_error_string(errno)); } return fileSize; } if (fd != -1) { thatQ->setError(QFile::UnspecifiedError, QLatin1String("Not implemented!")); return 0; } #endif bool filled = false; if (fileHandle != INVALID_HANDLE_VALUE && openMode != QIODevice::NotOpen ) filled = QFileSystemEngine::fillMetaData(fileHandle, metaData, QFileSystemMetaData::SizeAttribute); else filled = doStat(QFileSystemMetaData::SizeAttribute); if (!filled) { thatQ->setError(QFile::UnspecifiedError, qt_error_string(errno)); return 0; } return metaData.size(); }
/*! \internal */ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) { Q_Q(QFSFileEngine); if (openMode & QIODevice::Unbuffered) { int flags = openModeToOpenFlags(openMode); // Try to open the file in unbuffered mode. do { fd = QT_OPEN(nativeFilePath.constData(), flags, 0666); } while (fd == -1 && errno == EINTR); // On failure, return and report the error. if (fd == -1) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(errno)); return false; } #ifndef O_CLOEXEC // not needed on Linux >= 2.6.23 setCloseOnExec(fd); // ignore failure #endif // Seek to the end when in Append mode. if (flags & QFile::Append) { int ret; do { ret = QT_LSEEK(fd, 0, SEEK_END); } while (ret == -1 && errno == EINTR); if (ret == -1) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(int(errno))); return false; } } fh = 0; } else { QByteArray fopenMode = openModeToFopenMode(openMode, filePath); // Try to open the file in buffered mode. do { fh = QT_FOPEN(nativeFilePath.constData(), fopenMode.constData()); } while (!fh && errno == EINTR); // On failure, return and report the error. if (!fh) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(int(errno))); return false; } setCloseOnExec(fileno(fh)); // ignore failure // Seek to the end when in Append mode. if (openMode & QIODevice::Append) { int ret; do { ret = QT_FSEEK(fh, 0, SEEK_END); } while (ret == -1 && errno == EINTR); if (ret == -1) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(int(errno))); return false; } } fd = -1; } closeFileHandle = true; return true; }
/*! \internal */ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) { Q_Q(QFSFileEngine); if (openMode & QIODevice::Unbuffered) { int flags = openModeToOpenFlags(openMode); // Try to open the file in unbuffered mode. do { fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, 0666); } while (fd == -1 && errno == EINTR); // On failure, return and report the error. if (fd == -1) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(errno)); return false; } if (!(openMode & QIODevice::WriteOnly)) { // we don't need this check if we tried to open for writing because then // we had received EISDIR anyway. if (QFileSystemEngine::fillMetaData(fd, metaData) && metaData.isDirectory()) { q->setError(QFile::OpenError, QLatin1String("file to open is a directory")); QT_CLOSE(fd); return false; } } // Seek to the end when in Append mode. if (flags & QFile::Append) { int ret; do { ret = QT_LSEEK(fd, 0, SEEK_END); } while (ret == -1 && errno == EINTR); if (ret == -1) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(int(errno))); return false; } } fh = 0; } else { QByteArray fopenMode = openModeToFopenMode(openMode, fileEntry, metaData); // Try to open the file in buffered mode. do { fh = QT_FOPEN(fileEntry.nativeFilePath().constData(), fopenMode.constData()); } while (!fh && errno == EINTR); // On failure, return and report the error. if (!fh) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(int(errno))); return false; } if (!(openMode & QIODevice::WriteOnly)) { // we don't need this check if we tried to open for writing because then // we had received EISDIR anyway. if (QFileSystemEngine::fillMetaData(QT_FILENO(fh), metaData) && metaData.isDirectory()) { q->setError(QFile::OpenError, QLatin1String("file to open is a directory")); fclose(fh); return false; } } setCloseOnExec(fileno(fh)); // ignore failure // Seek to the end when in Append mode. if (openMode & QIODevice::Append) { int ret; do { ret = QT_FSEEK(fh, 0, SEEK_END); } while (ret == -1 && errno == EINTR); if (ret == -1) { q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(int(errno))); return false; } } fd = -1; } closeFileHandle = true; return true; }
bool StarComponent::loadStaticData() { // We break from Qt / KDE API and use traditional file handling here, to obtain speed. // We also avoid C++ constructors for the same reason. KStarsData* data = KStarsData::Instance(); FILE *dataFile, *nameFile; bool swapBytes = false; BinFileHelper dataReader, nameReader; QString name, gname, visibleName; StarObject *star; if(starsLoaded) return true; // prepare to index stars to this date m_skyMesh->setKSNumbers( &m_reindexNum ); /* Open the data files */ // TODO: Maybe we don't want to hardcode the filename? if((dataFile = dataReader.openFile("namedstars.dat")) == NULL) { qDebug() << "Could not open data file namedstars.dat" << endl; return false; } if(!(nameFile = nameReader.openFile("starnames.dat"))) { qDebug() << "Could not open data file starnames.dat" << endl; return false; } if(!dataReader.readHeader()) { qDebug() << "Error reading namedstars.dat header : " << dataReader.getErrorNumber() << " : " << dataReader.getError() << endl; return false; } if(!nameReader.readHeader()) { qDebug() << "Error reading starnames.dat header : " << nameReader.getErrorNumber() << " : " << nameReader.getError() << endl; return false; } //KDE_fseek(nameFile, nameReader.getDataOffset(), SEEK_SET); QT_FSEEK(nameFile, nameReader.getDataOffset(), SEEK_SET); swapBytes = dataReader.getByteSwap(); long int nstars = 0; //KDE_fseek(dataFile, dataReader.getDataOffset(), SEEK_SET); QT_FSEEK(dataFile, dataReader.getDataOffset(), SEEK_SET); qint16 faintmag; quint8 htm_level; quint16 t_MSpT; fread( &faintmag, 2, 1, dataFile ); if( swapBytes ) faintmag = bswap_16( faintmag ); fread( &htm_level, 1, 1, dataFile ); fread( &t_MSpT, 2, 1, dataFile ); // Unused if( swapBytes ) faintmag = bswap_16( faintmag ); if( faintmag / 100.0 > m_FaintMagnitude ) m_FaintMagnitude = faintmag / 100.0; if( htm_level != m_skyMesh->level() ) qDebug() << "WARNING: HTM Level in shallow star data file and HTM Level in m_skyMesh do not match. EXPECT TROUBLE" << endl; for(int i = 0; i < m_skyMesh -> size(); ++i) { Trixel trixel = i;// = ( ( i >= 256 ) ? ( i - 256 ) : ( i + 256 ) ); for(unsigned long j = 0; j < (unsigned long)dataReader.getRecordCount(i); ++j) { if(!fread(&stardata, sizeof(starData), 1, dataFile)){ qDebug() << "FILE FORMAT ERROR: Could not read starData structure for star #" << j << " under trixel #" << trixel << endl; } /* Swap Bytes when required */ if(swapBytes) byteSwap( &stardata ); if(stardata.flags & 0x01) { /* Named Star - Read the nameFile */ visibleName = ""; if(!fread(&starname, sizeof( starName ), 1, nameFile)) qDebug() << "ERROR: fread() call on nameFile failed in trixel " << trixel << " star " << j << endl; name = QByteArray(starname.longName, 32); gname = QByteArray(starname.bayerName, 8); if ( ! gname.isEmpty() && gname.at(0) != '.') visibleName = gname; if(! name.isEmpty() ) { // HEV: look up star name in internationalization filesource name = i18nc("star name", name.toLocal8Bit().data()); } else { name = i18n("star"); } } else qDebug() << "ERROR: Named star file contains unnamed stars! Expect trouble." << endl; /* Create the new StarObject */ star = new StarObject; star->init( &stardata ); if( star->getHDIndex() != 0 && name == i18n("star")) name = QString("HD %1").arg(star->getHDIndex()); star->setNames( name, visibleName ); star->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); ++nstars; if ( ! gname.isEmpty() ) m_genName.insert( gname, star ); if ( ! name.isEmpty() && name != i18n("star")) { objectNames(SkyObject::STAR).append( name ); } if ( ! visibleName.isEmpty() && gname != name ) { objectNames(SkyObject::STAR).append( star -> gname(false) ); } m_ObjectList.append( star ); m_starIndex->at( trixel )->append( star ); double pm = star->pmMagnitude(); for (int j = 0; j < m_highPMStars.size(); j++ ) { HighPMStarList* list = m_highPMStars.at( j ); if ( list->append( trixel, star, pm ) ) break; } if( star->getHDIndex() != 0 ) m_HDHash.insert( star->getHDIndex(), star ); } } dataReader.closeFile(); nameReader.closeFile(); starsLoaded = true; return true; }
bool DeepStarComponent::loadStaticStars() { FILE *dataFile; if( !staticStars ) return true; if( !fileOpened ) return false; dataFile = starReader.getFileHandle(); rewind( dataFile ); if( !starReader.readHeader() ) { qDebug() << "Error reading header of catalog file " << dataFileName << ": " << starReader.getErrorNumber() << ": " << starReader.getError() << endl; return false; } quint8 recordSize = starReader.guessRecordSize(); if( recordSize != 16 && recordSize != 32 ) { qDebug() << "Cannot understand catalog file " << dataFileName << endl; return false; } //KDE_fseek(dataFile, starReader.getDataOffset(), SEEK_SET); QT_FSEEK(dataFile, starReader.getDataOffset(), SEEK_SET); qint16 faintmag; quint8 htm_level; quint16 t_MSpT; fread( &faintmag, 2, 1, dataFile ); if( starReader.getByteSwap() ) faintmag = bswap_16( faintmag ); fread( &htm_level, 1, 1, dataFile ); fread( &t_MSpT, 2, 1, dataFile ); // Unused if( starReader.getByteSwap() ) faintmag = bswap_16( faintmag ); // TODO: Read the multiplying factor from the dataFile m_FaintMagnitude = faintmag / 100.0; if( htm_level != m_skyMesh->level() ) qDebug() << "WARNING: HTM Level in shallow star data file and HTM Level in m_skyMesh do not match. EXPECT TROUBLE" << endl; // JM 2012-12-05: Breaking into into 2 loops instead of one previously with multiple IF checks for recordSize // While the CPU branch prediction might not suffer any penalities since the branch prediction after a few times // should always gets it right. It's better to do it this way to avoid any chances since the compiler might not optimize it. if (recordSize == 32) { for(Trixel i = 0; i < (unsigned int)m_skyMesh->size(); ++i) { Trixel trixel = i; quint64 records = starReader.getRecordCount( i ); StarBlock *SB = new StarBlock( records ); if( !SB ) qDebug() << "ERROR: Could not allocate new StarBlock to hold shallow unnamed stars for trixel " << trixel << endl; m_starBlockList.at( trixel )->setStaticBlock( SB ); for(quint64 j = 0; j < records; ++j) { bool fread_success = false; fread_success = fread( &stardata, sizeof( starData ), 1, dataFile ); if( !fread_success ) { qDebug() << "ERROR: Could not read starData structure for star #" << j << " under trixel #" << trixel << endl; } /* Swap Bytes when required */ if( starReader.getByteSwap() ) byteSwap( &stardata ); /* Initialize star with data just read. */ StarObject* star; #ifdef KSTARS_LITE star = &(SB->addStar( stardata )->star); #else star = SB->addStar( stardata ); #endif if( star ) { //KStarsData* data = KStarsData::Instance(); //star->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); //if( star->getHDIndex() != 0 ) if (stardata.HD) m_CatalogNumber.insert( stardata.HD, star ); } else { qDebug() << "CODE ERROR: More unnamed static stars in trixel " << trixel << " than we allocated space for!" << endl; } } } } else { for(Trixel i = 0; i < (unsigned int)m_skyMesh->size(); ++i) { Trixel trixel = i; quint64 records = starReader.getRecordCount( i ); StarBlock *SB = new StarBlock( records ); if( !SB ) qDebug() << "ERROR: Could not allocate new StarBlock to hold shallow unnamed stars for trixel " << trixel << endl; m_starBlockList.at( trixel )->setStaticBlock( SB ); for(quint64 j = 0; j < records; ++j) { bool fread_success = false; fread_success = fread( &deepstardata, sizeof( deepStarData ), 1, dataFile ); if( !fread_success ) { qDebug() << "ERROR: Could not read starData structure for star #" << j << " under trixel #" << trixel << endl; } /* Swap Bytes when required */ if( starReader.getByteSwap() ) byteSwap( &deepstardata ); /* Initialize star with data just read. */ StarObject* star; #ifdef KSTARS_LITE star = &(SB->addStar( stardata )->star); #else star = SB->addStar( deepstardata ); #endif if( star ) { //KStarsData* data = KStarsData::Instance(); //star->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); //if( star->getHDIndex() != 0 ) if (stardata.HD) m_CatalogNumber.insert( stardata.HD, star ); } else { qDebug() << "CODE ERROR: More unnamed static stars in trixel " << trixel << " than we allocated space for!" << endl; } } } } return true; }
/*! \internal */ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len) { Q_Q(QFSFileEngine); // Buffered stdlib mode. if (fh) { qint64 readBytes = 0; qint64 read = 0; int retry = 0; // Read in blocks of 4k to avoid platform limitations (Windows // commonly bails out if you read or write too large blocks at once). qint64 bytesToRead; do { if (retry == 1) retry = 2; bytesToRead = qMin<qint64>(4096, len - read); do { readBytes = fread(data + read, 1, size_t(bytesToRead), fh); } while (readBytes == 0 && !feof(fh) && errno == EINTR); if (readBytes > 0) { read += readBytes; } else if (!retry && feof(fh)) { // Synchronize and try again (just once though). if (++retry == 1) QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET); } } while (retry == 1 || (readBytes == bytesToRead && read < len)); // Return the number of bytes read, or if nothing was read, return -1 // if an error occurred, or 0 if we detected EOF. if (read == 0) { q->setError(QFile::ReadError, qt_error_string(int(errno))); if (!feof(fh)) read = -1; } return read; } // Unbuffered stdio mode. qint64 ret = 0; if (len) { int result; qint64 read = 0; errno = 0; // Read in blocks of 4k to avoid platform limitations (Windows // commonly bails out if you read or write too large blocks at once). do { qint64 bytesToRead = qMin<qint64>(4096, len - read); do { result = QT_READ(fd, data + read, int(bytesToRead)); } while (result == -1 && errno == EINTR); if (result > 0) read += result; } while (result > 0 && read < len); // Return the number of bytes read, or if nothing was read, return -1 // if an error occurred. if (read > 0) { ret += read; } else if (read == 0 && result < 0) { ret = -1; q->setError(QFile::ReadError, qt_error_string(errno)); } } return ret; }