Example #1
0
//---------------------------------------------------------------------------
bool SMBSlave::browse_stat_path(const SMBUrl& _url, UDSEntry& udsentry, bool ignore_errors)
  // Returns: true on success, false on failure
{
   SMBUrl url = _url;

   int cacheStatErr = cache_stat(url, &st);
   if(cacheStatErr == 0)
   {
      if(!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
      {
         qCDebug(KIO_SMB) << "mode: "<< st.st_mode;
         warning(i18n("%1:\n"
                      "Unknown file type, neither directory or file.", url.toDisplayString()));
         return false;
      }

      udsentry.insert(KIO::UDSEntry::UDS_FILE_TYPE, st.st_mode & S_IFMT);
      udsentry.insert(KIO::UDSEntry::UDS_SIZE, st.st_size);

      QString str;
      uid_t uid = st.st_uid;
      struct passwd *user = getpwuid( uid );
      if ( user )
          str = user->pw_name;
      else
          str = QString::number( uid );
      udsentry.insert(KIO::UDSEntry::UDS_USER, str);

      gid_t gid = st.st_gid;
      struct group *grp = getgrgid( gid );
      if ( grp )
          str = grp->gr_name;
      else
          str = QString::number( gid );
      udsentry.insert(KIO::UDSEntry::UDS_GROUP, str);

      udsentry.insert(KIO::UDSEntry::UDS_ACCESS, st.st_mode & 07777);
      udsentry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, st.st_mtime);
      udsentry.insert(KIO::UDSEntry::UDS_ACCESS_TIME, st.st_atime);
      // No, st_ctime is not UDS_CREATION_TIME...
   }
   else
   {
       if (!ignore_errors) {
           if (cacheStatErr == EPERM || cacheStatErr == EACCES)
               if (checkPassword(url)) {
                   redirection( url );
                   return false;
               }

           reportError(url, cacheStatErr);
       } else if (cacheStatErr == ENOENT || cacheStatErr == ENOTDIR) {
           warning(i18n("File does not exist: %1", url.url()));
       }
       qCDebug(KIO_SMB) << "ERROR!!";
       return false;
   }

   return true;
}
Example #2
0
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();
}
Example #3
0
SMBUrl SMBUrl::partUrl() const
{
    if (m_type == SMBURLTYPE_SHARE_OR_PATH && !fileName().isEmpty()) {
        SMBUrl url (*this);
        url.setFileName(fileName() + QLatin1String(".part"));
        return url;
    }

    return SMBUrl();
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
//===========================================================================
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();
}
Example #7
0
//---------------------------------------------------------------------------
bool SMBSlave::browse_stat_path(const SMBUrl &_url, UDSEntry &udsentry, bool ignore_errors)
// Returns: true on success, false on failure
{
    UDSAtom udsatom;

    SMBUrl url = _url;

    if(cache_stat(url, &st) == 0)
    {
        if(!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
        {
            kdDebug(KIO_SMB) << "SMBSlave::browse_stat_path mode: " << st.st_mode << endl;
            warning(i18n("%1:\n"
                         "Unknown file type, neither directory or file.")
                        .arg(url.prettyURL()));
            return false;
        }

        udsatom.m_uds = KIO::UDS_FILE_TYPE;
        udsatom.m_long = st.st_mode & S_IFMT;
        udsentry.append(udsatom);

        udsatom.m_uds = KIO::UDS_SIZE;
        udsatom.m_long = st.st_size;
        udsentry.append(udsatom);

        udsatom.m_uds = KIO::UDS_USER;
        uid_t uid = st.st_uid;
        struct passwd *user = getpwuid(uid);
        if(user)
            udsatom.m_str = user->pw_name;
        else
            udsatom.m_str = QString::number(uid);
        udsentry.append(udsatom);

        udsatom.m_uds = KIO::UDS_GROUP;
        gid_t gid = st.st_gid;
        struct group *grp = getgrgid(gid);
        if(grp)
            udsatom.m_str = grp->gr_name;
        else
            udsatom.m_str = QString::number(gid);
        udsentry.append(udsatom);

        udsatom.m_uds = KIO::UDS_ACCESS;
        udsatom.m_long = st.st_mode & 07777;
        udsentry.append(udsatom);

        udsatom.m_uds = UDS_MODIFICATION_TIME;
        udsatom.m_long = st.st_mtime;
        udsentry.append(udsatom);

        udsatom.m_uds = UDS_ACCESS_TIME;
        udsatom.m_long = st.st_atime;
        udsentry.append(udsatom);

        udsatom.m_uds = UDS_CREATION_TIME;
        udsatom.m_long = st.st_ctime;
        udsentry.append(udsatom);
    }
    else
    {
        if(!ignore_errors)
        {
            if(errno == EPERM || errno == EACCES)
                if(checkPassword(url))
                {
                    redirection(url);
                    return false;
                }

            reportError(url);
        }
        else if(errno == ENOENT || errno == ENOTDIR)
        {
            warning(i18n("File does not exist: %1").arg(url.url()));
        }
        kdDebug(KIO_SMB) << "SMBSlave::browse_stat_path ERROR!!" << endl;
        return false;
    }

    return true;
}
Example #8
0
void SMBSlave::reportError(const SMBUrl &url)
{
    kdDebug(KIO_SMB) << "reportError " << url << " " << perror << endl;
    switch(errno)
    {
        case ENOENT:
            if(url.getType() == SMBURLTYPE_ENTIRE_NETWORK)
                error(ERR_SLAVE_DEFINED, i18n("Unable to find any workgroups in your local network. This might be caused by an enabled firewall."));
            else
                error(ERR_DOES_NOT_EXIST, url.prettyURL());
            break;
#ifdef ENOMEDIUM
        case ENOMEDIUM:
            error(ERR_SLAVE_DEFINED, i18n("No media in device for %1").arg(url.prettyURL()));
            break;
#endif
#ifdef EHOSTDOWN
        case EHOSTDOWN:
#endif
        case ECONNREFUSED:
            error(ERR_SLAVE_DEFINED, i18n("Could not connect to host for %1").arg(url.prettyURL()));
            break;
        case ENOTDIR:
            error(ERR_CANNOT_ENTER_DIRECTORY, url.prettyURL());
            break;
        case EFAULT:
        case EINVAL:
            error(ERR_DOES_NOT_EXIST, url.prettyURL());
            break;
        case EPERM:
        case EACCES:
            error(ERR_ACCESS_DENIED, url.prettyURL());
            break;
        case EIO:
        case ENETUNREACH:
            if(url.getType() == SMBURLTYPE_ENTIRE_NETWORK || url.getType() == SMBURLTYPE_WORKGROUP_OR_SERVER)
                error(ERR_SLAVE_DEFINED, i18n("Error while connecting to server responsible for %1").arg(url.prettyURL()));
            else
                error(ERR_CONNECTION_BROKEN, url.prettyURL());
            break;
        case ENOMEM:
            error(ERR_OUT_OF_MEMORY, url.prettyURL());
            break;
        case ENODEV:
            error(ERR_SLAVE_DEFINED, i18n("Share could not be found on given server"));
            break;
        case EBADF:
            error(ERR_INTERNAL, i18n("BAD File descriptor"));
            break;
        case ETIMEDOUT:
            error(ERR_SERVER_TIMEOUT, url.host());
            break;
#ifdef ENOTUNIQ
        case ENOTUNIQ:
            error(ERR_SLAVE_DEFINED, i18n("The given name could not be resolved to a unique server. "
                                          "Make sure your network is setup without any name conflicts "
                                          "between names used by Windows and by UNIX name resolution."));
            break;
#endif
        case 0: // success
            error(ERR_INTERNAL, i18n("libsmbclient reported an error, but did not specify "
                                     "what the problem is. This might indicate a severe problem "
                                     "with your network - but also might indicate a problem with "
                                     "libsmbclient.\n"
                                     "If you want to help us, please provide a tcpdump of the "
                                     "network interface while you try to browse (be aware that "
                                     "it might contain private data, so do not post it if you are "
                                     "unsure about that - you can send it privately to the developers "
                                     "if they ask for it)"));
            break;
        default:
            error(ERR_INTERNAL, i18n("Unknown error condition in stat: %1").arg(QString::fromLocal8Bit(strerror(errno))));
    }
}
Example #9
0
//===========================================================================
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();
}
Example #10
0
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();
}
Example #11
0
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();
}