opendir change: refinement
[minix.git] / commands / ftp101 / file.c
blob3c53e9331051edcdf2a25b9aa7b074e312e95b9d
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", ""));
272 if(DOcmdcheck())
273 return(0);
275 file = cmdargv[1];
277 if(cmdargc < 2) {
278 if(readline("File: ", line2, sizeof(line2)) < 0)
279 return(-1);
280 file = line2;
283 return(DOcommand("STAT", file));
286 int DOlist()
288 char *path;
289 char *local;
290 int fd;
291 int s;
293 if(DOcmdcheck())
294 return(0);
296 path = cmdargv[1];
298 if(cmdargc < 2)
299 path = "";
301 if(cmdargc < 3)
302 local = "";
303 else
304 local = cmdargv[2];
306 if(*local == '\0')
307 fd = 1;
308 else
309 fd = open(local, O_WRONLY | O_CREAT | O_TRUNC, 0666);
311 if(fd < 0) {
312 printf("Could not open local file %s. Error %s\n", local, strerror(errno));
313 return(0);
316 s = DOdata("LIST", path, RETR, fd);
318 if(fd > 2)
319 close(fd);
321 return(s);
324 int DOnlst()
326 char *path;
327 char *local;
328 int fd;
329 int s;
331 if(DOcmdcheck())
332 return(0);
334 path = cmdargv[1];
336 if(cmdargc < 2)
337 path = "";
339 if(cmdargc < 3)
340 local = "";
341 else
342 local = cmdargv[2];
344 if(*local == '\0')
345 fd = 1;
346 else
347 fd = open(local, O_WRONLY | O_CREAT | O_TRUNC, 0666);
349 if(fd < 0) {
350 printf("Could not open local file %s. Error %s\n", local, strerror(errno));
351 return(0);
354 s = DOdata("NLST", path, RETR, fd);
356 if(fd > 2)
357 close(fd);
359 return(s);
362 int DOretr()
364 char *file, *localfile;
365 int fd;
366 int s;
368 if(DOcmdcheck())
369 return(0);
371 file = cmdargv[1];
373 if(cmdargc < 2) {
374 if(readline("Remote File: ", line2, sizeof(line2)) < 0)
375 return(-1);
376 file = line2;
379 if(cmdargc < 3)
380 localfile = file;
381 else
382 localfile = cmdargv[2];
384 fd = open(localfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
386 if(fd < 0) {
387 printf("Could not open local file %s. Error %s\n", localfile, strerror(errno));
388 return(0);
391 s = DOdata("RETR", file, RETR, fd);
393 close(fd);
395 return(s);
398 int DOrretr()
400 char *file, *localfile;
401 int fd;
402 int s;
403 off_t filesize;
404 char restart[16];
406 if(DOcmdcheck())
407 return(0);
409 file = cmdargv[1];
411 if(cmdargc < 2) {
412 if(readline("Remote File: ", line2, sizeof(line2)) < 0)
413 return(-1);
414 file = line2;
417 if(cmdargc < 3)
418 localfile = file;
419 else
420 localfile = cmdargv[2];
422 fd = open(localfile, O_RDWR);
424 if(fd < 0) {
425 printf("Could not open local file %s. Error %s\n", localfile, strerror(errno));
426 return(0);
429 if(type == TYPE_A) {
430 if(asciisize(fd, &filesize)) {
431 printf("Could not determine ascii file size of %s\n", localfile);
432 close(fd);
433 return(0);
435 } else
436 filesize = lseek(fd, 0, SEEK_END);
438 sprintf(restart, "%u", filesize);
440 s = DOcommand("REST", restart);
442 if(s != 350) {
443 close(fd);
444 return(s);
447 s = DOdata("RETR", file, RETR, fd);
449 close(fd);
451 return(s);
454 char *ttime(time_t t)
456 struct tm *tm;
457 static char tbuf[16];
459 tm = localtime(&t);
461 sprintf(tbuf, "%04d%02d%02d%02d%02d.%02d",
462 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
463 tm->tm_hour, tm->tm_min, tm->tm_sec);
465 return(tbuf);
468 static int cloneit(file, mode)
469 char *file;
470 int mode;
472 int opr;
473 int s;
474 int ss;
475 struct stat st;
476 static unsigned short lcrc;
477 static unsigned short ccrc;
478 static unsigned long csize;
479 static char ft;
480 static unsigned long maj;
481 static unsigned long min;
482 static unsigned long uid;
483 static unsigned long gid;
484 static unsigned long fmode;
485 static unsigned long size;
486 static unsigned long mtime;
487 struct utimbuf ut;
488 unsigned short crc(char *fname);
490 if(mode == 1) {
491 /* see if file exists locally */
492 ss = stat(file, &st);
494 opr = printreply;
495 printreply = 0;
496 s = DOcommand("SITE FDET", file);
497 printreply = opr;
499 if((s / 100) != 2)
500 return(-1);
502 sscanf(reply, "%*d %c%lu%lu%lu%lu%lu%lu%lu",
503 &ft, &maj, &min, &uid, &gid, &fmode, &size, &mtime);
505 if(ft == 'f') {
506 opr = printreply;
507 printreply = 0;
508 s = DOcommand("SITE CCRC", file);
509 printreply = opr;
510 if((s / 100) != 2)
511 return(-1);
513 sscanf(reply, "%*hu %*s%u%lu", &ccrc, &csize);
514 if(ss < 0) return(-1);
515 lcrc = crc(file);
516 if(size != csize || size != st.st_size || ccrc != lcrc)
517 return(-1);
518 } else
519 if(ss < 0 && ft == 'd') {
520 s = mkdir(file, fmode);
521 printf("mkdir %s\n", file);
522 } else
523 if((ss < 0) && (ft == 'b' || ft == 'c' || ft == 'p')) {
524 s = mknod(file, fmode, maj << 8 | min);
525 printf("mknod %s %lu %lu\n", file, maj, min);
526 } else
527 return(0);
529 ss = stat(file, &st);
530 if(ss < 0)
531 return(-1);
532 if(st.st_uid != uid || st.st_gid != gid) {
533 s = chown(file, uid, gid);
534 printf("chown %lu:%lu %s\n", uid, gid, file);
536 if(st.st_mode != fmode) {
537 s = chmod(file, fmode);
538 printf("chmod %04lo %s\n", fmode, file);
540 if(st.st_mtime != mtime) {
541 ut.actime = mtime;
542 ut.modtime = mtime;
543 s = utime(file, &ut);
544 printf("touch -m -t %s %s\n", ttime(mtime), file);
547 return(0);
550 int DOMretr()
552 char *files;
553 int fd, s;
554 char *p;
555 FILE *fp;
556 char name[32];
558 if(DOcmdcheck())
559 return(0);
561 files = cmdargv[1];
563 if(cmdargc < 2) {
564 if(readline("Files: ", line2, sizeof(line2)) < 0)
565 return(-1);
566 files = line2;
569 tmpnam(name);
571 fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
573 if(fd < 0) {
574 printf("Could not open local file %s. Error %s\n", name, strerror(errno));
575 return(0);
578 s = DOdata("NLST", files, RETR, fd);
580 close(fd);
582 if(s == 226 || s == 250) {
583 fp = fopen(name, "r");
584 unlink(name);
585 if(fp == (FILE *)NULL) {
586 printf("Unable to open file listing.\n");
587 return(0);
589 while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
590 p = line2 + strlen(line2) - 1;
591 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
592 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
593 printf("Retrieving file: %s\n", line2); fflush(stdout);
594 fd = open(line2, O_WRONLY | O_CREAT | O_TRUNC, 0666);
595 if(fd < 0)
596 printf("Unable to open local file %s\n", line2);
597 else {
598 s = DOdata("RETR", line2, RETR, fd);
599 close(fd);
600 if(s < 0) break;
603 fclose(fp);
604 } else
605 unlink(name);
607 return(s);
610 int DOappe()
612 char *file, *remotefile;
613 int fd;
614 int s;
616 if(DOcmdcheck())
617 return(0);
619 file = cmdargv[1];
621 if(cmdargc < 2) {
622 if(readline("Local File: ", line2, sizeof(line2)) < 0)
623 return(-1);
624 file = line2;
627 if(cmdargc < 3)
628 remotefile = file;
629 else
630 remotefile = cmdargv[2];
632 fd = open(file, O_RDONLY);
634 if(fd < 0) {
635 printf("Could not open local file %s. Error %s\n", file, strerror(errno));
636 return(0);
639 s = DOdata("APPE", remotefile, STOR, fd);
641 close(fd);
643 return(s);
646 int DOstor()
648 char *file, *remotefile;
649 int fd;
650 int s;
652 if(DOcmdcheck())
653 return(0);
655 file = cmdargv[1];
657 if(cmdargc < 2) {
658 if(readline("Local File: ", line2, sizeof(line2)) < 0)
659 return(-1);
660 file = line2;
663 if(cmdargc < 3)
664 remotefile = file;
665 else
666 remotefile = cmdargv[2];
668 fd = open(file, O_RDONLY);
670 if(fd < 0) {
671 printf("Could not open local file %s. Error %s\n", file, strerror(errno));
672 return(0);
675 s = DOdata("STOR", remotefile, STOR, fd);
677 close(fd);
679 return(s);
682 int DOrstor()
684 char *file, *remotefile;
685 int fd;
686 int s;
687 off_t filesize, rmtsize;
688 char restart[16];
690 if(DOcmdcheck())
691 return(0);
693 file = cmdargv[1];
695 if(cmdargc < 2) {
696 if(readline("Local File: ", line2, sizeof(line2)) < 0)
697 return(-1);
698 file = line2;
701 if(cmdargc < 3)
702 remotefile = file;
703 else
704 remotefile = cmdargv[2];
706 s = DOcommand("SIZE", remotefile);
708 if(s != 215)
709 return(s);
711 rmtsize = atol(reply+4);
713 fd = open(file, O_RDONLY);
715 if(fd < 0) {
716 printf("Could not open local file %s. Error %s\n", file, strerror(errno));
717 return(0);
720 if(type == TYPE_A)
721 filesize = asciisetsize(fd, rmtsize);
722 else
723 filesize = lseek(fd, rmtsize, SEEK_SET);
725 if(filesize != rmtsize) {
726 printf("Could not set file start of %s\n", file);
727 close(fd);
728 return(0);
731 sprintf(restart, "%u", rmtsize);
733 s = DOcommand("REST", restart);
735 if(s != 350) {
736 close(fd);
737 return(s);
740 s = DOdata("STOR", remotefile, STOR, fd);
742 close(fd);
744 return(s);
747 int DOstou()
749 char *file, *remotefile;
750 int fd;
751 int s;
753 if(DOcmdcheck())
754 return(0);
756 file = cmdargv[1];
758 if(cmdargc < 2) {
759 if(readline("Local File: ", line2, sizeof(line2)) < 0)
760 return(-1);
761 file = line2;
764 if(cmdargc < 3)
765 remotefile = file;
766 else
767 remotefile = cmdargv[2];
769 fd = open(file, O_RDONLY);
771 if(fd < 0) {
772 printf("Could not open local file %s. Error %s\n", file, strerror(errno));
773 return(0);
776 s = DOdata("STOU", remotefile, STOR, fd);
778 close(fd);
780 return(s);
783 int DOMstor()
785 char *files;
786 char *name;
787 char *p;
788 int fd, s;
789 FILE *fp;
791 if(DOcmdcheck())
792 return(0);
794 files = cmdargv[1];
796 if(cmdargc < 2) {
797 if(readline("Files: ", line2, sizeof(line2)) < 0)
798 return(-1);
799 files = line2;
802 name = dir(files, 0);
804 fp = fopen(name, "r");
806 if(fp == (FILE *)NULL) {
807 printf("Unable to open listing file.\n");
808 return(0);
811 while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
812 p = line2 + strlen(line2) - 1;
813 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
814 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
815 printf("Sending file: %s\n", line2); fflush(stdout);
816 fd = open(line2, O_RDONLY);
817 if(fd < 0)
818 printf("Unable to open local file %s\n", line2);
819 else {
820 s = DOdata("STOR", line2, STOR, fd);
821 close(fd);
822 if(s < 0) break;
825 fclose(fp);
826 unlink(name);
828 return(s);
831 static int asciisize(fd, filesize)
832 int fd;
833 off_t *filesize;
835 unsigned long count;
836 char *p, *pp;
837 int cnt;
839 count = 0;
841 while((cnt = read(fd, buffer, sizeof(buffer))) > 0) {
842 p = buffer; pp = buffer + cnt;
843 count += cnt;
844 while(p < pp)
845 if(*p++ == '\n')
846 count++;
849 if(cnt == 0) {
850 *filesize = count;
851 return(0);
854 return(-1);
857 static off_t asciisetsize(fd, filesize)
858 int fd;
859 off_t filesize;
861 off_t sp;
862 int s;
864 sp = 0;
866 while(sp < filesize) {
867 s = read(fd, buffer, 1);
868 if(s < 0)
869 return(-1);
870 if(s == 0) break;
871 sp++;
872 if(*buffer == '\n')
873 sp++;
876 return(sp);
879 int DOclone()
881 char *files;
882 int fd, s;
883 char *p;
884 FILE *fp;
885 char name[32];
887 if(DOcmdcheck())
888 return(0);
890 files = cmdargv[1];
892 tmpnam(name);
894 fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
896 if(fd < 0) {
897 printf("Could not open local file %s. Error %s\n", name, strerror(errno));
898 return(0);
901 s = DOdata("NLST", files, RETR, fd);
903 close(fd);
905 if(s == 226 || s == 250) {
906 fp = fopen(name, "r");
907 unlink(name);
908 if(fp == (FILE *)NULL) {
909 printf("Unable to open file listing.\n");
910 return(0);
912 while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
913 p = line2 + strlen(line2) - 1;
914 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
915 if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
916 cmdargv[1] = line2;
917 if(cloneit(line2, 1)) {
918 printf("Retrieving file: %s\n", line2); fflush(stdout);
919 fd = open(line2, O_WRONLY | O_CREAT | O_TRUNC, 0666);
920 if(fd < 0)
921 printf("Unable to open local file %s\n", line2);
922 else {
923 s = DOdata("RETR", line2, RETR, fd);
924 close(fd);
925 if(s < 0) break;
927 s = cloneit(line2, 2);
930 fclose(fp);
931 } else
932 unlink(name);
934 return(s);