+bool FileName::chdir() const
+{
+ return QDir::setCurrent(d->fi.absoluteFilePath());
+}
+
+
+bool FileName::link(FileName const & name) const
+{
+ return QFile::link(toqstr(absFileName()), toqstr(name.absFileName()));
+}
+
+
+unsigned long checksum_ifstream_fallback(char const * file)
+{
+ unsigned long result = 0;
+ //LYXERR(Debug::FILES, "lyx::sum() using istreambuf_iterator (fast)");
+ ifstream ifs(file, ios_base::in | ios_base::binary);
+ if (!ifs)
+ return result;
+
+ istreambuf_iterator<char> beg(ifs);
+ istreambuf_iterator<char> end;
+ boost::crc_32_type crc;
+ crc = for_each(beg, end, crc);
+ result = crc.checksum();
+ return result;
+}
+
+unsigned long FileName::checksum() const
+{
+ unsigned long result = 0;
+
+ if (!exists()) {
+ //LYXERR0("File \"" << absFileName() << "\" does not exist!");
+ return result;
+ }
+ // a directory may be passed here so we need to test it. (bug 3622)
+ if (isDirectory()) {
+ LYXERR0('"' << absFileName() << "\" is a directory!");
+ return result;
+ }
+
+ // This is used in the debug output at the end of the method.
+ static QTime t;
+ if (lyxerr.debugging(Debug::FILES))
+ t.restart();
+
+#if QT_VERSION >= 0x999999
+ // First version of checksum uses Qt4.4 mmap support.
+ // FIXME: This code is not ready with Qt4.4.2,
+ // see http://www.lyx.org/trac/ticket/5293
+ // FIXME: should we check if the MapExtension extension is supported?
+ // see QAbstractFileEngine::supportsExtension() and
+ // QAbstractFileEngine::MapExtension)
+ QFile qf(fi.filePath());
+ if (!qf.open(QIODevice::ReadOnly))
+ return result;
+ qint64 size = fi.size();
+ uchar * ubeg = qf.map(0, size);
+ uchar * uend = ubeg + size;
+ boost::crc_32_type ucrc;
+ ucrc.process_block(ubeg, uend);
+ qf.unmap(ubeg);
+ qf.close();
+ result = ucrc.checksum();
+
+#else // QT_VERSION
+
+ string const encoded = toSafeFilesystemEncoding();
+ char const * file = encoded.c_str();
+
+ #ifdef SUM_WITH_MMAP
+ //LYXERR(Debug::FILES, "using mmap (lightning fast)");
+
+ int fd = open(file, O_RDONLY);
+ if (!fd)
+ return result;
+
+ struct stat info;
+ if (fstat(fd, &info)){
+ // fstat fails on samba shares (bug 5891)
+ close(fd);
+ return checksum_ifstream_fallback(file);
+ }
+
+ void * mm = mmap(0, info.st_size, PROT_READ,
+ MAP_PRIVATE, fd, 0);
+ // Some platforms have the wrong type for MAP_FAILED (compaq cxx).
+ if (mm == reinterpret_cast<void*>(MAP_FAILED)) {
+ close(fd);
+ return result;
+ }
+
+ char * beg = static_cast<char*>(mm);
+ char * end = beg + info.st_size;
+
+ boost::crc_32_type crc;
+ crc.process_block(beg, end);
+ result = crc.checksum();
+
+ munmap(mm, info.st_size);
+ close(fd);
+
+ #else // no SUM_WITH_MMAP
+ result = checksum_ifstream_fallback(file);
+ #endif // SUM_WITH_MMAP
+#endif // QT_VERSION
+
+ LYXERR(Debug::FILES, "Checksumming \"" << absFileName() << "\" "
+ << result << " lasted " << t.elapsed() << " ms.");
+ return result;
+}
+
+