92 lines
2.7 KiB
C++
92 lines
2.7 KiB
C++
/*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*
|
|
* NineP — a minimal, synchronous 9P2000 client over a Unix-domain socket.
|
|
*
|
|
* Just enough protocol to talk to a plan9port plumber: version negotiation,
|
|
* attach, walk, open, read and write. No auth (plumber accepts NOFID afid),
|
|
* no create/remove/stat. All little-endian, matching plan9port fcall.h.
|
|
*/
|
|
#ifndef OLLIE_NINEP_H
|
|
#define OLLIE_NINEP_H
|
|
|
|
#include <QByteArray>
|
|
#include <QString>
|
|
#include <cstdint>
|
|
|
|
class QLocalSocket;
|
|
|
|
/*!
|
|
* One synchronous 9P2000 session. Not thread-safe; create one per thread.
|
|
*/
|
|
class NineP
|
|
{
|
|
public:
|
|
NineP();
|
|
~NineP();
|
|
|
|
NineP(const NineP &) = delete;
|
|
NineP &operator=(const NineP &) = delete;
|
|
|
|
/*!
|
|
* Connect to \a socketPath, negotiate 9P2000, and attach as \a user.
|
|
* Returns true on success. On failure, errorString() explains why.
|
|
*/
|
|
bool connectAndAttach(const QString &socketPath, const QString &user,
|
|
const QString &aname = QString());
|
|
|
|
bool isConnected() const;
|
|
void close();
|
|
|
|
/*!
|
|
* Walk from the attached root to \a name (single path element)
|
|
* binding \a newFid to it. Returns true on success.
|
|
*/
|
|
bool walk(uint32_t newFid, const QString &name);
|
|
|
|
/*! Open \a fid with the given 9P \a mode (OREAD=0, OWRITE=1, ORDWR=2). */
|
|
bool open(uint32_t fid, uint8_t mode);
|
|
|
|
/*!
|
|
* Write \a data to \a fid at \a offset. Returns bytes accepted, or -1.
|
|
*/
|
|
int write(uint32_t fid, uint64_t offset, const QByteArray &data);
|
|
|
|
/*!
|
|
* Read up to \a count bytes from \a fid at \a offset. Returns bytes read
|
|
* (0 at EOF), or -1 on error. Blocks until server responds.
|
|
*/
|
|
int read(uint32_t fid, uint64_t offset, uint32_t count, QByteArray *out);
|
|
|
|
/*!
|
|
* Send Tread without waiting for reply. Used with recvReadReply() for
|
|
* cancellable blocking reads on edit port.
|
|
*/
|
|
bool beginRead(uint32_t fid, uint64_t offset, uint32_t count);
|
|
|
|
/*!
|
|
* Wait up to \a firstByteTimeoutMs for Rread reply. Returns byte count
|
|
* (>=0), 0 with \a timedOut set when nothing arrived, or -1 on error.
|
|
*/
|
|
int recvReadReply(QByteArray *out, int firstByteTimeoutMs, bool *timedOut);
|
|
|
|
bool clunk(uint32_t fid);
|
|
|
|
uint32_t msize() const { return m_msize; }
|
|
QString errorString() const { return m_error; }
|
|
|
|
enum OpenMode : uint8_t { OREAD = 0, OWRITE = 1, ORDWR = 2 };
|
|
static constexpr uint32_t RootFid = 0;
|
|
|
|
private:
|
|
bool sendMsg(uint8_t type, uint16_t tag, const QByteArray &body);
|
|
bool recvMsg(uint8_t *type, uint16_t *tag, QByteArray *body);
|
|
bool readExactly(char *buf, int n);
|
|
|
|
QLocalSocket *m_sock = nullptr;
|
|
uint32_t m_msize = 8192;
|
|
QString m_error;
|
|
};
|
|
|
|
#endif
|