File: kio_smb.h

package info (click to toggle)
kio-extras 4%3A25.04.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 31,928 kB
  • sloc: cpp: 28,852; ansic: 3,084; perl: 1,048; xml: 116; sh: 92; python: 28; makefile: 9
file content (284 lines) | stat: -rw-r--r-- 9,783 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/*
    SPDX-License-Identifier: GPL-2.0-or-later
    SPDX-FileCopyrightText: 2000 Caldera Systems Inc.
    SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sitter@kde.org>
    SPDX-FileContributor: Matthew Peterson <mpeterson@caldera.com>
*/

#ifndef KIO_SMB_H_INCLUDED
#define KIO_SMB_H_INCLUDED

#include <config-smb.h>

#include "smb-logsettings.h"

//--------------
// KF includes
//--------------
#include <KIO/Global>
#include <KIO/WorkerBase>

//-----------------------------
// Standard C library includes
//-----------------------------
#include <arpa/inet.h>
#include <errno.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <time.h>

//-----------------------------
// Qt includes
//-----------------------------

#include <QDateTime>
#include <QLoggingCategory>
#include <QObject>
#include <QUrl>

//-------------------------------
// Samba client library includes
//-------------------------------
extern "C" {
#include <libsmbclient.h>
}

//---------------------------
// kio_smb internal includes
//---------------------------
#include "smbauthenticator.h"
#include "smbcontext.h"
#include "smburl.h"

using namespace KIO;
class SMBWorker;

class WorkerFrontend : public SMBAbstractFrontend
{
public:
    explicit WorkerFrontend(SMBWorker &worker);
    bool checkCachedAuthentication(AuthInfo &info) override;

private:
    SMBWorker &m_worker;
};

class SMBWorker : public QObject, public KIO::WorkerBase
{
    Q_OBJECT
    friend class SMBCDiscoverer;
    friend class SMBResumeIO;
    WorkerFrontend m_frontend{*this};
    SMBContext m_context{new SMBAuthenticator(m_frontend)};
    Q_DISABLE_COPY(SMBWorker)

private:
    class SMBError
    {
    public:
        int kioErrorId;
        QString errorString;
    };

    /**
     * we store the current url, it's needed for
     * callback authorization method
     */
    SMBUrl m_current_url;

    /**
     * From Controlcenter, show SHARE$ or not
     */
    //    bool m_showHiddenShares;     //currently unused, Alex <neundorf@kde.org>

    /**
     * libsmbclient need global variables to store in,
     * else it crashes on exit next method after use cache_stat,
     * looks like gcc (C/C++) failure
     */
    struct stat st {
    };

protected:
    //---------------------------------------------
    // Authentication functions (kio_smb_auth.cpp)
    //---------------------------------------------
    // (please prefix functions with auth)

    /**
     * Description :   Initializes the libsmbclient
     * Return :        true on success false with errno set on error
     */
    bool auth_initialize_smbc();

    int checkPassword(SMBUrl &url);

    //---------------------------------------------
    // Cache functions (kio_smb_auth.cpp)
    //---------------------------------------------

    // Stat methods

    //-----------------------------------------
    // Browsing functions (kio_smb_browse.cpp)
    //-----------------------------------------
    // (please prefix functions with browse)

    /**
     * Description :  Return a stat of given SMBUrl. Calls cache_stat and
     *                pack it in UDSEntry. UDSEntry will not be cleared
     * Parameter :    SMBUrl the url to stat
     * Return :       cache_stat() return code
     */
    int browse_stat_path(const SMBUrl &url, UDSEntry &udsentry);

    /**
     * Description :  call smbc_stat and return stats of the url
     * Parameter :    SMBUrl the url to stat
     * Return :       stat* of the url
     * Note :         it has some problems with stat in method, looks like
     *                something leave(or removed) on the stack. If your
     *                method segfault on returning try to change the stat*
     *                variable
     */
    static int cache_stat(const SMBUrl &url, struct stat *st);

    //---------------------------------------------
    // Configuration functions (kio_smb_config.cpp)
    //---------------------------------------------
    // (please prefix functions with config)

    //---------------------------------------
    // Directory functions (kio_smb_dir.cpp)
    //---------------------------------------
    // (please prefix functions with dir)

    //--------------------------------------
    // File IO functions (kio_smb_file.cpp)
    //--------------------------------------
    // (please prefix functions with file)

    //----------------------------
    // Misc functions (this file)
    //----------------------------

    /**
     * Description :  correct a given URL
     *                valid URL's are
     *
     *                smb://[[domain;]user[:password]@]server[:port][/share[/path[/file]]]
     *                smb:/[[domain;]user[:password]@][group/[server[/share[/path[/file]]]]]
     *                domain   = workgroup(domain) of the user
     *                user     = username
     *                password = password of useraccount
     *                group    = workgroup(domain) of server
     *                server   = host to connect
     *                share    = a share of the server (host)
     *                path     = a path of the share
     * Parameter :    QUrl the url to check
     * Return :       new QUrl if it is corrected. else the same QUrl
     */
    QUrl checkURL(const QUrl &kurl) const;

