📄 ftp-basic.c
字号:
{ char *request, *respline, *s; int nwritten, i; uerr_t err; unsigned char addr4[4];#ifdef ENABLE_IPV6 if (ip_default_family == AF_INET6) { err = ftp_epsv (rbuf, addr, port, "2"); /* try IPv6 with EPSV */ if (FTPOK == err) return FTPOK; err = ftp_epsv (rbuf, addr, port, "1"); /* try IPv4 with EPSV */ if (FTPOK == err) return FTPOK; }#endif /* Form the request. */ request = ftp_request ("PASV", NULL); /* And send it. */ nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request)); if (nwritten < 0) { xfree (request); return WRITEFAILED; } xfree (request); /* Get the server response. */ err = ftp_response (rbuf, &respline); if (err != FTPOK) { xfree (respline); return err; } if (*respline != '2') { xfree (respline); return FTPNOPASV; } /* Parse the request. */ /* respline::=227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */ s = respline; for (s += 4; *s && !ISDIGIT (*s); s++); if (!*s) return FTPINVPASV; for (i = 0; i < 4; i++) { addr4[i] = 0; for (; ISDIGIT (*s); s++) addr4[i] = (*s - '0') + 10 * addr4[i]; if (*s == ',') s++; else { xfree (respline); return FTPINVPASV; } } /* Eventually make an IPv4 in IPv6 adress if needed */ map_ipv4_to_ip ((ip4_address *)addr4, addr); *port=0; for (; ISDIGIT (*s); s++) *port = (*s - '0') + 10 * (*port); if (*s == ',') s++; else { xfree (respline); return FTPINVPASV; } { unsigned short port2 = 0; for (; ISDIGIT (*s); s++) port2 = (*s - '0') + 10 * port2; *port = (*port) * 256 + port2; } xfree (respline); return FTPOK;}/* Sends the TYPE request to the server. */uerr_tftp_type (struct rbuf *rbuf, int type){ char *request, *respline; int nwritten; uerr_t err; char stype[2]; /* Construct argument. */ stype[0] = type; stype[1] = 0; /* Send TYPE request. */ request = ftp_request ("TYPE", stype); nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request)); if (nwritten < 0) { xfree (request); return WRITEFAILED; } xfree (request); /* Get appropriate response. */ err = ftp_response (rbuf, &respline); if (err != FTPOK) { xfree (respline); return err; } if (*respline != '2') { xfree (respline); return FTPUNKNOWNTYPE; } xfree (respline); /* All OK. */ return FTPOK;}/* Changes the working directory by issuing a CWD command to the server. */uerr_tftp_cwd (struct rbuf *rbuf, const char *dir){ char *request, *respline; int nwritten; uerr_t err; /* Send CWD request. */ request = ftp_request ("CWD", dir); nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request)); if (nwritten < 0) { xfree (request); return WRITEFAILED; } xfree (request); /* Get appropriate response. */ err = ftp_response (rbuf, &respline); if (err != FTPOK) { xfree (respline); return err; } if (*respline == '5') { xfree (respline); return FTPNSFOD; } if (*respline != '2') { xfree (respline); return FTPRERR; } xfree (respline); /* All OK. */ return FTPOK;}/* Sends REST command to the FTP server. */uerr_tftp_rest (struct rbuf *rbuf, long offset){ char *request, *respline; int nwritten; uerr_t err; static char numbuf[24]; /* Buffer for the number */ number_to_string (numbuf, offset); request = ftp_request ("REST", numbuf); nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request)); if (nwritten < 0) { xfree (request); return WRITEFAILED; } xfree (request); /* Get appropriate response. */ err = ftp_response (rbuf, &respline); if (err != FTPOK) { xfree (respline); return err; } if (*respline != '3') { xfree (respline); return FTPRESTFAIL; } xfree (respline); /* All OK. */ return FTPOK;}/* Sends RETR command to the FTP server. */uerr_tftp_retr (struct rbuf *rbuf, const char *file){ char *request, *respline; int nwritten; uerr_t err; /* Send RETR request. */ request = ftp_request ("RETR", file); nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request)); if (nwritten < 0) { xfree (request); return WRITEFAILED; } xfree (request); /* Get appropriate response. */ err = ftp_response (rbuf, &respline); if (err != FTPOK) { xfree (respline); return err; } if (*respline == '5') { xfree (respline); return FTPNSFOD; } if (*respline != '1') { xfree (respline); return FTPRERR; } xfree (respline); /* All OK. */ return FTPOK;}/* Sends the LIST command to the server. If FILE is NULL, send just `LIST' (no space). */uerr_tftp_list (struct rbuf *rbuf, const char *file){ char *request, *respline; int nwritten; uerr_t err; /* Send LIST request. */ request = ftp_request ("LIST", file); nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request)); if (nwritten < 0) { xfree (request); return WRITEFAILED; } xfree (request); /* Get appropriate respone. */ err = ftp_response (rbuf, &respline); if (err != FTPOK) { xfree (respline); return err; } if (*respline == '5') { xfree (respline); return FTPNSFOD; } if (*respline != '1') { xfree (respline); return FTPRERR; } xfree (respline); /* All OK. */ return FTPOK;}/* Sends the SYST command to the server. */uerr_tftp_syst (struct rbuf *rbuf, enum stype *server_type){ char *request, *respline; int nwritten; uerr_t err; /* Send SYST request. */ request = ftp_request ("SYST", NULL); nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request)); if (nwritten < 0) { xfree (request); return WRITEFAILED; } xfree (request); /* Get appropriate response. */ err = ftp_response (rbuf, &respline); if (err != FTPOK) { xfree (respline); return err; } if (*respline == '5') { xfree (respline); return FTPSRVERR; } /* Skip the number (215, but 200 (!!!) in case of VMS) */ strtok (respline, " "); /* Which system type has been reported (we are interested just in the first word of the server response)? */ request = strtok (NULL, " "); if (!strcasecmp (request, "VMS")) *server_type = ST_VMS; else if (!strcasecmp (request, "UNIX")) *server_type = ST_UNIX; else if (!strcasecmp (request, "WINDOWS_NT") || !strcasecmp (request, "WINDOWS2000")) *server_type = ST_WINNT; else if (!strcasecmp (request, "MACOS")) *server_type = ST_MACOS; else if (!strcasecmp (request, "OS/400")) *server_type = ST_OS400; else *server_type = ST_OTHER; xfree (respline); /* All OK. */ return FTPOK;}/* Sends the PWD command to the server. */uerr_tftp_pwd (struct rbuf *rbuf, char **pwd){ char *request, *respline; int nwritten; uerr_t err; /* Send PWD request. */ request = ftp_request ("PWD", NULL); nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request)); if (nwritten < 0) { xfree (request); return WRITEFAILED; } xfree (request); /* Get appropriate response. */ err = ftp_response (rbuf, &respline); if (err != FTPOK) { xfree (respline); return err; } if (*respline == '5') { xfree (respline); return FTPSRVERR; } /* Skip the number (257), leading citation mark, trailing citation mark and everything following it. */ strtok (respline, "\""); request = strtok (NULL, "\""); /* Has the `pwd' been already allocated? Free! */ FREE_MAYBE (*pwd); *pwd = xstrdup (request); xfree (respline); /* All OK. */ return FTPOK;}/* Sends the SIZE command to the server, and returns the value in 'size'. * If an error occurs, size is set to zero. */uerr_tftp_size (struct rbuf *rbuf, const char *file, long int *size){ char *request, *respline; int nwritten; uerr_t err; /* Send PWD request. */ request = ftp_request ("SIZE", file); nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request)); if (nwritten < 0) { xfree (request); *size = 0; return WRITEFAILED; } xfree (request); /* Get appropriate response. */ err = ftp_response (rbuf, &respline); if (err != FTPOK) { xfree (respline); *size = 0; return err; } if (*respline == '5') { /* * Probably means SIZE isn't supported on this server. * Error is nonfatal since SIZE isn't in RFC 959 */ xfree (respline); *size = 0; return FTPOK; } errno = 0; *size = strtol (respline + 4, NULL, 0); if (errno) { /* * Couldn't parse the response for some reason. On the (few) * tests I've done, the response is 213 <SIZE> with nothing else - * maybe something a bit more resilient is necessary. It's not a * fatal error, however. */ xfree (respline); *size = 0; return FTPOK; } xfree (respline); /* All OK. */ return FTPOK;}/* If URL's params are of the form "type=X", return character X. Otherwise, return 'I' (the default type). */charftp_process_type (const char *params){ if (params && 0 == strncasecmp (params, "type=", 5) && params[5] != '\0') return TOUPPER (params[5]); else return 'I';}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -