diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,8 +161,7 @@ endif() add_subdirectory( thumbnail ) add_subdirectory( docfilter ) -if (libssh_FOUND AND HAVE_UTIME_H) - # does not compile on Windows: kio_sftp.cpp(28): fatal error C1083: Cannot open include file: 'utime.h': No such file or directory +if (libssh_FOUND) add_subdirectory(sftp) endif () add_subdirectory(settings) diff --git a/sftp/CMakeLists.txt b/sftp/CMakeLists.txt --- a/sftp/CMakeLists.txt +++ b/sftp/CMakeLists.txt @@ -1,7 +1,9 @@ add_definitions(-DTRANSLATION_DOMAIN=\"kio5_sftp\") include_directories(${LIBSSH_INCLUDE_DIR}) - +if(WIN32) +include_directories(${QT_MKSPECS_DIR}/default) # for SYMLINKS +endif() set(kio_sftp_SRCS kio_sftp.cpp) ecm_qt_declare_logging_category(kio_sftp_SRCS diff --git a/sftp/kio_sftp.cpp b/sftp/kio_sftp.cpp --- a/sftp/kio_sftp.cpp +++ b/sftp/kio_sftp.cpp @@ -26,22 +26,30 @@ #include "kio_sftp_trace_debug.h" #include #include -#include #include #include #include #include #include #include +#include #include #include #include #include #include +#ifdef Q_OS_WIN +#include // for permissions +using namespace std::experimental::filesystem; +#include +#else +#include +#endif + #define KIO_SFTP_SPECIAL_TIMEOUT 30 // How big should each data packet be? Definitely not bigger than 64kb or @@ -379,7 +387,11 @@ if (isBrokenLink) { // It is a link pointing to nowhere fileType = S_IFMT - 1; +#ifdef Q_OS_WIN + access = static_cast(perms::owner_all | perms::group_all | perms::others_all); +#else access = S_IRWXU | S_IRWXG | S_IRWXO; +#endif size = 0LL; } else { switch (sb->type) { @@ -390,7 +402,12 @@ fileType = S_IFDIR; break; case SSH_FILEXFER_TYPE_SYMLINK: +#ifdef Q_OS_WIN + // TODO Check if this works for other OSes too. + fileType = QT_STAT_LNK; +#else fileType = S_IFLNK; +#endif break; case SSH_FILEXFER_TYPE_SPECIAL: case SSH_FILEXFER_TYPE_UNKNOWN: @@ -1751,7 +1768,11 @@ mode_t initialMode; if (permissions != -1) { +#ifdef Q_OS_WIN + initialMode = permissions | static_cast(perms::owner_write | perms::owner_read); +#else initialMode = permissions | S_IWUSR | S_IRUSR; +#endif } else { initialMode = 0644; } @@ -1924,9 +1945,9 @@ // check if destination is ok ... QT_STATBUF buff; const bool bDestExists = (QT_STAT(QFile::encodeName(sCopyFile), &buff) != -1); - + QFileInfo info(sCopyFile); if(bDestExists) { - if(S_ISDIR(buff.st_mode)) { + if(info.isDir()) { errorCode = ERR_IS_DIRECTORY; return sftpProtocol::ClientError; } @@ -1944,7 +1965,7 @@ const QString dest = (bMarkPartial ? sPart : sCopyFile); if (bMarkPartial && bPartExists && buff.st_size > 0) { - if (S_ISDIR(buff.st_mode)) { + if(info.isDir()) { errorCode = ERR_DIR_ALREADY_EXIST; return sftpProtocol::ClientError; // client side error } @@ -1958,7 +1979,11 @@ // otherwise we can be in for a surprise on NFS. mode_t initialMode; if (permissions != -1) +#ifdef Q_OS_WIN + initialMode = permissions | static_cast(perms::owner_write); +#else initialMode = permissions | S_IWUSR; +#endif else initialMode = 0666; @@ -2015,10 +2040,19 @@ if (!mtimeStr.isEmpty()) { QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate); if (dt.isValid()) { - struct utimbuf utbuf; - utbuf.actime = buff.st_atime; // access time, unchanged - utbuf.modtime = dt.toTime_t(); // modification time - utime(QFile::encodeName(sCopyFile), &utbuf); + QFile receivedFile(sCopyFile); + if (!receivedFile.exists()) { + if (!receivedFile.open(QIODevice::ReadWrite | QIODevice::Text)) { + QString error_msg = receivedFile.errorString(); + qCDebug(KIO_SFTP_LOG) << QStringLiteral("Couldn't update modified time : ") << error_msg; + } + else { + receivedFile.open(QIODevice::ReadWrite | QIODevice::Text); + receivedFile.setFileTime(QDateTime::fromTime_t(buff.st_atime), + QFileDevice::FileTime(QFileDevice::FileAccessTime)); + receivedFile.setFileTime(dt, QFileDevice::FileTime(QFileDevice::FileModificationTime)); + } + } } } @@ -2032,9 +2066,9 @@ // check if source is ok ... QT_STATBUF buff; bool bSrcExists = (QT_STAT(QFile::encodeName(sCopyFile), &buff) != -1); - + QFileInfo info(sCopyFile); if (bSrcExists) { - if (S_ISDIR(buff.st_mode)) { + if(info.isDir()) { errorCode = ERR_IS_DIRECTORY; return sftpProtocol::ClientError; } @@ -2210,7 +2244,11 @@ if (isBrokenLink) { // It is a link pointing to nowhere fileType = S_IFMT - 1; +#ifdef Q_OS_WIN + access = static_cast(perms::owner_all | perms::group_all | perms::others_all); +#else access = S_IRWXU | S_IRWXG | S_IRWXO; +#endif size = 0LL; } else { switch (dirent->type) { @@ -2221,7 +2259,11 @@ fileType = S_IFDIR; break; case SSH_FILEXFER_TYPE_SYMLINK: +#ifdef Q_OS_WIN + fileType = QT_STAT_LNK; +#else fileType = S_IFLNK; +#endif break; case SSH_FILEXFER_TYPE_SPECIAL: case SSH_FILEXFER_TYPE_UNKNOWN: