plptools
Loading...
Searching...
No Matches
rfsv16.cc
Go to the documentation of this file.
1/*
2 * This file is part of plptools.
3 *
4 * Copyright (C) 1999 Philip Proudman <philip.proudman@btinternet.com>
5 * Copyright (C) 1999 Matt J. Gumbley <matt@gumbley.demon.co.uk>
6 * Copyright (C) 1999-2002 Fritz Elfert <felfert@to.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * along with this program; if not, see <https://www.gnu.org/licenses/>.
20 *
21 */
22#include "config.h"
23
24#include "rfsv16.h"
25#include "bufferstore.h"
26#include "tcpsocket.h"
27#include "bufferarray.h"
28
29#include <algorithm>
30#include <iostream>
31#include <fstream>
32
33#include <stdlib.h>
34#include <time.h>
35
36#include "ignore-value.h"
37
38#define RFSV16_MAXDATALEN 852 // 640
39
40using namespace std;
41
43{
44 serNum = 0;
46 skt = _skt;
47 reset();
48}
49
51fopen(uint32_t attr, const char *name, uint32_t &handle)
52{
54 string realName = convertSlash(name);
55
56 // Allow random access, rather than forcing the caller to ask for it
57 a.addWord((P_FRANDOM | attr) & 0xFFFF);
58 a.addStringT(realName.c_str());
60 return E_PSI_FILE_DISC;
61
63 if (res == 0) {
64 handle = (long)a.getWord(0);
65 return E_PSI_GEN_NONE;
66 }
67 return res;
68}
69
71mktemp(uint32_t &handle, string &tmpname)
72{
74
75 a.addWord(P_FUNIQUE);
76 a.addStringT("TMP");
78 return E_PSI_FILE_DISC;
79
81 if (res == E_PSI_GEN_NONE) {
82 handle = a.getWord(0);
83 tmpname = a.getString(2);
84 return res;
85 }
86 return res;
87}
88
90fcreatefile(uint32_t attr, const char *name, uint32_t &handle)
91{
92 return fopen(attr | P_FCREATE, name, handle);
93}
94
96freplacefile(uint32_t attr, const char *name, uint32_t &handle)
97{
98 return fopen(attr | P_FREPLACE, name, handle);
99}
100
102fopendir(const char * const name, uint32_t &handle)
103{
104 return fopen(P_FDIR, name, handle);
105}
106
108fclose(uint32_t fileHandle)
109{
111 a.addWord(fileHandle & 0xFFFF);
113 return E_PSI_FILE_DISC;
114 return getResponse(a);
115}
116
118opendir(const uint32_t attr, const char *name, rfsvDirhandle &dH) {
119 uint32_t handle;
120 Enum<rfsv::errs> res = fopendir(name, handle);
121 dH.h = handle;
122 dH.b.init();
123 return res;
124}
125
128 return fclose(dH.h);
129}
130
134
135 if (dH.b.getLen() < 17) {
136 dH.b.init();
137 dH.b.addWord(dH.h & 0xFFFF);
138 if (!sendCommand(SIBO_FDIRREAD, dH.b))
139 return E_PSI_FILE_DISC;
140 res = getResponse(dH.b);
141 if (res == E_PSI_GEN_NONE) {
142 uint16_t bufferLen = dH.b.getWord(0);
143 dH.b.discardFirstBytes(2);
144 if (dH.b.getLen() != bufferLen)
145 return E_PSI_GEN_FAIL;
146 }
147 }
148 if ((res == E_PSI_GEN_NONE) && (dH.b.getLen() > 16)) {
149 uint16_t version = dH.b.getWord(0);
150 if (version != 2)
151 return E_PSI_GEN_FAIL;
152 e.attr = attr2std((uint32_t)dH.b.getWord(2));
153 e.size = dH.b.getDWord(4);
154 e.time.setSiboTime(dH.b.getDWord(8));
155 e.name = dH.b.getString(16);
156 //e.UID = PlpUID(0,0,0);
157 e.attrstr = attr2String(e.attr);
158
159 dH.b.discardFirstBytes(17 + e.name.length());
160
161 }
162 return res;
163}
164
166dir(const char *name, PlpDir &files)
167{
169 files.clear();
171 while (res == E_PSI_GEN_NONE) {
172 PlpDirent e;
173 res = readdir(h, e);
174 if (res == E_PSI_GEN_NONE)
175 files.push_back(e);
176 }
177 closedir(h);
178 if (res == E_PSI_FILE_EOF)
179 res = E_PSI_GEN_NONE;
180 return res;
181}
182
183uint32_t rfsv16::
184opMode(uint32_t mode)
185{
186 uint32_t ret = 0;
187
188 ret |= ((mode & 03) == PSI_O_RDONLY) ? 0 : P_FUPDATE;
189 ret |= (mode & PSI_O_TRUNC) ? P_FREPLACE : 0;
190 ret |= (mode & PSI_O_CREAT) ? P_FCREATE : 0;
191 ret |= (mode & PSI_O_APPEND) ? P_FAPPEND : 0;
192 if ((mode & 03) == PSI_O_RDONLY)
193 ret |= (mode & PSI_O_EXCL) ? 0 : P_FSHARE;
194 return ret;
195}
196
198fgetmtime(const char * const name, PsiTime &mtime)
199{
201 string realName = convertSlash(name);
202 a.addStringT(realName.c_str());
203 if (!sendCommand(SIBO_FINFO, a))
204 return E_PSI_FILE_DISC;
205
207 if (res != E_PSI_GEN_NONE)
208 return res;
209 else if (a.getLen() == 16) {
210 // According to Alex's docs, Psion's file times are in
211 // seconds since 13:00!!, 1.1.1970
212 mtime.setSiboTime(a.getDWord(8));
213 return res;
214 }
215 return E_PSI_GEN_FAIL;
216}
217
219fsetmtime(const char *name, PsiTime mtime)
220{
221 // According to Alexander's protocol doc, SIBO_SFDATE sets the modification
222 // time - and as far as I can see SIBO only keeps a modification
223 // time. So call SIBO_SFDATE here.
225 string realName = convertSlash(name);
226 // According to Alex's docs, Psion's file times are in
227 // seconds since 13:00!!, 1.1.1970
228 a.addDWord(mtime.getSiboTime());
229 a.addStringT(realName.c_str());
231 return E_PSI_FILE_DISC;
232 return getResponse(a);
233}
234
236fgetattr(const char * const name, uint32_t &attr)
237{
239 string realName = convertSlash(name);
240 a.addStringT(realName.c_str());
241 if (!sendCommand(SIBO_FINFO, a))
242 return E_PSI_FILE_DISC;
243
245 if (res != E_PSI_GEN_NONE)
246 return res;
247 else if (a.getLen() == 16) {
248 attr = attr2std((long)a.getWord(2));
249 return res;
250 }
251 return E_PSI_GEN_FAIL;
252}
253
255fgeteattr(const char * const name, PlpDirent &e)
256{
258 string realName = convertSlash(name);
259 a.addStringT(realName.c_str());
260 if (!sendCommand(SIBO_FINFO, a))
261 return E_PSI_FILE_DISC;
263 if (res != E_PSI_GEN_NONE)
264 return res;
265 else if (a.getLen() == 16) {
266
267 // Get the filename.
268 const char *p = strrchr(realName.c_str(), '\\');
269 if (p) {
270 p++;
271 } else {
272 p = realName.c_str();
273 }
274
275 // Uppercase the resulting filename as, while EPOC16 is case insensitive, it returns all responses as uppercase.
276 string name = p;
277 std::transform(name.begin(), name.end(), name.begin(), ::toupper);
278
279 e.name = name;
280 e.attr = attr2std((long)a.getWord(2));
281 e.size = a.getDWord(4);
282 e.time.setSiboTime(a.getDWord(8));
283 e.UID = PlpUID(0,0,0);
284 e.attrstr = string(attr2String(e.attr));
285 return res;
286 }
287 return E_PSI_GEN_FAIL;
288}
289
291fsetattr(const char *name, uint32_t seta, uint32_t unseta)
292{
293 uint32_t statusword = std2attr(seta) & (~ std2attr(unseta));
294 statusword ^= 0x0000001; // r bit is inverted
295 uint32_t bitmask = std2attr(seta) | std2attr(unseta);
297 a.addWord(statusword & 0xFFFF);
298 a.addWord(bitmask & 0xFFFF);
299 a.addStringT(name);
301 return E_PSI_FILE_DISC;
302 return getResponse(a);
303}
304
306dircount(const char * const name, uint32_t &count)
307{
310 while (res == E_PSI_GEN_NONE) {
311 PlpDirent e;
312 res = readdir(h, e);
313 if (res == E_PSI_GEN_NONE)
314 count++;
315 }
316 closedir(h);
317 if (res == E_PSI_FILE_EOF)
318 res = E_PSI_GEN_NONE;
319 return res;
320}
321
323devlist(uint32_t &devbits)
324{
326 uint32_t fileHandle;
327 devbits = 0;
328
329 // The following is taken from a trace between a Series 3c and PsiWin.
330 // Hope it works! We SIBO_PARSE to find the correct node, then FOPEN
331 // (P_FDEVICE) this, SIBO_FDEVICEREAD each entry, setting the appropriate
332 // drive-letter-bit in devbits, then FCLOSE.
333
335 a.init();
336 a.addByte(0x00); // no Name 1
337 a.addByte(0x00); // no Name 2
338 a.addByte(0x00); // no Name 3
339 if (!sendCommand(SIBO_PARSE, a))
340 return E_PSI_FILE_DISC;
341 res = getResponse(a);
342 if (res != E_PSI_GEN_NONE)
343 return res;
344
345 // Find the drive to FOPEN
346 char name[4] = { 'x', ':', '\\', '\0' } ;
347 a.discardFirstBytes(6); // Result, fsys, dev, path, file, file, ending, flag
348 /* This leaves R E M : : M : \ */
349 name[0] = (char) a.getByte(5); // the M
350 res = fopen(P_FDEVICE, name, fileHandle);
351 if (res != E_PSI_GEN_NONE)
352 return status;
353
354 while (1) {
355 a.init();
356 a.addWord(fileHandle & 0xFFFF);
358 return E_PSI_FILE_DISC;
359 res = getResponse(a);
360 if (res)
361 break;
362 uint16_t version = a.getWord(0);
363 if ((version < 1) || (version > 2)) {
364 cerr << "devlist: not version 1 or 2" << endl;
365 fclose(fileHandle);
366 return E_PSI_GEN_FAIL;
367 }
368 char drive = a.getByte(64);
369 if (drive >= 'A' && drive <= 'Z') {
370 int shift = (drive - 'A');
371 devbits |= (long) ( 1 << shift );
372 }
373 else {
374 cerr << "devlist: non-alphabetic drive letter ("
375 << drive << ")" << endl;
376 }
377 }
378 if (res == E_PSI_FILE_EOF)
379 res = E_PSI_GEN_NONE;
380 fclose(fileHandle);
381 return res;
382}
383
384static int sibo_dattr[] = {
385 1, // Unknown
386 2, // Floppy
387 3, // Disk
388 6, // Flash
389 5, // RAM
390 7, // ROM
391 7, // write-protected == ROM ?
392};
393
395devinfo(const char drive, PlpDrive &dinfo)
396{
399
400 // Again, this is taken from an exchange between PsiWin and a 3c.
401 // For each drive, we SIBO_PARSE with its drive letter to get a response
402 // (which we ignore), then do a SIBO_STATUSDEVICE to get the info.
403
404 a.init();
405 a.addByte(toupper(drive)); // Name 1
406 a.addByte(':');
407 a.addByte(0x00);
408
409 a.addByte(0x00); // No name 2
410 a.addByte(0x00); // No name 3
411 if (!sendCommand(SIBO_PARSE, a))
412 return E_PSI_FILE_DISC;
413 if ((res = getResponse(a)) != E_PSI_GEN_NONE)
414 return res;
415
416 a.init();
417 a.addByte(toupper(drive)); // Name 1
418 a.addByte(':');
419 a.addByte('\\');
420 a.addByte(0x00);
422 return E_PSI_FILE_DISC;
423 if ((res = getResponse(a)) != E_PSI_GEN_NONE)
424 return res;
425
426 int attr = a.getWord(2);
427 attr = sibo_dattr[a.getWord(2) & 0xff];
428 dinfo.setMediaType(attr);
429
430 attr = a.getWord(2);
431 int changeable = a.getWord(4) ? 32 : 0;
432 int internal = (attr & 0x2000) ? 16 : 0;
433
434 dinfo.setDriveAttribute(changeable | internal);
435
436 int variable = (attr & 0x4000) ? 1 : 0;
437 int dualdens = (attr & 0x1000) ? 2 : 0;
438 int formattable = (attr & 0x0800) ? 4 : 0;
439 int protect = ((attr & 0xff) == 6) ? 8 : 0;
440
441 dinfo.setMediaAttribute(variable|dualdens|formattable|protect);
442
443 dinfo.setUID(0);
444 dinfo.setSize(a.getDWord(6), 0);
445 dinfo.setSpace(a.getDWord(10), 0);
446
447 dinfo.setName(toupper(drive), a.getString(14));
448
449
450 return res;
451}
452
454sendCommand(enum commands cc, bufferStore & data)
455{
456 if (status == E_PSI_FILE_DISC) {
457 reconnect();
458 if (status == E_PSI_FILE_DISC)
459 return false;
460 }
461
462 bool result;
464 a.addWord(cc);
465 a.addWord(data.getLen());
466 a.addBuff(data);
467 result = skt->sendBufferStore(a);
468 if (!result) {
469 reconnect();
470 result = skt->sendBufferStore(a);
471 if (!result)
473 }
474 return result;
475}
476
477
480{
481 // getWord(2) is the size field
482 // which is the body of the response not counting the command (002a) and
483 // the size word.
484 if (skt->getBufferStore(data) != 1) {
485 cerr << "rfsv16::getResponse: duff response. "
486 "getBufferStore failed." << endl;
487 } else if (data.getWord(0) == 0x2a &&
488 data.getWord(2) == data.getLen()-4) {
489 Enum<rfsv::errs> ret = (enum errs)(int16_t)data.getWord(4);
490 data.discardFirstBytes(6);
491 return ret;
492 } else {
493 cerr << "rfsv16::getResponse: duff response. Size field:" <<
494 data.getWord(2) << " Frame size:" <<
495 data.getLen()-4 << " Result field:" <<
496 data.getWord(4) << endl;
497 }
499 return status;
500}
501
503fread(const uint32_t handle, unsigned char * const buf, const uint32_t len, uint32_t &count)
504{
506 unsigned char *p = buf;
507 long l;
508
509 count = 0;
510 do {
512
513 // Read in blocks of 291 bytes; the maximum payload for
514 // an RFSV frame. ( As seen in traces ) - this isn't optimal:
515 // RFSV can handle fragmentation of frames, where only the
516 // first SIBO_FREAD RESPONSE frame has a RESPONSE (00 2A), SIZE
517 // and RESULT field. Every subsequent frame
518 // just has data, 297 bytes (or less) of it.
519 //
520 a.addWord(handle);
521 a.addWord((len - count) > RFSV16_MAXDATALEN
523 : (len - count));
524 if (!sendCommand(SIBO_FREAD, a))
525 return E_PSI_FILE_DISC;
526 if ((res = getResponse(a)) != E_PSI_GEN_NONE) {
527 if (res == E_PSI_FILE_EOF)
528 return E_PSI_GEN_NONE;
529 return res;
530 }
531 if ((l = a.getLen()) > 0) {
532 memcpy(p, a.getString(), l);
533 count += l;
534 p += l;
535 }
536 } while ((count < len) && (l > 0));
537 return res;
538}
539
541fwrite(const uint32_t handle, const unsigned char * const buf, const uint32_t len, uint32_t &count)
542{
544 const unsigned char *p = buf;
545
546 count = 0;
547 while (count < len) {
549 int nbytes;
550
551 // Write in blocks of 291 bytes; the maximum payload for
552 // an RFSV frame. ( As seen in traces ) - this isn't optimal:
553 // RFSV can handle fragmentation of frames, where only the
554 // first SIBO_FREAD RESPONSE frame has a RESPONSE (00 2A), SIZE
555 // and RESULT field. Every subsequent frame
556 // just has data, 297 bytes (or less) of it.
557 nbytes = (len - count) > RFSV16_MAXDATALEN
559 : (len - count);
560 a.addWord(handle);
561 a.addBytes(p, nbytes);
563 return E_PSI_FILE_DISC;
564 if ((res = getResponse(a)) != E_PSI_GEN_NONE)
565 return res;
566
567 count += nbytes;
568 p += nbytes;
569 }
570 return res;
571}
572
574copyFromPsion(const char *from, const char *to, void *ptr, cpCallback_t cb)
575{
577 uint32_t handle;
578 uint32_t len;
579 uint32_t total = 0;
580
581 if ((res = fopen(P_FSHARE | P_FSTREAM, from, handle)) != E_PSI_GEN_NONE)
582 return res;
583 ofstream op(to);
584 if (!op) {
585 fclose(handle);
586 return E_PSI_GEN_FAIL;
587 }
588 do {
589 unsigned char buf[RFSV_SENDLEN];
590 if ((res = fread(handle, buf, sizeof(buf), len)) == E_PSI_GEN_NONE) {
591 if (len > 0)
592 op.write((char *)buf, len);
593 total += len;
594 if (cb && !cb(ptr, total))
595 res = E_PSI_FILE_CANCEL;
596 }
597 } while (len > 0 && (res == E_PSI_GEN_NONE));
598
599 fclose(handle);
600 op.close();
601 if (res == E_PSI_FILE_EOF)
602 res = E_PSI_GEN_NONE;
603 return res;
604}
605
607copyFromPsion(const char *from, int fd, cpCallback_t cb)
608{
610 uint32_t handle;
611 uint32_t len;
612 uint32_t total = 0;
613
614 if ((res = fopen(P_FSHARE | P_FSTREAM, from, handle)) != E_PSI_GEN_NONE)
615 return res;
616 do {
617 unsigned char buf[RFSV_SENDLEN];
618 if ((res = fread(handle, buf, sizeof(buf), len)) == E_PSI_GEN_NONE) {
619 if (len > 0)
620 // FIXME: return UNIX errors from this method.
621 ignore_value(write(fd, buf, len));
622 total += len;
623 if (cb && !cb(NULL, total))
624 res = E_PSI_FILE_CANCEL;
625 }
626 } while (len > 0 && (res == E_PSI_GEN_NONE));
627
628 fclose(handle);
629 if (res == E_PSI_FILE_EOF)
630 res = E_PSI_GEN_NONE;
631 return res;
632}
633
635copyToPsion(const char *from, const char *to, void *ptr, cpCallback_t cb)
636{
637 uint32_t handle;
638 uint32_t len = 0;
639 uint32_t total = 0;
641
642 ifstream ip(from);
643 if (!ip)
644 return E_PSI_FILE_NXIST;
645 res = fcreatefile(P_FSTREAM | P_FUPDATE, to, handle);
646 if (res != E_PSI_GEN_NONE) {
647 res = freplacefile(P_FSTREAM | P_FUPDATE, to, handle);
648 if (res != E_PSI_GEN_NONE)
649 return res;
650 }
651 unsigned char *buff = new unsigned char[RFSV_SENDLEN];
652 while (res == E_PSI_GEN_NONE && ip && !ip.eof()) {
653 ip.read((char *)buff, RFSV_SENDLEN);
654 if ((res = fwrite(handle, buff, ip.gcount(), len)) == E_PSI_GEN_NONE) {
655 total += len;
656 if (cb && !cb(ptr, total))
657 res = E_PSI_FILE_CANCEL;
658 }
659 }
660 delete[]buff;
661 fclose(handle);
662 ip.close();
663 return res;
664}
665
667copyOnPsion(const char *from, const char *to, void *ptr, cpCallback_t cb)
668{
669 uint32_t handle_from;
670 uint32_t handle_to;
671 uint32_t len;
672 uint32_t wlen;
673 uint32_t total = 0;
675
676 if ((res = fopen(P_FSHARE | P_FSTREAM, from, handle_from)) != E_PSI_GEN_NONE)
677 return res;
678 res = fcreatefile(P_FSTREAM | P_FUPDATE, to, handle_to);
679 if (res != E_PSI_GEN_NONE) {
680 res = freplacefile(P_FSTREAM | P_FUPDATE, to, handle_to);
681 if (res != E_PSI_GEN_NONE)
682 return res;
683 }
684 do {
685 unsigned char buf[RFSV_SENDLEN];
686 if ((res = fread(handle_from, buf, sizeof(buf), len)) == E_PSI_GEN_NONE) {
687 if (len > 0) {
688 if ((res = fwrite(handle_to, buf, len, wlen)) == E_PSI_GEN_NONE) {
689 total += wlen;
690 if (cb && !cb(ptr, total))
691 res = E_PSI_FILE_CANCEL;
692 }
693 }
694 }
695 } while (len > 0 && wlen > 0 && (res == E_PSI_GEN_NONE));
696 fclose(handle_from);
697 fclose(handle_to);
698 if (res == E_PSI_FILE_EOF)
699 res = E_PSI_GEN_NONE;
700 return res;
701}
702
704pathtest(const char * const path)
705{
706 string realName = convertSlash(path);
708 a.addStringT(realName.c_str());
710 return getResponse(a);
711}
712
714fsetsize(uint32_t handle, uint32_t size)
715{
717 a.addWord(handle & 0xffff);
718 a.addDWord(size);
720 return E_PSI_FILE_DISC;
721 return getResponse(a);
722}
723
724/*
725 * Unix-like implementation off fseek with one
726 * exception: If seeking beyond eof, the gap
727 * contains garbage instead of zeroes.
728 */
730fseek(const uint32_t handle, const int32_t pos, const uint32_t mode, uint32_t &resultpos)
731{
734 uint32_t savpos = 0;
735 uint32_t realpos;
736 uint32_t calcpos = 0;
737
738/*
739 seek-parameter for psion:
740 dword position
741 dword handle
742 dword mode
743 1 = from start
744 2 = from current pos
745 3 = from end
746 ??no more?? 4 = sense recpos
747 ??no more?? 5 = set recpos
748 ??no more?? 6 = text-rewind
749*/
750
751 if ((mode < PSI_SEEK_SET) || (mode > PSI_SEEK_END))
752 return E_PSI_GEN_ARG;
753
754 if ((mode == PSI_SEEK_CUR) && (pos >= 0)) {
755 /* get and save current position */
756 a.init();
757 a.addWord(handle);
758 a.addDWord(0);
759 a.addWord(PSI_SEEK_CUR);
760 if (!sendCommand(SIBO_FSEEK, a))
761 return E_PSI_FILE_DISC;
762 if ((res = getResponse(a)) != E_PSI_GEN_NONE)
763 return res;
764 savpos = a.getDWord(0);
765 if (pos == 0) {
766 resultpos = savpos;
767 return res;
768 }
769 }
770 if ((mode == PSI_SEEK_END) && (pos >= 0)) {
771 /* get and save end position */
772 a.init();
773 a.addWord(handle);
774 a.addDWord(0);
775 a.addWord(PSI_SEEK_END);
776 if (!sendCommand(SIBO_FSEEK, a))
777 return E_PSI_FILE_DISC;
778 if ((res = getResponse(a)) != E_PSI_GEN_NONE)
779 return res;
780 savpos = a.getDWord(0);
781 if (pos == 0) {
782 resultpos = savpos;
783 return res;
784 }
785 }
786 /* Now the real seek */
787 a.addWord(handle);
788 a.addDWord(pos);
789 a.addWord(mode);
790 if (!sendCommand(SIBO_FSEEK, a))
791 return E_PSI_FILE_DISC;
792 if ((res = getResponse(a)) != 0)
793 return res;
794 realpos = a.getDWord(0);
795 switch (mode) {
796 case PSI_SEEK_SET:
797 calcpos = pos;
798 break;
799 case PSI_SEEK_CUR:
800 calcpos = savpos + pos;
801 break;
802 case PSI_SEEK_END:
803 resultpos = realpos;
804 return res;
805 break;
806 }
807 if (calcpos > realpos) {
808 /* Beyond end of file */
809 res = fsetsize(handle, calcpos);
810 if (res != E_PSI_GEN_NONE)
811 return res;
812 a.init();
813 a.addWord(handle);
814 a.addDWord(calcpos);
815 a.addWord(PSI_SEEK_SET);
816 if (!sendCommand(SIBO_FSEEK, a))
817 return E_PSI_FILE_DISC;
818 if ((res = getResponse(a)) != 0)
819 return res;
820 realpos = a.getDWord(0);
821 }
822 resultpos = realpos;
823 return res;
824}
825
827mkdir(const char* dirName)
828{
829 string realName = convertSlash(dirName);
831 a.addStringT(realName.c_str());
833 return getResponse(a);
834}
835
837rmdir(const char *dirName)
838{
839 // EPOC16 doesn't provide an RMDIR command, so we fake it using DELETE (and a few little tweaks).
840
841 // Rudimentary argument checking.
842 string path(dirName);
843 if (path.empty()) {
844 return E_PSI_FILE_NAME;
845 }
846
847 // The EPOC32 implementation of RMDIR allows for deletion of paths with or without a trailing forward slash.
848 // However, EPOC16's DELETE (which we use here) doesn't like these, so we strip them to ensure parity between the
849 // two implementations.
850 if (path.back() == '\\') {
851 path.pop_back();
852 }
853
854 // Get the path's attributes and ensure it's a directory.
855 uint32_t attr;
856 Enum<rfsv::errs> res = fgetattr(path.c_str(), attr);
857 if (res != E_PSI_GEN_NONE) {
858 return res;
859 }
860 if ((attr & PSI_A_DIR) == 0) {
861 return E_PSI_FILE_DIR;
862 }
863
864 return remove(path.c_str());
865}
866
868rename(const char *oldName, const char *newName)
869{
870 string realOldName = convertSlash(oldName);
871 string realNewName = convertSlash(newName);
873 a.addStringT(realOldName.c_str());
874 a.addStringT(realNewName.c_str());
876 return getResponse(a);
877}
878
880remove(const char* psionName)
881{
882 string realName = convertSlash(psionName);
884 a.addStringT(realName.c_str());
885 // and this needs sending in the length word.
887 return getResponse(a);
888}
889
891setVolumeName(const char drive , const char * const name)
892{
893// Not yet ...
894 return E_PSI_GEN_FAIL;
895}
896
897/*
898 * Translate SIBO attributes to standard attributes.
899 */
900uint32_t rfsv16::
901attr2std(uint32_t attr)
902{
903 uint32_t res = 0;
904
905 // Common attributes
906 if (!(attr & P_FAWRITE))
907 res |= PSI_A_RDONLY;
908 if (attr & P_FAHIDDEN)
909 res |= PSI_A_HIDDEN;
910 if (attr & P_FASYSTEM)
911 res |= PSI_A_SYSTEM;
912 if (attr & P_FADIR)
913 res |= PSI_A_DIR;
914 if (attr & P_FAMOD)
915 res |= PSI_A_ARCHIVE;
916 if (attr & P_FAVOLUME)
917 res |= PSI_A_VOLUME;
918
919 // SIBO-specific
920 if (attr & P_FAREAD)
921 res |= PSI_A_READ;
922 if (attr & P_FAEXEC)
923 res |= PSI_A_EXEC;
924 if (attr & P_FASTREAM)
925 res |= PSI_A_STREAM;
926 if (attr & P_FATEXT)
927 res |= PSI_A_TEXT;
928
929 // Do what we can for EPOC
930 res |= PSI_A_NORMAL;
931
932 return res;
933}
934
935/*
936 * Translate standard attributes to SIBO attributes.
937 */
938uint32_t rfsv16::
939std2attr(const uint32_t attr)
940{
941 uint32_t res = 0;
942
943 // Common attributes
944 if (!(attr & PSI_A_RDONLY))
945 res |= P_FAWRITE;
946 if (attr & PSI_A_HIDDEN)
947 res |= P_FAHIDDEN;
948 if (attr & PSI_A_SYSTEM)
949 res |= P_FASYSTEM;
950 if (attr & PSI_A_DIR)
951 res |= P_FADIR;
952 if (attr & PSI_A_ARCHIVE)
953 res |= P_FAMOD;
954 if (attr & PSI_A_VOLUME)
955 res |= P_FAVOLUME;
956
957 // SIBO-specific
958 if (attr & PSI_A_READ)
959 res |= P_FAREAD;
960 if (attr & PSI_A_EXEC)
961 res |= P_FAEXEC;
962 if (attr & PSI_A_STREAM)
963 res |= P_FASTREAM;
964 if (attr & PSI_A_TEXT)
965 res |= P_FATEXT;
966
967 return res;
968}
Wrapper class featuring range-checking and string representation of enumerated values.
Definition: Enum.h:136
A class, representing a directory entry of the Psion.
Definition: plpdirent.h:78
std::string attrstr
Definition: plpdirent.h:184
PsiTime time
Definition: plpdirent.h:183
std::string name
Definition: plpdirent.h:185
PlpUID UID
Definition: plpdirent.h:182
uint32_t attr
Definition: plpdirent.h:181
uint32_t size
Definition: plpdirent.h:180
A class representing information about a Disk drive on the psion.
Definition: plpdirent.h:196
void setUID(uint32_t uid)
Definition: plpdirent.cc:147
void setSpace(uint32_t spaceLo, uint32_t spaceHi)
Definition: plpdirent.cc:157
void setSize(uint32_t sizeLo, uint32_t sizeHi)
Definition: plpdirent.cc:152
void setMediaAttribute(uint32_t attr)
Definition: plpdirent.cc:142
void setName(char drive, const char *const volname)
Definition: plpdirent.cc:162
void setMediaType(uint32_t type)
Definition: plpdirent.cc:132
void setDriveAttribute(uint32_t attr)
Definition: plpdirent.cc:137
A class, representing the UIDs of a file on the Psion.
Definition: plpdirent.h:40
Psion time related utility class.
Definition: psitime.h:125
uint32_t getSiboTime()
Retrieves the instance's current value in SIBO time format.
Definition: psitime.cc:246
void setSiboTime(uint32_t stime)
Modifies the value of this instance.
Definition: psitime.cc:237
A class for dealing with sockets.
Definition: tcpsocket.h:38
int getBufferStore(bufferStore &a, bool wait=true)
Receive data into a bufferStore .
Definition: tcpsocket.cc:289
bool sendBufferStore(const bufferStore &a)
Sends data from a bufferStore .
Definition: tcpsocket.cc:325
A generic container for an array of bytes.
Definition: bufferstore.h:37
void discardFirstBytes(int len=0)
Removes bytes from the start of the buffer.
Definition: bufferstore.cc:143
void init()
Initializes the bufferStore.
Definition: bufferstore.cc:77
uint16_t getWord(long pos=0) const
Retrieves the word at index pos.
Definition: bufferstore.cc:102
const char * getString(long pos=0) const
Retrieves the characters at index pos.
Definition: bufferstore.cc:120
void addWord(int w)
Appends a word to the content of this instance.
Definition: bufferstore.cc:193
unsigned long getLen() const
Retrieves the length of a bufferStore.
Definition: bufferstore.cc:94
uint32_t getDWord(long pos=0) const
Retrieves the dword at index pos.
Definition: bufferstore.cc:106
Enum< rfsv::errs > fgetattr(const char *const, uint32_t &)
Retrieves attributes of a file on the Psion.
Definition: rfsv16.cc:236
bool sendCommand(enum commands, bufferStore &)
Definition: rfsv16.cc:454
Enum< rfsv::errs > opendir(const uint32_t, const char *const, rfsvDirhandle &)
Open a directory for reading with readdir.
Definition: rfsv16.cc:118
Enum< rfsv::errs > devinfo(const char, PlpDrive &)
Retrieves details about a drive.
Definition: rfsv16.cc:395
Enum< rfsv::errs > fread(const uint32_t, unsigned char *const, const uint32_t, uint32_t &)
Reads from a file on the Psion.
Definition: rfsv16.cc:503
Enum< rfsv::errs > pathtest(const char *const)
Checks to see if the directory component of a path or file name exists and is valid.
Definition: rfsv16.cc:704
Enum< rfsv::errs > remove(const char *const)
Removes a file on the Psion.
Definition: rfsv16.cc:880
Enum< rfsv::errs > fgeteattr(const char *const, PlpDirent &)
Retrieves attributes, size and modification time of a file on the Psion.
Definition: rfsv16.cc:255
Enum< rfsv::errs > closedir(rfsvDirhandle &)
Close a directory, previously opened with opendir.
Definition: rfsv16.cc:127
Enum< rfsv::errs > fseek(const uint32_t, const int32_t, const uint32_t, uint32_t &)
Sets the current file position of a file on the Psion.
Definition: rfsv16.cc:730
uint32_t std2attr(const uint32_t)
Definition: rfsv16.cc:939
Enum< rfsv::errs > freplacefile(const uint32_t, const char *const, uint32_t &)
Creates an named file, overwriting an existing file.
Definition: rfsv16.cc:96
Enum< rfsv::errs > copyOnPsion(const char *, const char *, void *, cpCallback_t)
Copies a file from the Psion to the Psion.
Definition: rfsv16.cc:667
uint32_t opMode(const uint32_t)
Converts an open-mode (A combination of the PSI_O_ constants.) from generic representation to the mac...
Definition: rfsv16.cc:184
Enum< rfsv::errs > devlist(uint32_t &)
Retrieves available drives on the Psion.
Definition: rfsv16.cc:323
Enum< rfsv::errs > fsetsize(const uint32_t, const uint32_t)
Resizes an open file on the Psion.
Definition: rfsv16.cc:714
uint32_t attr2std(const uint32_t)
Definition: rfsv16.cc:901
Enum< rfsv::errs > setVolumeName(const char, const char *const)
Set the name of a Psion Volume (Drive).
Definition: rfsv16.cc:891
Enum< rfsv::errs > copyFromPsion(const char *const, const char *const, void *, cpCallback_t)
Copies a file from the Psion to the local machine.
Definition: rfsv16.cc:574
@ P_FUNIQUE
Definition: rfsv16.h:109
@ P_FDIR
Definition: rfsv16.h:113
@ P_FREPLACE
Definition: rfsv16.h:107
@ P_FSTREAM
Definition: rfsv16.h:110
@ P_FAPPEND
Definition: rfsv16.h:108
@ P_FUPDATE
Definition: rfsv16.h:117
@ P_FCREATE
Definition: rfsv16.h:106
@ P_FDEVICE
Definition: rfsv16.h:115
@ P_FRANDOM
Definition: rfsv16.h:118
@ P_FSHARE
Definition: rfsv16.h:119
Enum< rfsv::errs > dircount(const char *const, uint32_t &)
Counts number of entries in a directory.
Definition: rfsv16.cc:306
Enum< rfsv::errs > fgetmtime(const char *const, PsiTime &)
Retrieves the modification time of a file on the Psion.
Definition: rfsv16.cc:198
Enum< rfsv::errs > dir(const char *const, PlpDir &)
Reads a directory on the Psion.
Definition: rfsv16.cc:166
Enum< rfsv::errs > getResponse(bufferStore &)
Definition: rfsv16.cc:479
Enum< rfsv::errs > fopendir(const char *const, uint32_t &)
Definition: rfsv16.cc:102
Enum< rfsv::errs > mktemp(uint32_t &, std::string &)
Creates a unique temporary file.
Definition: rfsv16.cc:71
commands
Definition: rfsv16.h:79
@ SIBO_FREAD
Definition: rfsv16.h:82
@ SIBO_FDIRREAD
Definition: rfsv16.h:83
@ SIBO_RENAME
Definition: rfsv16.h:89
@ SIBO_MKDIR
Definition: rfsv16.h:94
@ SIBO_PATHTEST
Definition: rfsv16.h:97
@ SIBO_PARSE
Definition: rfsv16.h:93
@ SIBO_OPENUNIQUE
Definition: rfsv16.h:95
@ SIBO_FOPEN
Definition: rfsv16.h:80
@ SIBO_FINFO
Definition: rfsv16.h:91
@ SIBO_STATUSDEVICE
Definition: rfsv16.h:96
@ SIBO_FDEVICEREAD
Definition: rfsv16.h:84
@ SIBO_DELETE
Definition: rfsv16.h:90
@ SIBO_FWRITE
Definition: rfsv16.h:85
@ SIBO_SFDATE
Definition: rfsv16.h:100
@ SIBO_FCLOSE
Definition: rfsv16.h:81
@ SIBO_FSEEK
Definition: rfsv16.h:86
@ SIBO_FSETEOF
Definition: rfsv16.h:88
@ SIBO_SFSTAT
Definition: rfsv16.h:92
Enum< rfsv::errs > fopen(const uint32_t, const char *const, uint32_t &)
Opens a file.
Definition: rfsv16.cc:51
Enum< rfsv::errs > fsetattr(const char *const, const uint32_t seta, const uint32_t unseta)
Definition: rfsv16.cc:291
Enum< rfsv::errs > fcreatefile(const uint32_t, const char *const, uint32_t &)
Creates a named file.
Definition: rfsv16.cc:90
Enum< rfsv::errs > fsetmtime(const char *const, const PsiTime)
Sets the modification time of a file on the Psion.
Definition: rfsv16.cc:219
Enum< rfsv::errs > rmdir(const char *const)
Removes a directory on the Psion.
Definition: rfsv16.cc:837
Enum< rfsv::errs > readdir(rfsvDirhandle &, PlpDirent &)
Read directory entries.
Definition: rfsv16.cc:132
Enum< rfsv::errs > fwrite(const uint32_t, const unsigned char *const, const uint32_t, uint32_t &)
Write to a file on the Psion.
Definition: rfsv16.cc:541
@ P_FAHIDDEN
Definition: rfsv16.h:124
@ P_FAREAD
Definition: rfsv16.h:129
@ P_FAMOD
Definition: rfsv16.h:128
@ P_FAWRITE
Definition: rfsv16.h:123
@ P_FASYSTEM
Definition: rfsv16.h:125
@ P_FADIR
Definition: rfsv16.h:127
@ P_FAVOLUME
Definition: rfsv16.h:126
@ P_FASTREAM
Definition: rfsv16.h:131
@ P_FAEXEC
Definition: rfsv16.h:130
@ P_FATEXT
Definition: rfsv16.h:132
Enum< rfsv::errs > fclose(const uint32_t)
Close a file on the Psion whih was previously opened/created by using fopen , fcreatefile ,...
Definition: rfsv16.cc:108
Enum< rfsv::errs > rename(const char *const, const char *const)
Renames a file on the Psion.
Definition: rfsv16.cc:868
Enum< rfsv::errs > mkdir(const char *const)
Creates a directory on the Psion.
Definition: rfsv16.cc:827
Enum< rfsv::errs > copyToPsion(const char *const, const char *const, void *, cpCallback_t)
Copies a file from local machine to the Psion.
Definition: rfsv16.cc:635
rfsv16(TCPSocket *)
Private constructor.
Definition: rfsv16.cc:42
A helper class for storing intermediate internal information in rfsv16 and rfsv32 .
Definition: rfsv.h:53
bufferStore b
Definition: rfsv.h:59
uint32_t h
Definition: rfsv.h:58
@ PSI_O_CREAT
Definition: rfsv.h:99
@ PSI_O_EXCL
Definition: rfsv.h:100
@ PSI_O_TRUNC
Definition: rfsv.h:101
@ PSI_O_APPEND
Definition: rfsv.h:102
@ PSI_SEEK_END
Definition: rfsv.h:83
@ PSI_SEEK_CUR
Definition: rfsv.h:82
@ PSI_SEEK_SET
Definition: rfsv.h:81
errs
The known error codes.
Definition: rfsv.h:109
@ E_PSI_GEN_NONE
Definition: rfsv.h:110
@ E_PSI_FILE_NXIST
Definition: rfsv.h:135
@ E_PSI_FILE_EOF
Definition: rfsv.h:138
@ E_PSI_FILE_NAME
Definition: rfsv.h:140
@ E_PSI_FILE_CANCEL
Definition: rfsv.h:150
@ E_PSI_FILE_DIR
Definition: rfsv.h:144
@ E_PSI_GEN_FAIL
Definition: rfsv.h:111
@ E_PSI_FILE_DISC
Definition: rfsv.h:152
@ E_PSI_GEN_ARG
Definition: rfsv.h:112
@ PSI_O_RDONLY
Definition: rfsv.h:90
std::string attr2String(const uint32_t attr)
Converts a file attribute rfsv::file_attribs to human readable format, usable for showing them in dir...
Definition: rfsv.cc:150
@ PSI_A_NORMAL
Attributes, valid on EPOC only.
Definition: rfsv.h:203
@ PSI_A_RDONLY
Attributes, valid on both EPOC and SIBO.
Definition: rfsv.h:195
@ PSI_A_TEXT
Definition: rfsv.h:211
@ PSI_A_STREAM
Definition: rfsv.h:210
@ PSI_A_READ
Attributes, valid on SIBO only.
Definition: rfsv.h:208
@ PSI_A_ARCHIVE
Definition: rfsv.h:199
@ PSI_A_VOLUME
Definition: rfsv.h:200
@ PSI_A_HIDDEN
Definition: rfsv.h:196
@ PSI_A_EXEC
Definition: rfsv.h:209
@ PSI_A_DIR
Definition: rfsv.h:198
@ PSI_A_SYSTEM
Definition: rfsv.h:197
Enum< errs > status
Definition: rfsv.h:646
static std::string convertSlash(const std::string &name)
Utility method, converts '/' to '\'.
Definition: rfsv.cc:141
int32_t serNum
Definition: rfsv.h:647
void reconnect()
Definition: rfsv.cc:117
void reset()
Definition: rfsv.cc:124
TCPSocket * skt
Definition: rfsv.h:645
Definition: doctest.h:522
static rfsv * a
Definition: main.cc:53
static int sibo_dattr[]
Definition: rfsv16.cc:384
#define RFSV16_MAXDATALEN
Definition: rfsv16.cc:38
int(* cpCallback_t)(void *, uint32_t)
Defines the callback procedure for progress indication of copy operations.
Definition: rfsv.h:42
std::deque< class PlpDirent > PlpDir
Definition: rfsv.h:31
const int RFSV_SENDLEN
Definition: rfsv.h:36