int SMBSlave::cache_stat(const SMBUrl &url, struct stat *st) { int result = smbc_stat(url.toSmbcUrl(), st); kdDebug(KIO_SMB) << "smbc_stat " << url << " " << errno << " " << result << endl; kdDebug(KIO_SMB) << "size " << (KIO::filesize_t)st->st_size << endl; return result; }
void SMBSlave::fileSystemFreeSpace(const QUrl& url) { qCDebug(KIO_SMB) << url; SMBUrl smbcUrl = url; int handle = smbc_opendir(smbcUrl.toSmbcUrl()); if (handle < 0) { error(KIO::ERR_COULD_NOT_STAT, url.url()); return; } struct statvfs dirStat; memset(&dirStat, 0, sizeof(struct statvfs)); int err = smbc_fstatvfs(handle, &dirStat); smbc_closedir(handle); if (err < 0) { error(KIO::ERR_COULD_NOT_STAT, url.url()); return; } KIO::filesize_t blockSize; if (dirStat.f_frsize != 0) { blockSize = dirStat.f_frsize; } else { blockSize = dirStat.f_bsize; } setMetaData("total", QString::number(blockSize * dirStat.f_blocks)); setMetaData("available", QString::number(blockSize * dirStat.f_bavail)); finished(); }
int SMBSlave::cache_stat(const SMBUrl &url, struct stat* st ) { int cacheStatErr; int result = smbc_stat( url.toSmbcUrl(), st); if (result == 0){ cacheStatErr = 0; } else { cacheStatErr = errno; } qCDebug(KIO_SMB) << "size " << (KIO::filesize_t)st->st_size; return cacheStatErr; }
//=========================================================================== void SMBSlave::get( const KURL& kurl ) { char buf[MAX_XFER_BUF_SIZE]; int filefd = 0; ssize_t bytesread = 0; // time_t curtime = 0; time_t lasttime = 0; time_t starttime = 0; KIO::filesize_t totalbytesread = 0; QByteArray filedata; SMBUrl url; kdDebug(KIO_SMB) << "SMBSlave::get on " << kurl << endl; // check (correct) URL KURL kvurl = checkURL(kurl); // if URL is not valid we have to redirect to correct URL if (kvurl != kurl) { redirection(kvurl); finished(); return; } if(!auth_initialize_smbc()) return; // Stat url = kurl; if(cache_stat(url,&st) == -1 ) { if ( errno == EACCES ) error( KIO::ERR_ACCESS_DENIED, url.prettyURL()); else error( KIO::ERR_DOES_NOT_EXIST, url.prettyURL()); return; } if ( S_ISDIR( st.st_mode ) ) { error( KIO::ERR_IS_DIRECTORY, url.prettyURL()); return; } // Set the total size totalSize( st.st_size ); // Open and read the file filefd = smbc_open(url.toSmbcUrl(),O_RDONLY,0); if(filefd >= 0) { if(buf) { bool isFirstPacket = true; lasttime = starttime = time(NULL); while(1) { bytesread = smbc_read(filefd, buf, MAX_XFER_BUF_SIZE); if(bytesread == 0) { // All done reading break; } else if(bytesread < 0) { error( KIO::ERR_COULD_NOT_READ, url.prettyURL()); return; } filedata.setRawData(buf,bytesread); if (isFirstPacket) { // We need a KMimeType::findByNameAndContent(filename,data) // For now we do: find by extension, and if not found (or extension not reliable) // then find by content. bool accurate = false; KMimeType::Ptr mime = KMimeType::findByURL( kurl, st.st_mode, false, true, &accurate ); if ( !mime || mime->name() == KMimeType::defaultMimeType() || !accurate ) { KMimeType::Ptr p_mimeType = KMimeType::findByContent(filedata); if ( p_mimeType && p_mimeType->name() != KMimeType::defaultMimeType() ) mime = p_mimeType; } mimeType(mime->name()); isFirstPacket = false; } data( filedata ); filedata.resetRawData(buf,bytesread); // increment total bytes read totalbytesread += bytesread; processedSize(totalbytesread); } } smbc_close(filefd); data( QByteArray() ); processedSize(static_cast<KIO::filesize_t>(st.st_size)); } else { error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.prettyURL()); return; } finished(); }
//=========================================================================== void SMBSlave::rename( const QUrl& ksrc, const QUrl& kdest, KIO::JobFlags flags ) { SMBUrl src; SMBUrl dst; int errNum = 0; int retVal = 0; qCDebug(KIO_SMB) << "old name = " << ksrc << ", new name = " << kdest; src = ksrc; dst = kdest; // Check to se if the destination exists qCDebug(KIO_SMB) << "stat dst"; errNum = cache_stat(dst, &st); if( errNum == 0 ) { if(S_ISDIR(st.st_mode)) { qCDebug(KIO_SMB) << "KIO::ERR_DIR_ALREADY_EXIST"; error( KIO::ERR_DIR_ALREADY_EXIST, dst.toDisplayString()); return; } if(!(flags & KIO::Overwrite)) { qCDebug(KIO_SMB) << "KIO::ERR_FILE_ALREADY_EXIST"; error( KIO::ERR_FILE_ALREADY_EXIST, dst.toDisplayString()); return; } } qCDebug(KIO_SMB ) << "smbc_rename " << src.toSmbcUrl() << " " << dst.toSmbcUrl(); retVal = smbc_rename(src.toSmbcUrl(), dst.toSmbcUrl()); if( retVal < 0 ){ errNum = errno; } else { errNum = 0; } if( retVal < 0 ) { qCDebug(KIO_SMB ) << "failed "; switch(errNum) { case ENOENT: errNum = cache_stat(src, &st); if( errNum != 0 ) { if(errNum == EACCES) { qCDebug(KIO_SMB) << "KIO::ERR_ACCESS_DENIED"; error(KIO::ERR_ACCESS_DENIED, src.toDisplayString()); } else { qCDebug(KIO_SMB) << "KIO::ERR_DOES_NOT_EXIST"; error(KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); } } break; case EACCES: case EPERM: qCDebug(KIO_SMB) << "KIO::ERR_ACCESS_DENIED"; error( KIO::ERR_ACCESS_DENIED, dst.toDisplayString() ); break; default: qCDebug(KIO_SMB) << "KIO::ERR_CANNOT_RENAME"; error( KIO::ERR_CANNOT_RENAME, src.toDisplayString() ); } qCDebug(KIO_SMB) << "exit with error"; return; } qCDebug(KIO_SMB ) << "everything fine\n"; finished(); }
void SMBSlave::smbCopy(const QUrl& ksrc, const QUrl& kdst, int permissions, KIO::JobFlags flags) { SMBUrl src; SMBUrl dst; mode_t initialmode; ssize_t n; int dstflags; int srcfd = -1; int dstfd = -1; int errNum = 0; KIO::filesize_t processed_size = 0; unsigned char buf[MAX_XFER_BUF_SIZE]; qCDebug(KIO_SMB) << "SMBSlave::copy with src = " << ksrc << "and dest = " << kdst; // setup urls src = ksrc; dst = kdst; // Obtain information about source errNum = cache_stat(src, &st ); if( errNum != 0 ) { if ( errNum == EACCES ) { error( KIO::ERR_ACCESS_DENIED, src.toDisplayString()); } else { error( KIO::ERR_DOES_NOT_EXIST, src.toDisplayString()); } return; } if ( S_ISDIR( st.st_mode ) ) { error( KIO::ERR_IS_DIRECTORY, src.toDisplayString() ); return; } totalSize(st.st_size); // Check to se if the destination exists errNum = cache_stat(dst, &st); if( errNum == 0 ) { if(S_ISDIR(st.st_mode)) { error( KIO::ERR_DIR_ALREADY_EXIST, dst.toDisplayString()); return; } if(!(flags & KIO::Overwrite)) { error( KIO::ERR_FILE_ALREADY_EXIST, dst.toDisplayString()); return; } } // Open the source file srcfd = smbc_open(src.toSmbcUrl(), O_RDONLY, 0); if (srcfd < 0){ errNum = errno; } else { errNum = 0; } if(srcfd < 0) { if(errNum == EACCES) { error( KIO::ERR_ACCESS_DENIED, src.toDisplayString() ); } else { error( KIO::ERR_DOES_NOT_EXIST, src.toDisplayString() ); } return; } // Determine initial creation mode if(permissions != -1) { initialmode = permissions | S_IWUSR; } else { initialmode = 0 | S_IWUSR;//0666; } // Open the destination file dstflags = O_CREAT | O_TRUNC | O_WRONLY; if(!(flags & KIO::Overwrite)) { dstflags |= O_EXCL; } dstfd = smbc_open(dst.toSmbcUrl(), dstflags, initialmode); if (dstfd < 0){ errNum = errno; } else { errNum = 0; } if(dstfd < 0) { if(errNum == EACCES) { error(KIO::ERR_WRITE_ACCESS_DENIED, dst.toDisplayString()); } else { error(KIO::ERR_CANNOT_OPEN_FOR_READING, dst.toDisplayString()); } if(srcfd >= 0 ) { smbc_close(srcfd); } return; } // Perform copy while(1) { n = smbc_read(srcfd, buf, MAX_XFER_BUF_SIZE ); if(n > 0) { n = smbc_write(dstfd, buf, n); if(n == -1) { qCDebug(KIO_SMB) << "SMBSlave::copy copy now KIO::ERR_COULD_NOT_WRITE"; error( KIO::ERR_COULD_NOT_WRITE, dst.toDisplayString()); break; } processed_size += n; processedSize(processed_size); } else if(n == 0) { break; // finished } else { error( KIO::ERR_COULD_NOT_READ, src.toDisplayString()); break; } } // FINISHED: if(srcfd >= 0 ) { smbc_close(srcfd); } if(dstfd >= 0) { if(smbc_close(dstfd) == 0) { // TODO: set final permissions } else { error( KIO::ERR_COULD_NOT_WRITE, dst.toDisplayString()); return; } } finished(); }
void SMBSlave::smbCopyPut(const QUrl& ksrc, const QUrl& kdst, int permissions, KIO::JobFlags flags) { qCDebug(KIO_SMB) << "src = " << ksrc << ", dest = " << kdst; QFile srcFile (ksrc.toLocalFile()); const QFileInfo srcInfo (srcFile); if (srcInfo.exists()) { if (srcInfo.isDir()) { error(KIO::ERR_IS_DIRECTORY, ksrc.toDisplayString()); return; } } else { error(KIO::ERR_DOES_NOT_EXIST, ksrc.toDisplayString()); return; } if (!srcFile.open(QFile::ReadOnly)) { qCDebug(KIO_SMB) << "could not read from" << ksrc; switch (srcFile.error()) { case QFile::PermissionsError: error(KIO::ERR_WRITE_ACCESS_DENIED, ksrc.toDisplayString()); break; case QFile::OpenError: default: error(KIO::ERR_CANNOT_OPEN_FOR_READING, ksrc.toDisplayString()); break; } return; } totalSize(static_cast<filesize_t>(srcInfo.size())); bool bResume = false; bool bPartExists = false; const bool bMarkPartial = config()->readEntry("MarkPartial", true); const SMBUrl dstOrigUrl (kdst); if (bMarkPartial) { const int errNum = cache_stat(dstOrigUrl.partUrl(), &st); bPartExists = (errNum == 0); if (bPartExists) { if (!(flags & KIO::Overwrite) && !(flags & KIO::Resume)) { bResume = canResume(st.st_size); } else { bResume = (flags & KIO::Resume); } } } int dstfd = -1; int errNum = cache_stat(dstOrigUrl, &st); if (errNum == 0 && !(flags & KIO::Overwrite) && !(flags & KIO::Resume)) { if (S_ISDIR(st.st_mode)) { error( KIO::ERR_IS_DIRECTORY, dstOrigUrl.toDisplayString()); } else { error( KIO::ERR_FILE_ALREADY_EXIST, dstOrigUrl.toDisplayString()); } return; } KIO::filesize_t processed_size = 0; const SMBUrl dstUrl(bMarkPartial ? dstOrigUrl.partUrl() : dstOrigUrl); if (bResume) { // append if resuming qCDebug(KIO_SMB) << "resume" << dstUrl; dstfd = smbc_open(dstUrl.toSmbcUrl(), O_RDWR, 0 ); if (dstfd < 0) { errNum = errno; } else { const off_t offset = smbc_lseek(dstfd, 0, SEEK_END); if (offset == (off_t)-1) { error(KIO::ERR_COULD_NOT_SEEK, dstUrl.toDisplayString()); smbc_close(dstfd); return; } else { processed_size = offset; } } } else { mode_t mode; if (permissions == -1) { mode = 600; } else { mode = permissions | S_IRUSR | S_IWUSR; } qCDebug(KIO_SMB) << "NO resume" << dstUrl; dstfd = smbc_open(dstUrl.toSmbcUrl(), O_CREAT | O_TRUNC | O_WRONLY, mode); if (dstfd < 0) { errNum = errno; } } if (dstfd < 0) { if (errNum == EACCES) { qCDebug(KIO_SMB) << "access denied"; error( KIO::ERR_WRITE_ACCESS_DENIED, dstUrl.toDisplayString()); } else { qCDebug(KIO_SMB) << "can not open for writing"; error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, dstUrl.toDisplayString()); } return; } bool isErr = false; if (processed_size == 0 || srcFile.seek(processed_size)) { // Perform the copy char buf[MAX_XFER_BUF_SIZE]; while (1) { const ssize_t bytesRead = srcFile.read(buf, MAX_XFER_BUF_SIZE); if (bytesRead <= 0) { if (bytesRead < 0) { error(KIO::ERR_COULD_NOT_READ, ksrc.toDisplayString()); isErr = true; } break; } const qint64 bytesWritten = smbc_write(dstfd, buf, bytesRead); if (bytesWritten == -1) { error(KIO::ERR_COULD_NOT_WRITE, kdst.toDisplayString()); isErr = true; break; } processed_size += bytesWritten; processedSize(processed_size); } } else { isErr = true; error(KIO::ERR_COULD_NOT_SEEK, ksrc.toDisplayString()); } // FINISHED if (smbc_close(dstfd) < 0) { qCDebug(KIO_SMB) << dstUrl << "could not write"; error( KIO::ERR_COULD_NOT_WRITE, dstUrl.toDisplayString()); return; } // Handle error condition. if (isErr) { if (bMarkPartial) { const int size = config()->readEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE); const int errNum = cache_stat(dstUrl, &st); if (errNum == 0 && st.st_size < size) { smbc_unlink(dstUrl.toSmbcUrl()); } } return; } // Rename partial file to its original name. if (bMarkPartial) { smbc_unlink(dstOrigUrl.toSmbcUrl()); if (smbc_rename(dstUrl.toSmbcUrl(), dstOrigUrl.toSmbcUrl()) < 0) { qCDebug(KIO_SMB) << "failed to rename" << dstUrl << "to" << dstOrigUrl << "->" << strerror(errno); error(ERR_CANNOT_RENAME_PARTIAL, dstUrl.toDisplayString()); return; } } #ifdef HAVE_UTIME_H // set modification time const QString mtimeStr = metaData( "modified" ); if (!mtimeStr.isEmpty() ) { QDateTime dt = QDateTime::fromString( mtimeStr, Qt::ISODate ); if ( dt.isValid() ) { struct utimbuf utbuf; utbuf.actime = st.st_atime; // access time, unchanged utbuf.modtime = dt.toTime_t(); // modification time smbc_utime( dstUrl.toSmbcUrl(), &utbuf ); } } #endif // We have done our job => finish finished(); }