plptools
Loading...
Searching...
No Matches
main.cc
Go to the documentation of this file.
1/*
2 * This file is part of plptools.
3 *
4 * Copyright (C) 1999-2001 Fritz Elfert <felfert@to.com>
5 * Copyright (C) 2007 Reuben Thomas <rrt@sc3d.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19 *
20 */
21
22#include "config.h"
23
24#include <bufferarray.h>
25#include <bufferstore.h>
26#include <cliutils.h>
27#include <cstdint>
28#include <drive.h>
29#include <rfsv.h>
30#include <rfsvfactory.h>
31#include <rpcs.h>
32#include <rpcsfactory.h>
33#include <tcpsocket.h>
34
35#include <iostream>
36#include <string>
37
38#include <stdlib.h>
39#include <stdio.h>
40#include <signal.h>
41#include <unistd.h>
42#include <errno.h>
43
44#include "rfsv_api.h"
45
46#ifndef _GNU_SOURCE
47#define _GNU_SOURCE
48#endif
49#include <getopt.h>
50
51#include <fuse/fuse_lowlevel.h>
52
53using namespace std;
54
55static RFSV *a;
57
58static RPCS *r;
61
62/* Translate EPOC/SIBO error to UNIX error code, leaving positive
63 numbers alone */
64int epocerr_to_errno(long epocerr) {
65 int unixerr = (int)epocerr;
66
67 if (epocerr < 0) {
68 switch (epocerr) {
70 unixerr = 0;
71 break;
73 unixerr = -EEXIST;
74 break;
77 unixerr = -ENOENT;
78 break;
81 case RFSV::E_PSI_FILE_EOF: // Can't err = EOF as it's not an error code
82 case RFSV::E_PSI_FILE_ALLOC: // FIXME: No idea what this is
85 unixerr = -EPERM;
86 break;
88 unixerr = -ENOSPC;
89 break;
93 unixerr = -EINVAL;
94 break;
99 unixerr = -EACCES;
100 break;
105 unixerr = -EBUSY;
106 break;
121 default:
122 unixerr = -EIO;
123 break;
125 unixerr = -EINTR;
126 break;
129 unixerr = -ENODEV;
130 break;
132 unixerr = -EFBIG;
133 break;
135 unixerr = -EBADF;
136 break;
137 }
138 }
139
140 debuglog("EPOC error %ld became UNIX code %d", epocerr, unixerr);
141 return unixerr;
142}
143
144int rfsv_isalive(void) {
145 if (!a) {
146 if (!(a = rf->create(true)))
147 return 0;
148 }
149 return a->getStatus() == RFSV::E_PSI_GEN_NONE;
150}
151
152int rfsv_dir(const char *file, dentry **e) {
153 PlpDir entries;
154 dentry *tmp;
155 long ret;
156
157 if (!a)
158 return -ENODEV;
159 ret = a->dir(file, entries);
160
161 for (int i = 0; i < entries.size(); i++) {
162 PlpDirent pe = entries[i];
163 tmp = *e;
164 *e = (dentry *)calloc(1, sizeof(dentry));
165 if (!*e)
166 return -ENODEV;
167 (*e)->time = pe.getPsiTime().getTime();
168 (*e)->size = pe.getSize();
169 (*e)->attr = pe.getAttr();
170 (*e)->name = strdup(pe.getName());
171 (*e)->next = tmp;
172 }
173 return epocerr_to_errno(ret);
174}
175
176int rfsv_dircount(const char *file, uint32_t *count) {
177 if (!a)
178 return -ENODEV;
179 return epocerr_to_errno(a->dircount(file, *count));
180}
181
182int rfsv_rmdir(const char *name) {
183 if (!a)
184 return -ENODEV;
185 return epocerr_to_errno(a->rmdir(name));
186}
187
188int rfsv_mkdir(const char *file) {
189 if (!a)
190 return -ENODEV;
191 return epocerr_to_errno(a->mkdir(file));
192}
193
194int rfsv_remove(const char *file) {
195 if (!a)
196 return -ENODEV;
197 return epocerr_to_errno(a->remove(file));
198}
199
200int rfsv_fclose(long handle) {
201 if (!a)
202 return -ENODEV;
203 return epocerr_to_errno(a->fclose(handle));
204}
205
206int rfsv_fcreate(long attr, const char *file, uint32_t *handle) {
207 uint32_t ph;
208 long ret;
209
210 if (!a)
211 return -ENODEV;
212 ret = a->fcreatefile(attr, file, ph);
213 *handle = ph;
214 return epocerr_to_errno(ret);
215}
216
217int rfsv_open(const char *name, long mode, uint32_t *handle) {
218 long ret, retry;
219
220 if (!a)
221 return -ENODEV;
222 if (mode == O_RDONLY)
223 mode = RFSV::PSI_O_RDONLY;
224 else
225 mode = RFSV::PSI_O_RDWR;
226 for (retry = 100; retry > 0 && (ret = a->fopen(a->opMode(mode), name, *handle)) != RFSV::E_PSI_GEN_NONE; retry--)
227 usleep(20000);
228 return epocerr_to_errno(ret);
229}
230
231int rfsv_read(char *buf, long offset, long len, const char *name) {
232 uint32_t ret = 0, r_offset, handle;
233
234 if (!a)
235 return -ENODEV;
236 if ((ret = rfsv_open(name, O_RDONLY, &handle)))
237 return ret;
238 if (a->fseek(handle, offset, RFSV::PSI_SEEK_SET, r_offset) != RFSV::E_PSI_GEN_NONE ||
239 offset != r_offset ||
240 a->fread(handle, (unsigned char *)buf, len, ret) != RFSV::E_PSI_GEN_NONE)
241 ret = -1;
242 rfsv_fclose(handle);
243 return epocerr_to_errno(ret);
244}
245
246int rfsv_write(const char *buf, long offset, long len, const char *name) {
247 uint32_t ret = 0, r_offset, handle;
248
249 if (!a)
250 return -ENODEV;
251 if ((ret = rfsv_open(name, O_RDWR, &handle)))
252 return ret;
253 if (a->fseek(handle, offset, RFSV::PSI_SEEK_SET, r_offset) != RFSV::E_PSI_GEN_NONE ||
254 offset != r_offset ||
255 a->fwrite(handle, (unsigned char *)buf, len, ret) != RFSV::E_PSI_GEN_NONE)
256 ret = -1;
257 rfsv_fclose(handle);
258 return epocerr_to_errno(ret);
259}
260
261int rfsv_setmtime(const char *name, long time) {
262 if (!a)
263 return -ENODEV;
264 return epocerr_to_errno(a->fsetmtime(name, PsiTime(time)));
265}
266
267int rfsv_setsize(const char *name, long size) {
268 uint32_t ph;
269 long ret;
270
271 if (!a)
272 return -ENODEV;
273 ret = a->fopen(a->opMode(RFSV::PSI_O_RDWR), name, ph);
274 if (!ret) {
275 ret = a->fsetsize(ph, size);
276 a->fclose(ph);
277 }
278 return epocerr_to_errno(ret);
279}
280
281int rfsv_setattr(const char *name, long sattr, long dattr) {
282 if (!a)
283 return -ENODEV;
284 return epocerr_to_errno(a->fsetattr(name, sattr, dattr));
285}
286
287int rfsv_getattr(const char *name, long *attr, long *size, long *time) {
288 long res;
289 PlpDirent e;
290
291 if (!a)
292 return -ENODEV;
293 res = a->fgeteattr(name, e);
294 *attr = e.getAttr();
295 *size = e.getSize();
296 *time = e.getPsiTime().getTime();
297 return epocerr_to_errno(res);
298}
299
300int rfsv_rename(const char *oldname, const char *newname) {
301 if (!a)
302 return -ENODEV;
303 return epocerr_to_errno(a->rename(oldname, newname));
304}
305
306int rfsv_drivelist(int *cnt, device **dlist) {
307 *dlist = NULL;
308 uint32_t devbits;
309 long ret;
310 int i;
311
312 if (!a)
313 return -ENODEV;
314 ret = a->devlist(devbits);
315 if (ret == 0)
316 for (i = 0; i < 26; i++) {
317 Drive drive;
318
319 if ((devbits & 1) &&
320 ((a->devinfo(i + 'A', drive) == RFSV::E_PSI_GEN_NONE))) {
321
322 device *next = *dlist;
323 *dlist = (device *)malloc(sizeof(device));
324 (*dlist)->next = next;
325 (*dlist)->name = strdup(drive.getName().c_str());
326 (*dlist)->total = drive.getSize();
327 (*dlist)->free = drive.getSpace();
328 (*dlist)->letter = 'A' + i;
329 (*dlist)->attrib = static_cast<uint32_t>(drive.getMediaType());
330 (*cnt)++;
331 }
332 devbits >>= 1;
333 }
334 return epocerr_to_errno(ret);
335}
336
337static void
339{
340 cerr << _(
341 "Usage: plpfuse [OPTION...] MOUNTPOINT\n"
342 "\n"
343 "plpfuse options:\n"
344 "\n"
345 " -d, --debug Increase debugging level\n"
346 " -h, --help Display this text\n"
347 " -V, --version Print version and exit\n"
348 " -p, --port=[HOST:]PORT Connect to port PORT on host HOST\n"
349 " Default for HOST is 127.0.0.1\n"
350 " Default for PORT is "
351 ) << DPORT << "\n\n";
352}
353
354static struct option opts[] = {
355 {"help", no_argument, nullptr, 'h'},
356 {"debug", no_argument, nullptr, 'd'},
357 {"version", no_argument, nullptr, 'V'},
358 {"port", required_argument, nullptr, 'p'},
359 {nullptr, 0, nullptr, 0 }
360};
361
362int fuse(int argc, char *argv[])
363{
364 struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
365 struct fuse_chan *ch;
366 char *mountpoint;
367 int err = -1, foreground;
368
369 if (fuse_parse_cmdline(&args, &mountpoint, NULL, &foreground) != -1 &&
370 (ch = fuse_mount(mountpoint, &args)) != NULL) {
371 if (fuse_daemonize(foreground) != -1) {
372 struct fuse *fp = fuse_new(ch, &args, &plp_oper, sizeof(plp_oper), NULL);
373 if (fp != NULL)
374 err = fuse_loop(fp);
375 }
376 fuse_unmount(mountpoint, ch);
377 }
378 fuse_opt_free_args(&args);
379
380 return err ? 1 : 0;
381}
382
383int main(int argc, char**argv) {
384 string host = "127.0.0.1";
385 int sockNum = DPORT, i, c, oldoptind = 1;
386
388
389 /* N.B. Option handling is kludged. Most of the options are shared
390 with FUSE, except for -p/--port, which has to be removed from
391 argv so that FUSE doesn't see it. Hence, we don't complain
392 about unknown options, but leave that to FUSE, and similarly we
393 don't quit after issuing a version or help message. */
394 opterr = 0; // Suppress errors from unknown options
395 while ((c = getopt_long(argc, argv, "hVp:d", opts, NULL)) != -1) {
396 switch (c) {
397 case 'V':
398 cout << _("plpfuse version ") << VERSION << endl;
399 return 0;
400 case 'h':
401 help();
402 return 0;
403 case 'd':
404 debug++;
405 break;
406 case 'p':
407 if (!cli_utils::parse_port(optarg, &host, &sockNum)) {
408 cout << _("Invalid port definition.") << endl;
409 return 1;
410 }
411 argc -= optind - oldoptind;
412 for (i = oldoptind; i < argc; i++)
413 argv[i] = argv[i + (optind - oldoptind)];
414 break;
415 }
416 if (optind >= argc)
417 break;
418 }
419
420 rf = new RFSVFactory(host.c_str(), sockNum);
421 rp = new RPCSFactory(host.c_str(), sockNum);
422 a = rf->create(true);
423 r = rp->create(true);
424 if (a != NULL && r != NULL)
425 debuglog("plpfuse: connected");
426 else
427 debuglog("plpfuse: could not create rfsv or RPCS object, connect delayed");
428 return fuse(argc, argv);
429}
A generic container for an array of bytes.
Definition: bufferstore.h:36
A class representing information about a Disk drive on the psion.
Definition: drive.h:51
MediaType getMediaType() const
Retrieve the media type of the drive.
Definition: drive.cc:82
uint64_t getSpace() const
Retrieve the free capacity on the drive.
Definition: drive.cc:102
uint64_t getSize() const
Retrieve the total capacity of the drive.
Definition: drive.cc:98
std::string getName() const
Retrieve the volume name of the drive.
Definition: drive.cc:106
A class, representing a directory entry of the Psion.
Definition: plpdirent.h:79
uint32_t getAttr() const
Retrieves the file attributes of a directory entry.
Definition: plpdirent.cc:75
const char * getName() const
Retrieve the file name of a directory entry.
Definition: plpdirent.cc:102
PsiTime getPsiTime()
Retrieve the modification time of a directory entry.
Definition: plpdirent.cc:106
uint32_t getSize() const
Retrieves the file size of a directory entry.
Definition: plpdirent.cc:71
Psion time related utility class.
Definition: psitime.h:124
time_t getTime(void)
Retrieves the instance's current value in Unix time format.
Definition: psitime.cc:132
A factory for automatically instantiating the correct RFSV protocol variant depending on the connecte...
Definition: rfsvfactory.h:36
RFSV * create(bool, Enum< ConnectionError > *error=nullptr)
Creates a new RFSV instance.
Definition: rfsvfactory.cc:36
Access remote file services of a Psion.
Definition: rfsv.h:79
virtual Enum< errs > fsetsize(const uint32_t handle, const uint32_t size)=0
Resizes an open file on the Psion.
@ PSI_O_RDWR
Definition: rfsv.h:96
@ PSI_O_RDONLY
Definition: rfsv.h:94
virtual Enum< errs > fwrite(const uint32_t handle, const unsigned char *const buffer, const uint32_t len, uint32_t &count)=0
Write to a file on the Psion.
virtual uint32_t opMode(const uint32_t mode)=0
Converts an open-mode (A combination of the PSI_O_ constants.) from generic representation to the mac...
virtual Enum< errs > remove(const char *const name)=0
Removes a file on the Psion.
virtual Enum< errs > fseek(const uint32_t handle, const int32_t offset, const uint32_t mode, uint32_t &resultpos)=0
Sets the current file position of a file on the Psion.
virtual Enum< errs > fopen(const uint32_t attr, const char *const name, uint32_t &handle)=0
Opens a file.
virtual Enum< errs > fread(const uint32_t handle, unsigned char *const buffer, const uint32_t len, uint32_t &count)=0
Reads from a file on the Psion.
virtual Enum< errs > fsetattr(const char *const name, const uint32_t seta, const uint32_t unseta)=0
virtual Enum< errs > fgeteattr(const char *const name, PlpDirent &e)=0
Retrieves attributes, size and modification time of a file on the Psion.
virtual Enum< errs > fcreatefile(const uint32_t attr, const char *const name, uint32_t &handle)=0
Creates a named file.
virtual Enum< errs > fsetmtime(const char *const name, const PsiTime mtime)=0
Sets the modification time of a file on the Psion.
@ PSI_SEEK_SET
Definition: rfsv.h:85
virtual Enum< errs > mkdir(const char *const name)=0
Creates a directory on the Psion.
virtual Enum< errs > fclose(const uint32_t handle)=0
Close a file on the Psion whih was previously opened/created by using fopen , fcreatefile ,...
Enum< errs > getStatus()
Retrieves the current connection status.
Definition: rfsv.cc:145
virtual Enum< errs > dir(const char *const name, PlpDir &ret)=0
Reads a directory on the Psion.
virtual Enum< errs > dircount(const char *const name, uint32_t &count)=0
Counts number of entries in a directory.
virtual Enum< errs > rmdir(const char *const name)=0
Removes a directory on the Psion.
virtual Enum< errs > devlist(uint32_t &devbits)=0
Retrieves available drives on the Psion.
virtual Enum< errs > devinfo(const char drive, Drive &dinfo)=0
Retrieves details about a drive.
virtual Enum< errs > rename(const char *const oldname, const char *const newname)=0
Renames a file on the Psion.
@ E_PSI_FILE_TOOBIG
Definition: rfsv.h:177
@ E_PSI_FILE_PENDING
Definition: rfsv.h:152
@ E_PSI_FILE_ERASE
Definition: rfsv.h:174
@ E_PSI_FILE_ACCESS
Definition: rfsv.h:145
@ E_PSI_FILE_RDONLY
Definition: rfsv.h:150
@ E_PSI_FILE_ALLOC
Definition: rfsv.h:155
@ E_PSI_FILE_DIR
Definition: rfsv.h:148
@ E_PSI_FILE_WRITE
Definition: rfsv.h:140
@ E_PSI_GEN_INUSE
Definition: rfsv.h:123
@ E_PSI_FILE_RETRAN
Definition: rfsv.h:158
@ E_PSI_FILE_INACT
Definition: rfsv.h:160
@ E_PSI_FILE_FULL
Definition: rfsv.h:143
@ E_PSI_FILE_NDISC
Definition: rfsv.h:180
@ E_PSI_FILE_EXIST
Definition: rfsv.h:138
@ E_PSI_FILE_VOLUME
Definition: rfsv.h:153
@ E_PSI_FILE_DEVICE
Definition: rfsv.h:147
@ E_PSI_FILE_CONNECT
Definition: rfsv.h:157
@ E_PSI_FILE_CORRUPT
Definition: rfsv.h:172
@ E_PSI_FILE_DISC
Definition: rfsv.h:156
@ E_PSI_FILE_CANCEL
Definition: rfsv.h:154
@ E_PSI_FILE_HANDLE
Definition: rfsv.h:186
@ E_PSI_FILE_NXIST
Definition: rfsv.h:139
@ E_PSI_FILE_READ
Definition: rfsv.h:141
@ E_PSI_FILE_RECORD
Definition: rfsv.h:149
@ E_PSI_FILE_NOTREADY
Definition: rfsv.h:168
@ E_PSI_FILE_LINE
Definition: rfsv.h:159
@ E_PSI_FILE_OVERRUN
Definition: rfsv.h:163
@ E_PSI_FILE_PARITY
Definition: rfsv.h:161
@ E_PSI_FILE_INV
Definition: rfsv.h:151
@ E_PSI_FILE_FRAME
Definition: rfsv.h:162
@ E_PSI_FILE_NAME
Definition: rfsv.h:144
@ E_PSI_GEN_NONE
Definition: rfsv.h:114
@ E_PSI_FILE_ABORT
Definition: rfsv.h:173
@ E_PSI_FILE_LOCKED
Definition: rfsv.h:146
@ E_PSI_FILE_PROTECT
Definition: rfsv.h:171
@ E_PSI_FILE_DIRFULL
Definition: rfsv.h:170
@ E_PSI_FILE_COMPLETION
Definition: rfsv.h:182
@ E_PSI_FILE_DRIVER
Definition: rfsv.h:181
@ E_PSI_FILE_INVALID
Definition: rfsv.h:175
@ E_PSI_FILE_EOF
Definition: rfsv.h:142
@ E_PSI_FILE_UNKNOWN
Definition: rfsv.h:169
A factory for automatically instantiating the correct protocol variant depending on the connected Psi...
Definition: rpcsfactory.h:33
RPCS * create(bool, Enum< ConnectionError > *error=nullptr)
Creates a new RPCS instance.
Definition: rpcsfactory.cc:39
Remote procedure call services via PLP.
Definition: rpcs.h:52
void debuglog(const char *fmt,...)
Definition: fuse.c:50
struct fuse_operations plp_oper
Definition: fuse.c:581
int debug
Definition: fuse.c:47
bool parse_port(const std::string &arg, std::string *host, int *port)
Definition: cliutils.cc:53
int lookup_default_port()
Definition: cliutils.cc:44
Definition: doctest.h:522
int rfsv_rmdir(const char *name)
Definition: main.cc:182
int rfsv_dir(const char *file, dentry **e)
Definition: main.cc:152
static BufferStore owner
Definition: main.cc:60
int rfsv_drivelist(int *cnt, device **dlist)
Definition: main.cc:306
int epocerr_to_errno(long epocerr)
Definition: main.cc:64
int rfsv_open(const char *name, long mode, uint32_t *handle)
Definition: main.cc:217
int rfsv_mkdir(const char *file)
Definition: main.cc:188
int rfsv_getattr(const char *name, long *attr, long *size, long *time)
Definition: main.cc:287
int main(int argc, char **argv)
Definition: main.cc:383
int rfsv_dircount(const char *file, uint32_t *count)
Definition: main.cc:176
int rfsv_remove(const char *file)
Definition: main.cc:194
static struct option opts[]
Definition: main.cc:354
static RFSVFactory * rf
Definition: main.cc:56
int rfsv_setmtime(const char *name, long time)
Definition: main.cc:261
int rfsv_write(const char *buf, long offset, long len, const char *name)
Definition: main.cc:246
int rfsv_fcreate(long attr, const char *file, uint32_t *handle)
Definition: main.cc:206
int rfsv_setattr(const char *name, long sattr, long dattr)
Definition: main.cc:281
static RPCS * r
Definition: main.cc:58
int rfsv_fclose(long handle)
Definition: main.cc:200
static void help()
Definition: main.cc:338
static RFSV * a
Definition: main.cc:55
int rfsv_rename(const char *oldname, const char *newname)
Definition: main.cc:300
static RPCSFactory * rp
Definition: main.cc:59
int rfsv_isalive(void)
Definition: main.cc:144
int rfsv_setsize(const char *name, long size)
Definition: main.cc:267
int fuse(int argc, char *argv[])
Definition: main.cc:362
int rfsv_read(char *buf, long offset, long len, const char *name)
Definition: main.cc:231
#define _(String)
Definition: plpintl.h:34
std::deque< class PlpDirent > PlpDir
Definition: rfsv.h:34
long time
Definition: plpfuse.h:48
Description of a Psion-Device.
Definition: plpfuse.h:33
char * name
Definition: plpfuse.h:34
struct p_device * next
Definition: plpfuse.h:39