    Q_REQUIRED_RESULT WorkerResult reportError(const SMBUrl &url, const int errNum);
    void reportWarning(const SMBUrl &url, const int errNum);

public:
    // Functions overwritten in kio_smb.cpp
    SMBWorker(const QByteArray &pool, const QByteArray &app);
    ~SMBWorker() override = default;

    // Functions overwritten in kio_smb_browse.cpp
    Q_REQUIRED_RESULT WorkerResult listDir(const QUrl &url) override;
    Q_REQUIRED_RESULT WorkerResult stat(const QUrl &url) override;

    // Functions overwritten in kio_smb_config.cpp
    void reparseConfiguration() override;

    // Functions overwritten in kio_smb_dir.cpp
    Q_REQUIRED_RESULT WorkerResult copy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags) override;
    Q_REQUIRED_RESULT WorkerResult del(const QUrl &kurl, bool isfile) override;
    Q_REQUIRED_RESULT WorkerResult mkdir(const QUrl &kurl, int permissions) override;
    Q_REQUIRED_RESULT WorkerResult rename(const QUrl &src, const QUrl &dest, KIO::JobFlags flags) override;

    // Functions overwritten in kio_smb_file.cpp
    Q_REQUIRED_RESULT WorkerResult get(const QUrl &kurl) override;
    Q_REQUIRED_RESULT WorkerResult put(const QUrl &kurl, int permissions, KIO::JobFlags flags) override;
    Q_REQUIRED_RESULT WorkerResult open(const QUrl &kurl, QIODevice::OpenMode mode) override;
    Q_REQUIRED_RESULT WorkerResult read(KIO::filesize_t bytesRequested) override;
    Q_REQUIRED_RESULT WorkerResult write(const QByteArray &fileData) override;
    Q_REQUIRED_RESULT WorkerResult seek(KIO::filesize_t offset) override;
    Q_REQUIRED_RESULT WorkerResult truncate(KIO::filesize_t size) override;
    Q_REQUIRED_RESULT WorkerResult close() override;
    Q_REQUIRED_RESULT WorkerResult fileSystemFreeSpace(const QUrl &url) override;
    Q_REQUIRED_RESULT WorkerResult special(const QByteArray &) override;

private:
    SMBError errnumToKioError(const SMBUrl &url, const int errNum);
    Q_REQUIRED_RESULT WorkerResult smbCopy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags);
    Q_REQUIRED_RESULT WorkerResult smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags);
    Q_REQUIRED_RESULT WorkerResult smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags);
    bool workaroundEEXIST(const int errNum) const;
    int statToUDSEntry(const QUrl &url, const struct stat &st, KIO::UDSEntry &udsentry);
    Q_REQUIRED_RESULT WorkerResult getACE(QDataStream &stream);
    Q_REQUIRED_RESULT WorkerResult setACE(QDataStream &stream);

    /**
     * Used in open(), read(), write(), and close()
     * FIXME Placing these in the private section above causes m_openUrl = kurl
     * to fail in SMBWorker::open. Need to find out why this is.
     */
    int m_openFd;
    SMBUrl m_openUrl;

    const bool m_enableEEXISTWorkaround; /* Enables a workaround for some broken libsmbclient versions */
    // Close without calling finish(). Use this to close after error.
    void closeWithoutFinish();

    // Apply mtime if modified metadata is set. This callsback with a utbuf
    // with modtime accordingly set. The callback should implement the actual apply.
    template<typename UTimeFunction>
    void applyMTime(UTimeFunction &&callback)
    {
        const QString mtimeStr = metaData("modified");
        if (mtimeStr.isEmpty()) {
            return;
        }
        qCDebug(KIO_SMB_LOG) << "modified:" << mtimeStr;

        const QDateTime dateTime = QDateTime::fromString(mtimeStr, Qt::ISODate);
        if (dateTime.isValid()) {
            struct utimbuf utbuf {
            };
            utbuf.modtime = dateTime.toSecsSinceEpoch(); // modification time
            callback(utbuf);
        }
    }

    void applyMTimeSMBC(const SMBUrl &url)
    {
#ifdef HAVE_UTIME_H // smbc_utime is conditional inside the libsmb headers
        applyMTime([url](struct utimbuf utbuf) {
            struct stat st {
            };
            if (cache_stat(url, &st) == 0) {
                utbuf.actime = st.st_atime; // access time, unchanged
                smbc_utime(url.toSmbcUrl(), &utbuf);
            }
        });
#endif
    }
};

//===========================================================================
// Main worker entrypoint (see kio_smb.cpp)
extern "C" {
int kdemain(int argc, char **argv);
}

#endif // #endif KIO_SMB_H_INCLUDED