ftpsubr.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:4k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* Routines common to both the FTP client and server
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "socket.h"
  8. #include "proc.h"
  9. #include "ftp.h"
  10. #include "cmdparse.h"
  11. #include "md5.h"
  12. #define MD5BLOCK 64 /* Preferred MD5 block size */
  13. /* Send a file (opened by caller) on a network socket.
  14.  * Normal return: count of bytes sent
  15.  * Error return: -1
  16.  */
  17. long
  18. sendfile(fp,network,mode,verb)
  19. FILE *fp; /* File to be sent */
  20. FILE *network; /* Network stream to be sent on */
  21. enum ftp_type mode; /* Transfer mode */
  22. enum verb_level verb; /* Verbosity level */
  23. {
  24. long total = 0;
  25. long hmark = 0;
  26. char *buf;
  27. int cnt;
  28. char cmdbuf[50];
  29. if(verb >= V_STAT){
  30. sprintf(cmdbuf,"repeat socket %d",fileno(network));
  31. cmdparse(Cmds,cmdbuf,NULL);
  32. }
  33. switch(mode){
  34. default:
  35. case LOGICAL_TYPE:
  36. case IMAGE_TYPE:
  37. fmode(network,STREAM_BINARY);
  38. break;
  39. case ASCII_TYPE:
  40. fmode(network,STREAM_ASCII);
  41. break;
  42. }
  43. buf = mallocw(BUFSIZ);
  44. for(;;){
  45. if((cnt = fread(buf,1,BUFSIZ,fp)) == 0){
  46. break;
  47. }
  48. total += cnt;
  49. if(fwrite(buf,1,cnt,network) != cnt){
  50. total = -1;
  51. break;
  52. }
  53. while(verb == V_HASH && total >= hmark+1000){
  54. putchar('#');
  55. hmark += 1000;
  56. }
  57. }
  58. free(buf);
  59. if(verb == V_HASH)
  60. putchar('n');
  61. return total;
  62. }
  63. /* Receive a file (opened by caller) from a network stream
  64.  * Normal return: count of bytes received
  65.  * Error return: -1
  66.  */
  67. long
  68. recvfile(fp,network,mode,verb)
  69. FILE *fp;
  70. FILE *network;
  71. enum ftp_type mode;
  72. enum verb_level verb;
  73. {
  74. int cnt;
  75. long total = 0;
  76. long hmark = 0;
  77. char *buf;
  78. char cmdbuf[50];
  79. if(verb >= V_STAT){
  80. sprintf(cmdbuf,"repeat socket %d",fileno(network));
  81. cmdparse(Cmds,cmdbuf,NULL);
  82. }
  83. if(fp == NULL)
  84. fp = stdout; /* Default */
  85. switch(mode){
  86. default:
  87. case LOGICAL_TYPE:
  88. case IMAGE_TYPE:
  89. fmode(network,STREAM_BINARY);
  90. break;
  91. case ASCII_TYPE:
  92. fmode(network,STREAM_ASCII);
  93. break;
  94. }
  95. buf = mallocw(BUFSIZ);
  96. while((cnt = fread(buf,1,BUFSIZ,network)) != 0){
  97. total += cnt;
  98. while(verb == V_HASH && total >= hmark+1000){
  99. putchar('#');
  100. hmark += 1000;
  101. }
  102. if(fwrite(buf,1,cnt,fp) != cnt){
  103. total = -1;
  104. break;
  105. }
  106. /* Detect an abnormal close */
  107. if(socklen(fileno(network),0) == -1){
  108. total = -1;
  109. break;
  110. }
  111. }
  112. free(buf);
  113. if(verb == V_HASH)
  114. putchar('n');
  115. return total;
  116. }
  117. /* Determine if a file appears to be binary (i.e., non-text).
  118.  * Return 1 if binary, 0 if ascii text after rewinding the file pointer.
  119.  *
  120.  * Used by FTP to warn users when transferring a binary file in text mode.
  121.  */
  122. int
  123. isbinary(fp)
  124. FILE *fp;
  125. {
  126. int c,i;
  127. int rval;
  128. rval = 0;
  129. for(i=0;i<512;i++){
  130. if((c = getc(fp)) == EOF)
  131. break;
  132. if(c & 0x80){
  133. /* High bit is set, probably not text */
  134. rval = 1;
  135. break;
  136. }
  137. }
  138. /* Assume it was at beginning */
  139. fseek(fp,0L,SEEK_SET);
  140. return rval;
  141. }
  142. /* Compute MD5 hash of local file */
  143. int
  144. md5hash(fp,hash,ascii)
  145. FILE *fp;
  146. uint8 hash[16];
  147. int ascii;
  148. {
  149. MD5_CTX md;
  150. char *buf;
  151. int len;
  152. MD5Init(&md);
  153. if(ascii){
  154. /* Text file, hash canonical form (newlines = crlf) */
  155. char *cp;
  156. int c;
  157. cp = buf = malloc(MD5BLOCK);
  158. len = 0;
  159. while((c = fgetc(fp)) != EOF){
  160. if(c == 'n'){
  161. *cp++ = 'r';
  162. if(++len == MD5BLOCK){
  163. MD5Update(&md,(unsigned char *)buf,len);
  164. kwait(NULL);
  165. cp = buf;
  166. len = 0;
  167. }
  168. }
  169. *cp++ = c;
  170. if(++len == MD5BLOCK){
  171. MD5Update(&md,(unsigned char *)buf,len);
  172. kwait(NULL);
  173. cp = buf;
  174. len = 0;
  175. }
  176. }
  177. if(len != 0)
  178. MD5Update(&md,(unsigned char *)buf,len);
  179. free(buf);
  180. } else {
  181. buf = malloc(BUFSIZ);
  182. while((len = fread(buf,1,BUFSIZ,fp)) != 0){
  183. MD5Update(&md,(unsigned char *)buf,len);
  184. kwait(NULL);
  185. }
  186. free(buf);
  187. }
  188. MD5Final(hash,&md);
  189. return 0;
  190. }