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