retire nonsymbolic rootdev, dev2name
[minix.git] / commands / ftp101 / file.c
blob9fda3642346ce9c172b3017cf4c8079d0b5ecc0f
1 /* file.c Copyright 1992-2000 by Michael Temari All Rights Reserved
3 * This file is part of ftp.
6 * 01/25/96 Initial Release Michael Temari, <Michael@TemWare.Com>
7 */
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <fcntl.h>
16 #include <errno.h>
17 #include <time.h>
18 #include <utime.h>
19 #include <net/hton.h>
21 #include "ftp.h"
22 #include "file.h"
23 #include "net.h"
25 static char *dir(char *path, int full);
26 static int asciisize(int fd, off_t *filesize);
27 static off_t asciisetsize(int fd, off_t filesize);
28 static int cloneit(char *file, int mode);
30 #if (__WORD_SIZE == 4)
31 static char buffer[8192];
32 #else
33 static char buffer[2048];
34 #endif
35 static char line2[512];
37 static char *dir(path, full)
38 char *path;
39 int full;
41 char cmd[128];
42 static char name[32];
44 tmpnam(name);
46 if(full)
47 sprintf(cmd, "ls -l %s > %s", path, name);
48 else
49 sprintf(cmd, "ls -dA %s > %s", path, name);
51 system(cmd);
53 return(name);
56 int DOascii()
58 int s;
60 if(DOcmdcheck())
61 return(0);
63 s = DOcommand("TYPE", "A");
65 type = TYPE_A;
67 return(s);
70 int DObinary()
72 int s;
74 if(DOcmdcheck())
75 return(0);
77 s = DOcommand("TYPE", "I");
79 type = TYPE_I;
81 return(s);
84 int DOblock()
86 int s;
88 if(DOcmdcheck())
89 return(0);
91 s = DOcommand("MODE", "B");
93 mode = MODE_B;
95 return(s);
98 int DOstream()
100 int s;
102 if(DOcmdcheck())
103 return(0);
105 s = DOcommand("MODE", "S");
107 mode = MODE_S;
109 return(s);
112 int DOpwd()
114 int s;
116 if(DOcmdcheck())
117 return(0);
119 s = DOcommand("PWD", "");
121 if(s == 500 || s == 502)
122 s = DOcommand("XPWD", "");
124 return(s);
127 int DOcd()
129 char *path;
130 int s;
132 if(DOcmdcheck())
133 return(0);
135 path = cmdargv[1];
137 if(cmdargc < 2) {
138 if(readline("Path: ", line2, sizeof(line2)) < 0)
139 return(-1);
140 path = line2;
143 if(!strcmp(path, ".."))
144 s = DOcommand("CDUP", "");
145 else
146 s = DOcommand("CWD", path);
148 if(s == 500 || s == 502) {
149 if(!strcmp(path, ".."))
150 s = DOcommand("XCUP", "");
151 else
152 s = DOcommand("XCWD", path);
155 return(s);
158 int DOmkdir()
160 char *path;
161 int s;
163 if(DOcmdcheck())
164 return(0);
166 path = cmdargv[1];
168 if(cmdargc < 2) {
169 if(readline("Directory: ", line2, sizeof(line2)) < 0)
170 return(-1);
171 path = line2;
174 s = DOcommand("MKD", path);
176 if(s == 500 || s == 502)
177 s = DOcommand("XMKD", path);
179 return(s);
182 int DOrmdir()
184 char *path;
185 int s;
187 if(DOcmdcheck())
188 return(0);
190 path = cmdargv[1];
192 if(cmdargc < 2) {
193 if(readline("Directory: ", line2, sizeof(line2)) < 0)
194 return(-1);
195 path = line2;
198 s = DOcommand("RMD", path);
200 if(s == 500 || s == 502)
201 s = DOcommand("XRMD", path);
203 return(s);
206 int DOdelete()
208 char *file;
210 if(DOcmdcheck())
211 return(0);
213 file = cmdargv[1];
215 if(cmdargc < 2) {
216 if(readline("File: ", line2, sizeof(line2)) < 0)
217 return(-1);
218 file = line2;
221 return(DOcommand("DELE", file));
224 int DOmdtm()
226 char *file;
228 if(DOcmdcheck())
229 return(0);
231 file = cmdargv[1];
233 if(cmdargc < 2) {
234 if(readline("File: ", line2, sizeof(line2)) < 0)
235 return(-1);
236 file = line2;
239 return(DOcommand("MDTM", file));
242 int DOsize()
244 char *file;
246 if(DOcmdcheck())
247 return(0);
249 file = cmdargv[1];
251 if(cmdargc < 2) {
252 if(readline("File: ", line2, sizeof(line2)) < 0)
253 return(-1);
254 file = line2;
257 return(DOcommand("SIZE", file));
260 int DOstat()
262 char *file;
264 if(cmdargc < 2)
265 if(!linkopen) {
266 printf("You must \"OPEN\" a connection first.\n");
267 return(0);
268 } else
269 return(DOcommand("STAT", ""));
271 if(DOcmdcheck())
272 return(0);
274 file = cmdargv[1];
276 if(cmdargc < 2) {
277 if(readline("File: ", line2, sizeof(line2)) < 0)
278 return(-1);
279 file = line2;
282 return(DOcommand("STAT", file));
285 int DOlist()
287 char *path;
288 char *local;
289 int fd;
290 int s;
292 if(DOcmdcheck())
293 return(0);
295 path = cmdargv[1];
297 if(cmdargc < 2)
298 path = "";
300 if(cmdargc < 3)
301 local = "";
302 else
303 local = cmdargv[2];
305 if(*local == '\0')
306 fd = 1;
307 else
308 fd = open(local, O_WRONLY | O_CREAT | O_TRUNC, 0666);
310 if(fd < 0) {
311 printf("Could not open local file %s. Error %s\n", local, strerror(errno));
312 return(0);
315 s = DOdata("LIST", path, RETR, fd);
317 if(fd > 2)
318 close(fd);
320 return(s);
323 int DOnlst()
325 char *path;
326 char *local;
327 int fd;
328 int s;
330 if(DOcmdcheck())
331 return(0);
333 path = cmdargv[1];
335 if(cmdargc < 2)
336 path = "";
338 if(cmdargc < 3)
339 local = "";
340 else
341 local = cmdargv[2];
343 if(*local == '\0')
344 fd = 1;
345 else
346 fd = open(local, O_WRONLY | O_CREAT | O_TRUNC, 0666);
348 if(fd < 0) {
349 printf("Could not open local file %s. Error %s\n", local, strerror(errno));
350 return(0);
353 s = DOdata("NLST", path, RETR, fd);
355 if(fd > 2)
356 close(fd);
358 return(s);
361 int DOretr()
363 char *file, *localfile;
364 int fd;
365 int s;
367 if(DOcmdcheck())
368 return(0);
370 file = cmdargv[1];
372 if(cmdargc < 2) {
373 if(readline("Remote File: ", line2, sizeof(line2)) < 0)
374 return(-1);
375 file = line2;
378 if(cmdargc < 3)
379 localfile = file;
380 else
381 localfile = cmdargv[2];
383 fd = open(localfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
385 if(fd < 0) {
386 printf("Could not open local file %s. Error %s\n", localfile, strerror(errno));
387 return(0);
390 s = DOdata("RETR", file, RETR, fd);
392 close(fd);
394 return(s);
397 int DOrretr()
399 char *file, *localfile;
400 int fd;
401 int s;
402 off_t filesize;
403 char restart[16];
405 if(DOcmdcheck())
406 return(0);
408 file = cmdargv[1];
410 if(cmdargc < 2) {
411 if(readline("Remote File: ", line2, sizeof(line2)) < 0)
412 return(-1);
413 file = line2;
416 if(cmdargc < 3)
417 localfile = file;
418 else
419 localfile = cmdargv[2];
421 fd = open(localfile, O_RDWR);
423 if(fd < 0) {
424 printf("Could not open local file %s. Error %s\n", localfile, strerror(errno));
425 return(0);
428 if(type == TYPE_A) {
429 if(asciisize(fd, &filesize)) {
430 printf("Could not determine ascii file size of %s\n", localfile);
431 close(fd);
432 return(0);
434 } else
435 filesize = lseek(fd, 0, SEEK_END);
437 sprintf(restart, "%lu", filesize);
439 s = DOcommand("REST", restart);
441 if(s != 350) {
442 close(fd);
443 return(s);
446 s = DOdata("RETR", file, RETR, fd);
448 close(fd);
450 return(s);
453 char *ttime(time_t t)
455 struct tm *tm;
456 static char tbuf[16];
458 tm = localtime(&t);
460 sprintf(tbuf, "%04d%02d%02d%02d%02d.%02d",
461 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
462 tm->tm_hour, tm->tm_min, tm->tm_sec);
464 return(tbuf);
467 static int cloneit(file, mode)
468 char *file;
469 int mode;
471 int opr;
472 int s;
473 int ss;
474 struct stat st;
475 static unsigned short lcrc;
476 static unsigned short ccrc;
477 static unsigned long csize;
478 static char ft;
479 static unsigned long maj;
480 static unsigned long min;
481 static unsigned long uid;
482 static unsigned long gid;
483 static unsigned long fmode;
484 static unsigned long size;
485 static unsigned long mtime;
486 struct utimbuf ut;
487 unsigned short crc(char *fname);
489 if(mode == 1) {
490 /* see if file exists locally */
491 ss = stat(file, &st);
493 opr = printreply;
494 printreply = 0;
495 s = DOcommand("SITE FDET", file);
496 printreply = opr;
498 if((s / 100) != 2)
499 return(-1);
501 sscanf(reply, "%*d %c%lu%lu%lu%lu%lu%lu%lu",
502 &ft, &maj, &min, &uid, &gid, &fmode, &size, &mtime);
504 if(ft == 'f') {
505 opr = printreply;
506 printreply = 0;
507 s = DOcommand("SITE CCRC", file);
508 printreply = opr;
509 if((s / 100) != 2)
510 return(-1);
512 sscanf(reply, "%*d %*s%u%lu", &ccrc, &csize);
513 if(ss < 0) return(-1);
514 lcrc = crc(file);
515 if(size != csize || size != st.st_size || ccrc != lcrc)
516 return(-1);
517 } else
518 if(ss < 0 && ft == 'd') {
519 s = mkdir(file, fmode);
520 printf("mkdir %s\n", file);
521 } else
522 if((ss < 0) && (ft == 'b' || ft == 'c' || ft == 'p')) {
523 s = mknod(file, fmode, maj << 8 | min);
524 printf("mknod %c %u %u\n", file, maj, min);
525 } else
526 return(0);
528 ss = stat(file, &st);
529 if(ss < 0)
530 return(-1);
531 if(st.st_uid != uid || st.st_gid != gid) {
532 s = chown(file, uid, gid);
533 printf("chown %u:%u %s\n", uid, gid, file);
535 if(st.st_mode != fmode) {
536 s = chmod(file, fmode);
537 printf("chmod %04o %s\n", fmode, file);
539 if(st.st_mtime != mtime) {
540 ut.actime = mtime;
541 ut.modtime = mtime;
542 s = utime(file, &ut);
543 printf("touch -m -t %s %s\n", ttime(mtime), file);
546 return(0);
549 int DOMretr()
551 char *files;
552 int fd, s;
553 char *p;
554 FILE *fp;
555 char name[32];
557 if(DOcmdcheck())
558 return(0);
560 files = cmdargv[1];
562 if(cmdargc < 2) {
563 if(readline("Files: ", line2, sizeof(line2)) < 0)
564 return(-1);
565 files = line2;
568 tmpnam(name);
570 fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
572 if(fd < 0) {
573 printf("Could not open local file %s. Error %s\n", name, strerror(errno));
574 return(0);
577 s = DOdata("NLST", files, RETR, fd);
579 close(fd);
581 if(s == 226 || s == 250) {
582 fp = fopen(name, "r");
583 unlink(name);
584 if(fp == (FILE *)NULL) {
585 printf("Unable to open file listing.\n");
586 return(0);
588 while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
589 p = line2 + strlen(line2) - 1;
590 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
591 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
592 printf("Retrieving file: %s\n", line2); fflush(stdout);
593 fd = open(line2, O_WRONLY | O_CREAT | O_TRUNC, 0666);
594 if(fd < 0)
595 printf("Unable to open local file %s\n", line2);
596 else {
597 s = DOdata("RETR", line2, RETR, fd);
598 close(fd);
599 if(s < 0) break;
602 fclose(fp);
603 } else
604 unlink(name);
606 return(s);
609 int DOappe()
611 char *file, *remotefile;
612 int fd;
613 int s;
615 if(DOcmdcheck())
616 return(0);
618 file = cmdargv[1];
620 if(cmdargc < 2) {
621 if(readline("Local File: ", line2, sizeof(line2)) < 0)
622 return(-1);
623 file = line2;
626 if(cmdargc < 3)
627 remotefile = file;
628 else
629 remotefile = cmdargv[2];
631 fd = open(file, O_RDONLY);
633 if(fd < 0) {
634 printf("Could not open local file %s. Error %s\n", file, strerror(errno));
635 return(0);
638 s = DOdata("APPE", remotefile, STOR, fd);
640 close(fd);
642 return(s);
645 int DOstor()
647 char *file, *remotefile;
648 int fd;
649 int s;
651 if(DOcmdcheck())
652 return(0);
654 file = cmdargv[1];
656 if(cmdargc < 2) {
657 if(readline("Local File: ", line2, sizeof(line2)) < 0)
658 return(-1);
659 file = line2;
662 if(cmdargc < 3)
663 remotefile = file;
664 else
665 remotefile = cmdargv[2];
667 fd = open(file, O_RDONLY);
669 if(fd < 0) {
670 printf("Could not open local file %s. Error %s\n", file, strerror(errno));
671 return(0);
674 s = DOdata("STOR", remotefile, STOR, fd);
676 close(fd);
678 return(s);
681 int DOrstor()
683 char *file, *remotefile;
684 int fd;
685 int s;
686 off_t filesize, rmtsize;
687 char restart[16];
689 if(DOcmdcheck())
690 return(0);
692 file = cmdargv[1];
694 if(cmdargc < 2) {
695 if(readline("Local File: ", line2, sizeof(line2)) < 0)
696 return(-1);
697 file = line2;
700 if(cmdargc < 3)
701 remotefile = file;
702 else
703 remotefile = cmdargv[2];
705 s = DOcommand("SIZE", remotefile);
707 if(s != 215)
708 return(s);
710 rmtsize = atol(reply+4);
712 fd = open(file, O_RDONLY);
714 if(fd < 0) {
715 printf("Could not open local file %s. Error %s\n", file, strerror(errno));
716 return(0);
719 if(type == TYPE_A)
720 filesize = asciisetsize(fd, rmtsize);
721 else
722 filesize = lseek(fd, rmtsize, SEEK_SET);
724 if(filesize != rmtsize) {
725 printf("Could not set file start of %s\n", file);
726 close(fd);
727 return(0);
730 sprintf(restart, "%lu", rmtsize);
732 s = DOcommand("REST", restart);
734 if(s != 350) {
735 close(fd);
736 return(s);
739 s = DOdata("STOR", remotefile, STOR, fd);
741 close(fd);
743 return(s);
746 int DOstou()
748 char *file, *remotefile;
749 int fd;
750 int s;
752 if(DOcmdcheck())
753 return(0);
755 file = cmdargv[1];
757 if(cmdargc < 2) {
758 if(readline("Local File: ", line2, sizeof(line2)) < 0)
759 return(-1);
760 file = line2;
763 if(cmdargc < 3)
764 remotefile = file;
765 else
766 remotefile = cmdargv[2];
768 fd = open(file, O_RDONLY);
770 if(fd < 0) {
771 printf("Could not open local file %s. Error %s\n", file, strerror(errno));
772 return(0);
775 s = DOdata("STOU", remotefile, STOR, fd);
777 close(fd);
779 return(s);
782 int DOMstor()
784 char *files;
785 char *name;
786 char *p;
787 int fd, s;
788 FILE *fp;
790 if(DOcmdcheck())
791 return(0);
793 files = cmdargv[1];
795 if(cmdargc < 2) {
796 if(readline("Files: ", line2, sizeof(line2)) < 0)
797 return(-1);
798 files = line2;
801 name = dir(files, 0);
803 fp = fopen(name, "r");
805 if(fp == (FILE *)NULL) {
806 printf("Unable to open listing file.\n");
807 return(0);
810 while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
811 p = line2 + strlen(line2) - 1;
812 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
813 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
814 printf("Sending file: %s\n", line2); fflush(stdout);
815 fd = open(line2, O_RDONLY);
816 if(fd < 0)
817 printf("Unable to open local file %s\n", line2);
818 else {
819 s = DOdata("STOR", line2, STOR, fd);
820 close(fd);
821 if(s < 0) break;
824 fclose(fp);
825 unlink(name);
827 return(s);
830 static int asciisize(fd, filesize)
831 int fd;
832 off_t *filesize;
834 unsigned long count;
835 char *p, *pp;
836 int cnt;
838 count = 0;
840 while((cnt = read(fd, buffer, sizeof(buffer))) > 0) {
841 p = buffer; pp = buffer + cnt;
842 count += cnt;
843 while(p < pp)
844 if(*p++ == '\n')
845 count++;
848 if(cnt == 0) {
849 *filesize = count;
850 return(0);
853 return(-1);
856 static off_t asciisetsize(fd, filesize)
857 int fd;
858 off_t filesize;
860 off_t sp;
861 int s;
863 sp = 0;
865 while(sp < filesize) {
866 s = read(fd, buffer, 1);
867 if(s < 0)
868 return(-1);
869 if(s == 0) break;
870 sp++;
871 if(*buffer == '\n')
872 sp++;
875 return(sp);
878 int DOclone()
880 char *files;
881 int fd, s;
882 char *p;
883 FILE *fp;
884 char name[32];
886 if(DOcmdcheck())
887 return(0);
889 files = cmdargv[1];
891 tmpnam(name);
893 fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
895 if(fd < 0) {
896 printf("Could not open local file %s. Error %s\n", name, strerror(errno));
897 return(0);
900 s = DOdata("NLST", files, RETR, fd);
902 close(fd);
904 if(s == 226 || s == 250) {
905 fp = fopen(name, "r");
906 unlink(name);
907 if(fp == (FILE *)NULL) {
908 printf("Unable to open file listing.\n");
909 return(0);
911 while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
912 p = line2 + strlen(line2) - 1;
913 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
914 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
915 cmdargv[1] = line2;
916 if(cloneit(line2, 1)) {
917 printf("Retrieving file: %s\n", line2); fflush(stdout);
918 fd = open(line2, O_WRONLY | O_CREAT | O_TRUNC, 0666);
919 if(fd < 0)
920 printf("Unable to open local file %s\n", line2);
921 else {
922 s = DOdata("RETR", line2, RETR, fd);
923 close(fd);
924 if(s < 0) break;
926 s = cloneit(line2, 2);
929 fclose(fp);
930 } else
931 unlink(name);
933 return(s);