Changeset View
Standalone View
sftp/kio_sftp.cpp
Show All 20 Lines | |||||
21 | 21 | | |||
22 | #include "kio_sftp.h" | 22 | #include "kio_sftp.h" | ||
23 | 23 | | |||
24 | #include <config-runtime.h> | 24 | #include <config-runtime.h> | ||
25 | #include "kio_sftp_debug.h" | 25 | #include "kio_sftp_debug.h" | ||
26 | #include "kio_sftp_trace_debug.h" | 26 | #include "kio_sftp_trace_debug.h" | ||
27 | #include <cerrno> | 27 | #include <cerrno> | ||
28 | #include <cstring> | 28 | #include <cstring> | ||
29 | #include <utime.h> | | |||
brute4s99: this builds without `utime.h` on my system (Arch Linux with latest Plasma, Qt and other… | |||||
30 | 29 | | |||
31 | #include <QCoreApplication> | 30 | #include <QCoreApplication> | ||
32 | #include <QDir> | 31 | #include <QDir> | ||
33 | #include <QFile> | 32 | #include <QFile> | ||
34 | #include <QVarLengthArray> | 33 | #include <QVarLengthArray> | ||
35 | #include <QMimeType> | 34 | #include <QMimeType> | ||
36 | #include <QMimeDatabase> | 35 | #include <QMimeDatabase> | ||
36 | #include <QDateTime> | ||||
37 | 37 | | |||
38 | #include <kuser.h> | 38 | #include <kuser.h> | ||
39 | #include <kmessagebox.h> | 39 | #include <kmessagebox.h> | ||
40 | 40 | | |||
41 | #include <klocalizedstring.h> | 41 | #include <klocalizedstring.h> | ||
42 | #include <kconfiggroup.h> | 42 | #include <kconfiggroup.h> | ||
43 | #include <kio/ioslave_defaults.h> | 43 | #include <kio/ioslave_defaults.h> | ||
44 | 44 | | |||
45 | #ifdef Q_OS_WIN | ||||
46 | #include <experimental/filesystem> // for permissions | ||||
47 | using namespace std::experimental::filesystem; | ||||
48 | #include <qplatformdefs.h> | ||||
49 | #else | ||||
50 | #include <utime.h> | ||||
51 | #endif | ||||
52 | | ||||
45 | #define KIO_SFTP_SPECIAL_TIMEOUT 30 | 53 | #define KIO_SFTP_SPECIAL_TIMEOUT 30 | ||
46 | 54 | | |||
47 | // How big should each data packet be? Definitely not bigger than 64kb or | 55 | // How big should each data packet be? Definitely not bigger than 64kb or | ||
48 | // you will overflow the 2 byte size variable in a sftp packet. | 56 | // you will overflow the 2 byte size variable in a sftp packet. | ||
49 | #define MAX_XFER_BUF_SIZE (60 * 1024) | 57 | #define MAX_XFER_BUF_SIZE (60 * 1024) | ||
50 | 58 | | |||
51 | #define KSFTP_ISDIR(sb) (sb->type == SSH_FILEXFER_TYPE_DIRECTORY) | 59 | #define KSFTP_ISDIR(sb) (sb->type == SSH_FILEXFER_TYPE_DIRECTORY) | ||
52 | 60 | | |||
▲ Show 20 Lines • Show All 197 Lines • ▼ Show 20 Line(s) | 257 | int sftpProtocol::authenticateKeyboardInteractive(AuthInfo &info) { | |||
250 | 258 | | |||
251 | int err = ssh_userauth_kbdint(mSession, nullptr, nullptr); | 259 | int err = ssh_userauth_kbdint(mSession, nullptr, nullptr); | ||
252 | 260 | | |||
253 | while (err == SSH_AUTH_INFO) { | 261 | while (err == SSH_AUTH_INFO) { | ||
254 | const QString name = QString::fromUtf8(ssh_userauth_kbdint_getname(mSession)); | 262 | const QString name = QString::fromUtf8(ssh_userauth_kbdint_getname(mSession)); | ||
255 | const QString instruction = QString::fromUtf8(ssh_userauth_kbdint_getinstruction(mSession)); | 263 | const QString instruction = QString::fromUtf8(ssh_userauth_kbdint_getinstruction(mSession)); | ||
256 | const int n = ssh_userauth_kbdint_getnprompts(mSession); | 264 | const int n = ssh_userauth_kbdint_getnprompts(mSession); | ||
257 | 265 | | |||
258 | qCDebug(KIO_SFTP_LOG) << "name=" << name << " instruction=" << instruction << " prompts=" << n; | 266 | qCDebug(KIO_SFTP_LOG) << "name=" << name << " instruction=" << instruction << " prompts=" << n; | ||
Use kdebugsettings to enable sftp debug output instead of qCDebug->qDebug (which adds a lot of noise to the review) dfaure: Use `kdebugsettings` to enable sftp debug output instead of qCDebug->qDebug (which adds a lot… | |||||
259 | 267 | | |||
260 | for (int i = 0; i < n; ++i) { | 268 | for (int i = 0; i < n; ++i) { | ||
261 | char echo; | 269 | char echo; | ||
262 | const char *answer = ""; | 270 | const char *answer = ""; | ||
263 | 271 | | |||
264 | const QString prompt = QString::fromUtf8(ssh_userauth_kbdint_getprompt(mSession, i, &echo)); | 272 | const QString prompt = QString::fromUtf8(ssh_userauth_kbdint_getprompt(mSession, i, &echo)); | ||
265 | qCDebug(KIO_SFTP_LOG) << "prompt=" << prompt << " echo=" << QString::number(echo); | 273 | qCDebug(KIO_SFTP_LOG) << "prompt=" << prompt << " echo=" << QString::number(echo); | ||
266 | if (echo) { | 274 | if (echo) { | ||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Line(s) | 380 | } else { | |||
374 | sb = sb2; | 382 | sb = sb2; | ||
375 | } | 383 | } | ||
376 | } | 384 | } | ||
377 | } | 385 | } | ||
378 | 386 | | |||
379 | if (isBrokenLink) { | 387 | if (isBrokenLink) { | ||
380 | // It is a link pointing to nowhere | 388 | // It is a link pointing to nowhere | ||
381 | fileType = S_IFMT - 1; | 389 | fileType = S_IFMT - 1; | ||
390 | #ifdef Q_OS_WIN | ||||
391 | access = static_cast<mode_t>(perms::owner_all | perms::group_all | perms::others_all); | ||||
static_cast instead of c cast, a single cast should do. vonreth: static_cast instead of c cast, a single cast should do.
Are the types compatible? | |||||
392 | #else | ||||
382 | access = S_IRWXU | S_IRWXG | S_IRWXO; | 393 | access = S_IRWXU | S_IRWXG | S_IRWXO; | ||
394 | #endif | ||||
383 | size = 0LL; | 395 | size = 0LL; | ||
384 | } else { | 396 | } else { | ||
385 | switch (sb->type) { | 397 | switch (sb->type) { | ||
386 | case SSH_FILEXFER_TYPE_REGULAR: | 398 | case SSH_FILEXFER_TYPE_REGULAR: | ||
387 | fileType = S_IFREG; | 399 | fileType = S_IFREG; | ||
388 | break; | 400 | break; | ||
389 | case SSH_FILEXFER_TYPE_DIRECTORY: | 401 | case SSH_FILEXFER_TYPE_DIRECTORY: | ||
390 | fileType = S_IFDIR; | 402 | fileType = S_IFDIR; | ||
391 | break; | 403 | break; | ||
392 | case SSH_FILEXFER_TYPE_SYMLINK: | 404 | case SSH_FILEXFER_TYPE_SYMLINK: | ||
405 | #ifdef Q_OS_WIN | ||||
406 | // TODO Check if this works for other OSes too. | ||||
vonreth: What about the QFileInfo? | |||||
For my use case, I could not find any possibility of symlinks, (traversing Android filesystem) so I left it blank in here for any future dev to fix it. brute4s99: For my use case, I could not find any possibility of symlinks, (traversing Android filesystem)… | |||||
Yes, QT_STAT_LNK works on Unix too, we use it in many places in KIO So I'm pretty sure you can remove this ifdef. You could also replace S_IFREG with QT_STAT_REG and S_IFDIR with QT_STAT_DIR, for consistency. dfaure: Yes, QT_STAT_LNK works on Unix too, we use it in many places in KIO
(and it has the value… | |||||
407 | fileType = QT_STAT_LNK; | ||||
408 | #else | ||||
393 | fileType = S_IFLNK; | 409 | fileType = S_IFLNK; | ||
410 | #endif | ||||
394 | break; | 411 | break; | ||
395 | case SSH_FILEXFER_TYPE_SPECIAL: | 412 | case SSH_FILEXFER_TYPE_SPECIAL: | ||
396 | case SSH_FILEXFER_TYPE_UNKNOWN: | 413 | case SSH_FILEXFER_TYPE_UNKNOWN: | ||
397 | fileType = S_IFMT - 1; | 414 | fileType = S_IFMT - 1; | ||
398 | break; | 415 | break; | ||
399 | } | 416 | } | ||
400 | access = sb->permissions & 07777; | 417 | access = sb->permissions & 07777; | ||
401 | size = sb->size; | 418 | size = sb->size; | ||
▲ Show 20 Lines • Show All 1344 Lines • ▼ Show 20 Line(s) | 1761 | if (fstat) { | |||
1746 | totalBytesSent += fstat->size; | 1763 | totalBytesSent += fstat->size; | ||
1747 | sftp_attributes_free(fstat); | 1764 | sftp_attributes_free(fstat); | ||
1748 | } | 1765 | } | ||
1749 | } | 1766 | } | ||
1750 | } else { | 1767 | } else { | ||
1751 | mode_t initialMode; | 1768 | mode_t initialMode; | ||
1752 | 1769 | | |||
1753 | if (permissions != -1) { | 1770 | if (permissions != -1) { | ||
1771 | #ifdef Q_OS_WIN | ||||
1772 | initialMode = permissions | static_cast<mode_t>(perms::owner_write | perms::owner_read); | ||||
vonreth: single static cast as above | |||||
1773 | #else | ||||
1754 | initialMode = permissions | S_IWUSR | S_IRUSR; | 1774 | initialMode = permissions | S_IWUSR | S_IRUSR; | ||
1775 | #endif | ||||
1755 | } else { | 1776 | } else { | ||
1756 | initialMode = 0644; | 1777 | initialMode = 0644; | ||
1757 | } | 1778 | } | ||
1758 | 1779 | | |||
1759 | qCDebug(KIO_SFTP_LOG) << "Trying to open:" << QString(dest) << ", mode=" << QString::number(initialMode); | 1780 | qCDebug(KIO_SFTP_LOG) << "Trying to open:" << QString(dest) << ", mode=" << QString::number(initialMode); | ||
1760 | file = sftp_open(mSftp, dest.constData(), O_CREAT | O_TRUNC | O_WRONLY, initialMode); | 1781 | file = sftp_open(mSftp, dest.constData(), O_CREAT | O_TRUNC | O_WRONLY, initialMode); | ||
1761 | } // flags & KIO::Resume | 1782 | } // flags & KIO::Resume | ||
1762 | 1783 | | |||
▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Line(s) | 1903 | { | |||
1916 | 1937 | | |||
1917 | finished(); | 1938 | finished(); | ||
1918 | } | 1939 | } | ||
1919 | 1940 | | |||
1920 | sftpProtocol::StatusCode sftpProtocol::sftpCopyGet(const QUrl& url, const QString& sCopyFile, int permissions, KIO::JobFlags flags, int& errorCode) | 1941 | sftpProtocol::StatusCode sftpProtocol::sftpCopyGet(const QUrl& url, const QString& sCopyFile, int permissions, KIO::JobFlags flags, int& errorCode) | ||
1921 | { | 1942 | { | ||
1922 | qCDebug(KIO_SFTP_LOG) << url << "->" << sCopyFile << ", permissions=" << permissions; | 1943 | qCDebug(KIO_SFTP_LOG) << url << "->" << sCopyFile << ", permissions=" << permissions; | ||
1923 | 1944 | | |||
1924 | // check if destination is ok ... | 1945 | // check if destination is ok ... | ||
1925 | QT_STATBUF buff; | 1946 | QFileInfo copyFile(sCopyFile); | ||
We're now doing stat() twice, once here, and once in QFileInfo just below. This could be fixed by using QFileInfo for everything: const bool bDestExists = info.exists(); dfaure: We're now doing stat() twice, once here, and once in QFileInfo just below.
This could be fixed… | |||||
Please remove this variable, since you're not calling QT_STAT anymore. You'll notice that you're still using buff.st_size, which should become QFileInfo's size() method instead... dfaure: Please remove this variable, since you're not calling QT_STAT anymore.
You'll notice that… | |||||
1926 | const bool bDestExists = (QT_STAT(QFile::encodeName(sCopyFile), &buff) != -1); | 1947 | const bool bDestExists = copyFile.exists(); | ||
1927 | | ||||
1928 | if(bDestExists) { | 1948 | if(bDestExists) { | ||
1929 | if(S_ISDIR(buff.st_mode)) { | 1949 | if(copyFile.isDir()) { | ||
1930 | errorCode = ERR_IS_DIRECTORY; | 1950 | errorCode = ERR_IS_DIRECTORY; | ||
1931 | return sftpProtocol::ClientError; | 1951 | return sftpProtocol::ClientError; | ||
1932 | } | 1952 | } | ||
1933 | 1953 | | |||
1934 | if(!(flags & KIO::Overwrite)) { | 1954 | if(!(flags & KIO::Overwrite)) { | ||
1935 | errorCode = ERR_FILE_ALREADY_EXIST; | 1955 | errorCode = ERR_FILE_ALREADY_EXIST; | ||
1936 | return sftpProtocol::ClientError; | 1956 | return sftpProtocol::ClientError; | ||
1937 | } | 1957 | } | ||
1938 | } | 1958 | } | ||
1939 | 1959 | | |||
1940 | bool bResume = false; | 1960 | bool bResume = false; | ||
1941 | const QString sPart = sCopyFile + QLatin1String(".part"); // do we have a ".part" file? | 1961 | const QString sPart = sCopyFile + QLatin1String(".part"); // do we have a ".part" file? | ||
1942 | const bool bPartExists = (QT_STAT(QFile::encodeName(sPart), &buff) != -1); | 1962 | QFileInfo partFile(sPart); | ||
1963 | const bool bPartExists = partFile.exists(); | ||||
1943 | const bool bMarkPartial = config()->readEntry("MarkPartial", true); | 1964 | const bool bMarkPartial = config()->readEntry("MarkPartial", true); | ||
1944 | const QString dest = (bMarkPartial ? sPart : sCopyFile); | 1965 | const QString dest = (bMarkPartial ? sPart : sCopyFile); | ||
1945 | 1966 | | |||
1946 | if (bMarkPartial && bPartExists && buff.st_size > 0) { | 1967 | if (bMarkPartial && bPartExists && copyFile.size() > 0) { | ||
1947 | if (S_ISDIR(buff.st_mode)) { | 1968 | if(partFile.isDir()) { | ||
WRONG. Here we were testing the result of stat() on the .part file, see old line 1942. Granted, reusing "buff" didn't make the code very readable.... Create a different QFileInfo instance for the .part file, and use it for bPartExists and for isDir() here. dfaure: WRONG. Here we were testing the result of stat() on the .part file, see old line 1942.
Granted… | |||||
1948 | errorCode = ERR_DIR_ALREADY_EXIST; | 1969 | errorCode = ERR_DIR_ALREADY_EXIST; | ||
1949 | return sftpProtocol::ClientError; // client side error | 1970 | return sftpProtocol::ClientError; // client side error | ||
1950 | } | 1971 | } | ||
1951 | bResume = canResume( buff.st_size ); | 1972 | bResume = canResume( copyFile.size() ); | ||
dfaure: Red alert! Red alert! Uninitialized data being used! | |||||
1952 | } | 1973 | } | ||
1953 | 1974 | | |||
1954 | if (bPartExists && !bResume) // get rid of an unwanted ".part" file | 1975 | if (bPartExists && !bResume) // get rid of an unwanted ".part" file | ||
1955 | QFile::remove(sPart); | 1976 | QFile::remove(sPart); | ||
1956 | 1977 | | |||
1957 | // WABA: Make sure that we keep writing permissions ourselves, | 1978 | // WABA: Make sure that we keep writing permissions ourselves, | ||
1958 | // otherwise we can be in for a surprise on NFS. | 1979 | // otherwise we can be in for a surprise on NFS. | ||
1959 | mode_t initialMode; | 1980 | mode_t initialMode; | ||
1960 | if (permissions != -1) | 1981 | if (permissions != -1) | ||
1982 | #ifdef Q_OS_WIN | ||||
1983 | initialMode = permissions | static_cast<mode_t>(perms::owner_write); | ||||
vonreth: cast | |||||
1984 | #else | ||||
1961 | initialMode = permissions | S_IWUSR; | 1985 | initialMode = permissions | S_IWUSR; | ||
1986 | #endif | ||||
1962 | else | 1987 | else | ||
1963 | initialMode = 0666; | 1988 | initialMode = 0666; | ||
1964 | 1989 | | |||
1965 | // open the output file ... | 1990 | // open the output file ... | ||
1966 | int fd = -1; | 1991 | int fd = -1; | ||
1967 | KIO::fileoffset_t offset = 0; | 1992 | KIO::fileoffset_t offset = 0; | ||
1968 | if (bResume) { | 1993 | if (bResume) { | ||
1969 | fd = QT_OPEN( QFile::encodeName(sPart), O_RDWR ); // append if resuming | 1994 | fd = QT_OPEN( QFile::encodeName(sPart), O_RDWR ); // append if resuming | ||
Show All 29 Lines | 2023 | if ( !QFile::rename( QFile::encodeName(sPart), sCopyFile ) ) { | |||
1999 | // If rename fails, try removing the destination first if it exists. | 2024 | // If rename fails, try removing the destination first if it exists. | ||
2000 | if (!bDestExists || !QFile::remove(sCopyFile) || !QFile::rename(sPart, sCopyFile)) { | 2025 | if (!bDestExists || !QFile::remove(sCopyFile) || !QFile::rename(sPart, sCopyFile)) { | ||
2001 | qCDebug(KIO_SFTP_LOG) << "cannot rename " << sPart << " to " << sCopyFile; | 2026 | qCDebug(KIO_SFTP_LOG) << "cannot rename " << sPart << " to " << sCopyFile; | ||
2002 | errorCode = ERR_CANNOT_RENAME_PARTIAL; | 2027 | errorCode = ERR_CANNOT_RENAME_PARTIAL; | ||
2003 | result = sftpProtocol::ClientError; | 2028 | result = sftpProtocol::ClientError; | ||
2004 | } | 2029 | } | ||
2005 | } | 2030 | } | ||
2006 | } | 2031 | } | ||
2007 | else if (QT_STAT( QFile::encodeName(sPart), &buff ) == 0) { // should a very small ".part" be deleted? | 2032 | else if (partFile.exists()) { // should a very small ".part" be deleted? | ||
At this point we were doing another stat() in order to see how big the part file is *after* sftpGet. You need to call QFileInfo::refresh() first. dfaure: At this point we were doing another stat() in order to see how big the part file is *after*… | |||||
Better not do refresh on success, it slows things down for no purpose. else { partFile.refresh(); const int size = ...; if (partFile.exists() && partFile.size() < size) { partFile.remove(); } } dfaure: Better not do refresh on success, it slows things down for no purpose.
else {… | |||||
2008 | const int size = config()->readEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE); | 2033 | const int size = config()->readEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE); | ||
2009 | if (buff.st_size < size) | 2034 | if (partFile.size() < size) | ||
2010 | QFile::remove(sPart); | 2035 | QFile::remove(sPart); | ||
2011 | } | 2036 | } | ||
2012 | } | 2037 | } | ||
2013 | 2038 | | |||
2014 | const QString mtimeStr = metaData("modified"); | 2039 | const QString mtimeStr = metaData("modified"); | ||
2015 | if (!mtimeStr.isEmpty()) { | 2040 | if (!mtimeStr.isEmpty()) { | ||
2016 | QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate); | 2041 | QDateTime dt = QDateTime::fromString(mtimeStr, Qt::ISODate); | ||
2017 | if (dt.isValid()) { | 2042 | if (dt.isValid()) { | ||
2018 | struct utimbuf utbuf; | 2043 | QFile receivedFile(sCopyFile); | ||
2019 | utbuf.actime = buff.st_atime; // access time, unchanged | 2044 | if (receivedFile.exists()) { | ||
2020 | utbuf.modtime = dt.toTime_t(); // modification time | 2045 | if (!receivedFile.open(QIODevice::ReadWrite | QIODevice::Text)) { | ||
Why ReadWrite, if we know it doesn't exist? Does setFileTime() even need open() first? I wouldn't have thought so. dfaure: Why ReadWrite, if we know it doesn't exist?
Does setFileTime() even need open() first? I… | |||||
setFileTime() needs the file to be open. brute4s99: `setFileTime()` needs the file to be open.
Source : https://doc.qt.io/qt-5/qfiledevice. | |||||
2021 | utime(QFile::encodeName(sCopyFile), &utbuf); | 2046 | QString error_msg = receivedFile.errorString(); | ||
vonreth: well do something with the error string? | |||||
2047 | qCDebug(KIO_SFTP_LOG) << "Couldn't update modified time : " << error_msg; | ||||
no need for QStringLiteral here, sending a const char * to debug is perfectly fine; also, the qDebug must be categorized, just like all the other debug outputs pino: no need for QStringLiteral here, sending a `const char *` to debug is perfectly fine; also, the… | |||||
2048 | } | ||||
2049 | else { | ||||
dfaure: coding style: join with previous line
} else { | |||||
2050 | receivedFile.setFileTime(partFile.fileTime(QFileDevice::FileAccessTime), | ||||
dfaure: Again?? | |||||
Sorry I gave wrong advice. dfaure: Sorry I gave wrong advice.
The old code was preserving the atime just because the utime() API… | |||||
2051 | QFileDevice::FileAccessTime); | ||||
pino: what is this commented code for? | |||||
it uses buff.st_atime . Since I'm removing use of buff, I'm not sure how to handle this. For now I've commented out setting the file access time instruction for now. brute4s99: it uses buff.st_atime . Since I'm removing use of buff, I'm not sure how to handle this. For… | |||||
dfaure: Just use partFile.fileTime(QFileInfoFileAccessTime) | |||||
2052 | receivedFile.setFileTime(dt, QFileDevice::FileModificationTime); | ||||
You can remove the FileTime() type conversion, just do setFileTime(dt, QFileDevice::FileModificationTime) dfaure: You can remove the FileTime() type conversion, just do setFileTime(dt, QFileDevice… | |||||
2053 | } | ||||
2054 | } | ||||
2022 | } | 2055 | } | ||
2023 | } | 2056 | } | ||
2024 | 2057 | | |||
2025 | return result; | 2058 | return result; | ||
2026 | } | 2059 | } | ||
2027 | 2060 | | |||
2028 | sftpProtocol::StatusCode sftpProtocol::sftpCopyPut(const QUrl& url, const QString& sCopyFile, int permissions, JobFlags flags, int& errorCode) | 2061 | sftpProtocol::StatusCode sftpProtocol::sftpCopyPut(const QUrl& url, const QString& sCopyFile, int permissions, JobFlags flags, int& errorCode) | ||
2029 | { | 2062 | { | ||
2030 | qCDebug(KIO_SFTP_LOG) << sCopyFile << "->" << url << ", permissions=" << permissions << ", flags" << flags; | 2063 | qCDebug(KIO_SFTP_LOG) << sCopyFile << "->" << url << ", permissions=" << permissions << ", flags" << flags; | ||
2031 | 2064 | | |||
2032 | // check if source is ok ... | 2065 | // check if source is ok ... | ||
2033 | QT_STATBUF buff; | 2066 | QFileInfo copyFile(sCopyFile); | ||
dfaure: = info.exists() | |||||
dfaure: Same here | |||||
2034 | bool bSrcExists = (QT_STAT(QFile::encodeName(sCopyFile), &buff) != -1); | 2067 | bool bSrcExists = copyFile.exists(); | ||
2035 | | ||||
2036 | if (bSrcExists) { | 2068 | if (bSrcExists) { | ||
2037 | if (S_ISDIR(buff.st_mode)) { | 2069 | if(copyFile.isDir()) { | ||
2038 | errorCode = ERR_IS_DIRECTORY; | 2070 | errorCode = ERR_IS_DIRECTORY; | ||
2039 | return sftpProtocol::ClientError; | 2071 | return sftpProtocol::ClientError; | ||
2040 | } | 2072 | } | ||
2041 | } else { | 2073 | } else { | ||
2042 | errorCode = ERR_DOES_NOT_EXIST; | 2074 | errorCode = ERR_DOES_NOT_EXIST; | ||
2043 | return sftpProtocol::ClientError; | 2075 | return sftpProtocol::ClientError; | ||
2044 | } | 2076 | } | ||
2045 | 2077 | | |||
2046 | const int fd = QT_OPEN(QFile::encodeName(sCopyFile), O_RDONLY); | 2078 | const int fd = QT_OPEN(QFile::encodeName(sCopyFile), O_RDONLY); | ||
2047 | if(fd == -1) | 2079 | if(fd == -1) | ||
2048 | { | 2080 | { | ||
2049 | errorCode = ERR_CANNOT_OPEN_FOR_READING; | 2081 | errorCode = ERR_CANNOT_OPEN_FOR_READING; | ||
2050 | return sftpProtocol::ClientError; | 2082 | return sftpProtocol::ClientError; | ||
2051 | } | 2083 | } | ||
2052 | 2084 | | |||
2053 | totalSize(buff.st_size); | 2085 | totalSize(copyFile.size()); | ||
2054 | 2086 | | |||
2055 | // delegate the real work (errorCode gets status) ... | 2087 | // delegate the real work (errorCode gets status) ... | ||
2056 | StatusCode ret = sftpPut(url, permissions, flags, errorCode, fd); | 2088 | StatusCode ret = sftpPut(url, permissions, flags, errorCode, fd); | ||
2057 | ::close(fd); | 2089 | ::close(fd); | ||
2058 | return ret; | 2090 | return ret; | ||
2059 | } | 2091 | } | ||
2060 | 2092 | | |||
2061 | 2093 | | |||
▲ Show 20 Lines • Show All 143 Lines • ▼ Show 20 Line(s) | 2235 | } else { | |||
2205 | dirent = sb; | 2237 | dirent = sb; | ||
2206 | } | 2238 | } | ||
2207 | } | 2239 | } | ||
2208 | } | 2240 | } | ||
2209 | 2241 | | |||
2210 | if (isBrokenLink) { | 2242 | if (isBrokenLink) { | ||
2211 | // It is a link pointing to nowhere | 2243 | // It is a link pointing to nowhere | ||
2212 | fileType = S_IFMT - 1; | 2244 | fileType = S_IFMT - 1; | ||
2245 | #ifdef Q_OS_WIN | ||||
2246 | access = static_cast<mode_t>(perms::owner_all | perms::group_all | perms::others_all); | ||||
vonreth: cast | |||||
2247 | #else | ||||
2213 | access = S_IRWXU | S_IRWXG | S_IRWXO; | 2248 | access = S_IRWXU | S_IRWXG | S_IRWXO; | ||
2249 | #endif | ||||
2214 | size = 0LL; | 2250 | size = 0LL; | ||
2215 | } else { | 2251 | } else { | ||
2216 | switch (dirent->type) { | 2252 | switch (dirent->type) { | ||
2217 | case SSH_FILEXFER_TYPE_REGULAR: | 2253 | case SSH_FILEXFER_TYPE_REGULAR: | ||
2218 | fileType = S_IFREG; | 2254 | fileType = S_IFREG; | ||
2219 | break; | 2255 | break; | ||
2220 | case SSH_FILEXFER_TYPE_DIRECTORY: | 2256 | case SSH_FILEXFER_TYPE_DIRECTORY: | ||
2221 | fileType = S_IFDIR; | 2257 | fileType = S_IFDIR; | ||
2222 | break; | 2258 | break; | ||
2223 | case SSH_FILEXFER_TYPE_SYMLINK: | 2259 | case SSH_FILEXFER_TYPE_SYMLINK: | ||
2260 | #ifdef Q_OS_WIN | ||||
2261 | fileType = QT_STAT_LNK; | ||||
vonreth: QFileInfo | |||||
I'm not sure what is intended to achieve here, the remote file _can_ be a symlink, and IIRC when we had sftp on dolphin in KDE4 those symlinks were shown as such. andriusr: I'm not sure what is intended to achieve here, the remote file _can_ be a symlink, and IIRC… | |||||
I think what they mean is that if you remove the ifdef it should just work. albertvaka: I think what they mean is that if you remove the ifdef it should just work. | |||||
brute4s99: ah, gotcha! | |||||
brute4s99: `S_IFLNK` is not defined on WIndows | |||||
vonreth: Does https://code.woboq.org/qt5/qtbase/mkspecs/common/posix/qplatformdefs.h.html#111 work?
| |||||
brute4s99: yes! thanks Hannah! 🎉 | |||||
You can keep QT_STAT_LNK on every platform and remove the ifdef. That's the point of the abstraction Qt provides. For consistency, I would also change the other (S_IFDIR, etc.) to their Qt counterparts. albertvaka: You can keep QT_STAT_LNK on every platform and remove the ifdef. That's the point of the… | |||||
This is marked as Done, but it's not Done. In fact it matches my own suggestion above, so I agree with Albert ;-) dfaure: This is marked as Done, but it's not Done. In fact it matches my own suggestion above, so I… | |||||
brute4s99: so sorry, it seems I updated a previous version of the diff. | |||||
2262 | #else | ||||
2224 | fileType = S_IFLNK; | 2263 | fileType = S_IFLNK; | ||
2264 | #endif | ||||
2225 | break; | 2265 | break; | ||
2226 | case SSH_FILEXFER_TYPE_SPECIAL: | 2266 | case SSH_FILEXFER_TYPE_SPECIAL: | ||
2227 | case SSH_FILEXFER_TYPE_UNKNOWN: | 2267 | case SSH_FILEXFER_TYPE_UNKNOWN: | ||
2228 | break; | 2268 | break; | ||
2229 | } | 2269 | } | ||
2230 | 2270 | | |||
2231 | access = dirent->permissions & 07777; | 2271 | access = dirent->permissions & 07777; | ||
2232 | size = dirent->size; | 2272 | size = dirent->size; | ||
▲ Show 20 Lines • Show All 408 Lines • Show Last 20 Lines |
this builds without utime.h on my system (Arch Linux with latest Plasma, Qt and other packages), . Please inform if someone else has issues without this header.