From owner-svn-soc-all@FreeBSD.ORG Tue Jul 9 18:31:51 2013 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id C3B09DD1 for ; Tue, 9 Jul 2013 18:31:51 +0000 (UTC) (envelope-from ambarisha@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) by mx1.freebsd.org (Postfix) with ESMTP id A570E12A6 for ; Tue, 9 Jul 2013 18:31:51 +0000 (UTC) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.7/8.14.7) with ESMTP id r69IVpe4031547 for ; Tue, 9 Jul 2013 18:31:51 GMT (envelope-from ambarisha@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.7/8.14.6/Submit) id r69IVpIH031532 for svn-soc-all@FreeBSD.org; Tue, 9 Jul 2013 18:31:51 GMT (envelope-from ambarisha@FreeBSD.org) Date: Tue, 9 Jul 2013 18:31:51 GMT Message-Id: <201307091831.r69IVpIH031532@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to ambarisha@FreeBSD.org using -f From: ambarisha@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r254504 - in soc2013/ambarisha/head/usr.bin: dmget dms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 09 Jul 2013 18:31:51 -0000 Author: ambarisha Date: Tue Jul 9 18:31:50 2013 New Revision: 254504 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=254504 Log: DMS server first commit Added: soc2013/ambarisha/head/usr.bin/dmget/dm.h soc2013/ambarisha/head/usr.bin/dmget/utils.c soc2013/ambarisha/head/usr.bin/dms/ soc2013/ambarisha/head/usr.bin/dms/Makefile soc2013/ambarisha/head/usr.bin/dms/dm.h soc2013/ambarisha/head/usr.bin/dms/dms.c soc2013/ambarisha/head/usr.bin/dms/dms.h soc2013/ambarisha/head/usr.bin/dms/list.c soc2013/ambarisha/head/usr.bin/dms/list.h soc2013/ambarisha/head/usr.bin/dms/utils.c soc2013/ambarisha/head/usr.bin/dms/worker.c Modified: soc2013/ambarisha/head/usr.bin/dmget/Makefile soc2013/ambarisha/head/usr.bin/dmget/dmget.c soc2013/ambarisha/head/usr.bin/dmget/dmget.h soc2013/ambarisha/head/usr.bin/dmget/fetch.c Modified: soc2013/ambarisha/head/usr.bin/dmget/Makefile ============================================================================== --- soc2013/ambarisha/head/usr.bin/dmget/Makefile Tue Jul 9 15:20:46 2013 (r254503) +++ soc2013/ambarisha/head/usr.bin/dmget/Makefile Tue Jul 9 18:31:50 2013 (r254504) @@ -2,7 +2,7 @@ .include -SRCS= fetch.c dmget.c +SRCS= fetch.c utils.c dmget.c PROG= dmget CSTD?= c99 .if ${MK_OPENSSL} != "no" Added: soc2013/ambarisha/head/usr.bin/dmget/dm.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2013/ambarisha/head/usr.bin/dmget/dm.h Tue Jul 9 18:31:50 2013 (r254504) @@ -0,0 +1,59 @@ +#ifndef _DM_H +#define _DM_H + +#include +#include + +#include +#include + +/* TODO : Fix the path, make sure the perms on it are good */ +#define DMS_UDS_PATH "/tmp/dms.uds" + +struct dmres { +}; + +struct dmreq { + int v_level; + int family; + long ftp_timeout; + long http_timeout; + off_t B_size; + off_t S_size; + long T_secs; + long flags; + +#define A_FLAG (1 << 0) +#define F_FLAG (1 << 1) +#define O_STDOUT (1 << 2) +#define R_FLAG (1 << 3) +#define U_FLAG (1 << 4) +#define d_FLAG (1 << 5) +#define i_FLAG (1 << 6) +#define l_FLAG (1 << 7) +#define m_FLAG (1 << 8) +#define n_FLAG (1 << 9) +#define p_FLAG (1 << 10) +#define r_FLAG (1 << 11) +#define s_FLAG (1 << 12) + + char *i_filename; + char *URL; + char *path; +}; + +struct msg { + char op; + int len; + char *buf; +}; + +#define DMREQ 1 +#define DMRESP 2 +#define DMSTATREQ 3 +#define DMSTATRESP 4 +#define DMAUTHREQ 5 +#define DMAUTHRESP 6 +#define DMSIG 7 + +#endif /* _DMCLIENT_H */ Modified: soc2013/ambarisha/head/usr.bin/dmget/dmget.c ============================================================================== --- soc2013/ambarisha/head/usr.bin/dmget/dmget.c Tue Jul 9 15:20:46 2013 (r254503) +++ soc2013/ambarisha/head/usr.bin/dmget/dmget.c Tue Jul 9 18:31:50 2013 (r254504) @@ -1,4 +1,3 @@ - #include #include #include @@ -9,7 +8,9 @@ #include +#include "dm.h" #include "dmget.h" + auth_t dmAuthMethod; int dmTimeout; int dmRestartCalls; @@ -17,8 +18,11 @@ int dmLastErrCode; char dmLastErrString[MAXERRSTRING]; +static int dms; +static int sigint; + static void * -safe_malloc(size_t size) +Malloc(size_t size) { void *ptr = malloc(size); if (ptr == NULL) { @@ -27,170 +31,155 @@ return ptr; } -static char -mk_dmflags(void) -{ - char flags = 0; - if (dmRestartCalls != 0) - flags |= DM_RESTART_CALLS; - if (dmDebug != 0) - flags |= DM_DEBUG; - - return flags; -} - static int -mk_reqbuf(struct url *u, char **reqbuf, char op) +mk_reqbuf(struct dmreq dmreq, char **reqbuf, char op) { int bufsize = 0; + printf("mk_reqbuf() : Starting\n"); - bufsize += sizeof(bufsize); // Buffer size - bufsize += 1; // Opcode - bufsize += sizeof(struct url) - 4; // Struct url - doc pointer - bufsize += strlen(u->doc) + 1; // Url document name - bufsize += sizeof(dmTimeout); // Timeout - - *reqbuf = (char *) safe_malloc(bufsize); + bufsize += sizeof(bufsize); // Buffer size + bufsize += 1; // Opcode + bufsize += sizeof(struct dmreq) - (3 * sizeof(char*)); // fix sizeof(dmreq) + bufsize += strlen(dmreq.i_filename) + 1; // + bufsize += strlen(dmreq.URL) + 1; + bufsize += strlen(dmreq.path) + 1; + *reqbuf = (char *) Malloc(bufsize); + int i = 0; - + memcpy(*reqbuf, &(bufsize), sizeof(bufsize)); i += sizeof(bufsize); + + *(*reqbuf+i) = op; + i++; + + memcpy(*reqbuf + i, &(dmreq.v_level), sizeof(sizeof(dmreq.v_level))); + i += sizeof(dmreq.v_level); + + memcpy(*reqbuf + i, &(dmreq.family), sizeof(dmreq.family)); + i += sizeof(dmreq.family); + + memcpy(*reqbuf + i, &(dmreq.ftp_timeout), sizeof(dmreq.ftp_timeout)); + i += sizeof(dmreq.ftp_timeout); + + memcpy(*reqbuf + i, &(dmreq.http_timeout), sizeof(dmreq.http_timeout)); + i += sizeof(dmreq.http_timeout); + + memcpy(*reqbuf + i, &(dmreq.B_size), sizeof(dmreq.B_size)); + i += sizeof(dmreq.B_size); + + memcpy(*reqbuf + i, &(dmreq.S_size), sizeof(dmreq.S_size)); + i += sizeof(dmreq.S_size); + + memcpy(*reqbuf + i, &(dmreq.T_secs), sizeof(dmreq.T_secs)); + i += sizeof(dmreq.T_secs); + + memcpy(*reqbuf + i, &(dmreq.flags), sizeof(dmreq.flags)); + i += sizeof(dmreq.flags); - reqbuf[i++] = op; - - memcpy(*reqbuf + i, u->scheme, sizeof(u->scheme)); - i += sizeof(u->scheme); - - memcpy(*reqbuf + i, u->user, sizeof(u->user)); - i += sizeof(u->user); - - memcpy(*reqbuf + i, u->pwd, sizeof(u->pwd)); - i += sizeof(u->pwd); - - memcpy(*reqbuf + i, u->host, sizeof(u->host)); - i += sizeof(u->host); - - memcpy(*reqbuf + i, &(u->offset), sizeof(u->offset)); - i += sizeof(u->offset); - - memcpy(*reqbuf + i, &(u->length), sizeof(u->length)); - i += sizeof(u->length); - - memcpy(*reqbuf + i, &(u->ims_time), sizeof(u->ims_time)); - i += sizeof(u->ims_time); - - memcpy(*reqbuf + i, &dmTimeout, sizeof(dmTimeout)); - i += sizeof(dmTimeout); - - char dmFlags = mk_dmflags(); - memcpy(*reqbuf + i, &dmFlags, sizeof(dmFlags)); - i += sizeof(dmFlags); - - strcpy(*reqbuf + i, u->doc); - //Assert i == bufsize - strlen(doc) - 1 + strcpy(*reqbuf + i, dmreq.i_filename); + i += strlen(dmreq.i_filename) + 1; + + strcpy(*reqbuf + i, dmreq.URL); + i += strlen(dmreq.URL) + 1; + + strcpy(*reqbuf + i, dmreq.path); + i += strlen(dmreq.path) + 1; return bufsize; } static int -send_request(int sock, struct url *u) +send_request(int sock, struct dmreq dmreq) { char *reqbuf; - int bufsize = mk_reqbuf(u, &reqbuf, 0); - int err = write(sock, reqbuf, bufsize); - if (err == -1) { - perror("send_request write():"); - } + int bufsize = mk_reqbuf(dmreq, &reqbuf, DMREQ); + int err = Write(sock, reqbuf, bufsize); free(reqbuf); return (err); } static int -parse_rcvbuf(char *rcvbuf, int bufsize, struct dmres *dmres) +keep_reading(int sock, char *buf, int size) { - return 0; + int err = read(sock, buf, size); + while (err == -1 && errno == EINTR && sigint == 0) { + err = read(sock, buf, size); + } + + if (err == -1) + perror("read():"); + + return err; } static int recv_response(int sock, struct dmres *dmres) { int bufsize; - int kbytes = read(sock, &bufsize, sizeof(bufsize)); - if (kbytes == -1) { - perror("recv_response read():"); - } + keep_reading(sock, &bufsize, sizeof(bufsize)); + bufsize -= sizeof(bufsize); - char *rcvbuf = (char *) safe_malloc(bufsize); - - kbytes = read(sock, &rcvbuf, bufsize); + char *buf = (char *) Malloc(bufsize); + keep_reading(sock, buf, bufsize); - return (parse_rcvbuf(rcvbuf, bufsize, dmres)); + /* TODO: Check the error code in the response and set the + dmLastErrCode & dmLastErrString values */ } -FILE * -dmXGet(struct url *u, struct url_stat *us, const char *flags) +int +dm_request(struct dmreq dmreq) { - int udsock = socket(AF_UNIX, SOCK_STREAM, 0); + dms = socket(AF_UNIX, SOCK_STREAM, 0); struct sockaddr_un dms_addr; dms_addr.sun_family = AF_UNIX; strncpy(dms_addr.sun_path, DMS_UDS_PATH, sizeof(dms_addr.sun_path)); + int err = Connect(dms, (struct sockaddr *) &dms_addr, sizeof(dms_addr)); + + send_request(dms, dmreq); - int err = connect(udsock, (struct sockaddr *) &dms_addr, sizeof(dms_addr)); - if (err == -1) { - if (err == ENOENT) { - /* The DMS server process doesn't exist so start one */ - } else { - perror("dmXGet connect():"); - /* There was some error trying to connect to dms */ - } - } + struct dmres dmres; + recv_response(dms, &dmres); +} - err = send_request(udsock, u); - if (err == -1) { - perror("send_request :"); - } +static int +send_msg(int socket, struct msg msg) +{ + int bufsize = sizeof(bufsize); // Buffer size + bufsize += 1; // Op + bufsize += msg.len; // Signal number - struct dmres dmres; - for (;;) { - err = recv_response(udsock, &dmres); + char *sndbuf = (char *) Malloc(bufsize); + + int i = 0; + memcpy(sndbuf + i, &bufsize, sizeof(bufsize)); + i += sizeof(bufsize); - if (err == -1){ - perror("dmXGet read():"); - dmLastErrCode = errno; - strcpy(dmLastErrString, strerror(errno)); - return (NULL); - } - - if (dmres.op == DM_COMPLETE) { - FILE *savedf = fopen(dmres.fname, "r"); - if (savedf == NULL) { - dmLastErrCode = errno; - strcpy(dmLastErrString, strerror(errno)); - } - return (savedf); - } else if (dmres.op == DM_AUTH_REQ) { - err = dmAuthMethod(u); - if (err == -1) { - /* do what libfetch does when auth fails */ - } - send_request(udsock, u); - continue; - } else { - /* Received error code in response */ - } - } + *(sndbuf + i) = msg.op; + i++; + + memcpy(sndbuf + i, msg.buf, msg.len); + i += msg.len; - return (NULL); + int nbytes = Write(socket, sndbuf, bufsize); + free(sndbuf); + + return (nbytes); } -int -dmStat(struct url *u, struct url_stat *us, const char *flags) +void +dm_sighandler(int signal) { - us->size = -1; - us->mtime = 0; // Epoch - us->atime = us->mtime; + struct msg msg; + msg.op = DMSIG; + msg.buf = &signal; + msg.len = sizeof(signal); + send_msg(dms, msg); - return (-1); + if (signal == SIGINT) { + close(dms); + exit(2); + } } Modified: soc2013/ambarisha/head/usr.bin/dmget/dmget.h ============================================================================== --- soc2013/ambarisha/head/usr.bin/dmget/dmget.h Tue Jul 9 15:20:46 2013 (r254503) +++ soc2013/ambarisha/head/usr.bin/dmget/dmget.h Tue Jul 9 18:31:50 2013 (r254504) @@ -7,36 +7,16 @@ #include #include -/* TODO : Fix the path, make sure the perms on it are good */ -#define DMS_UDS_PATH "/tmp/dms.uds" +#include "dm.h" -#define DM_COMPLETE 1 -#define DM_AUTH_REQ 2 - - -struct dmres { - int op; - char fname[]; -}; - -#define DM_RESTART_CALLS 1 -#define DM_DEBUG 2 - -/* Authentication */ -extern auth_t dmAuthMethod; - -/* Last error code */ extern int dmLastErrCode; -#define MAXERRSTRING 256 -extern char dmLastErrString[MAXERRSTRING]; - -/* I/O timeout */ -extern int dmTimeout; - -/* Restart interrupted syscalls */ extern int dmRestartCalls; +extern char dmLastErrString[]; + +typedef int (*auth_t)(struct url *); +extern auth_t dmAuthMethod; -/* Extra verbosity */ -extern int dmDebug; +int dm_request(struct dmreq); +void dm_sighandler(int sig); #endif /* _DMCLIENT_H */ Modified: soc2013/ambarisha/head/usr.bin/dmget/fetch.c ============================================================================== --- soc2013/ambarisha/head/usr.bin/dmget/fetch.c Tue Jul 9 15:20:46 2013 (r254503) +++ soc2013/ambarisha/head/usr.bin/dmget/fetch.c Tue Jul 9 18:31:50 2013 (r254504) @@ -48,6 +48,7 @@ #include #include "dmget.h" +#include "dm.h" #define MINBUFSIZE 4096 #define TIMEOUT 120 @@ -95,26 +96,6 @@ static long http_timeout = TIMEOUT;/* default timeout for HTTP transfers */ static char *buf; /* transfer buffer */ - -/* - * Signal handler - */ -static void -sig_handler(int sig) -{ - switch (sig) { - case SIGALRM: - sigalrm = 1; - break; - case SIGINFO: - siginfo = 1; - break; - case SIGINT: - sigint = 1; - break; - } -} - struct xferstat { char name[64]; struct timeval start; /* start of transfer */ @@ -127,6 +108,9 @@ }; /* + * Signal handler + */ +/* * Compute and display ETA */ static const char * @@ -236,52 +220,6 @@ } /* - * Initialize the transfer statistics - */ -static void -stat_start(struct xferstat *xs, const char *name, off_t size, off_t offset) -{ - snprintf(xs->name, sizeof xs->name, "%s", name); - gettimeofday(&xs->start, NULL); - xs->last.tv_sec = xs->last.tv_usec = 0; - xs->size = size; - xs->offset = offset; - xs->rcvd = offset; - xs->lastrcvd = offset; - if (v_tty && v_level > 0) - stat_display(xs, 1); - else if (v_level > 0) - fprintf(stderr, "%-46s", xs->name); -} - -/* - * Update the transfer statistics - */ -static void -stat_update(struct xferstat *xs, off_t rcvd) -{ - xs->rcvd = rcvd; - if (v_tty && v_level > 0) - stat_display(xs, 0); -} - -/* - * Finalize the transfer statistics - */ -static void -stat_end(struct xferstat *xs) -{ - gettimeofday(&xs->last, NULL); - if (v_tty && v_level > 0) { - stat_display(xs, 2); - putc('\n', stderr); - } else if (v_level > 0) { - fprintf(stderr, " %s %s\n", - stat_bytes(xs->size), stat_bps(xs)); - } -} - -/* * Ask the user for authentication details */ static int @@ -328,444 +266,37 @@ static int fetch(char *URL, const char *path) { - struct url *url; - struct url_stat us; - struct stat sb, nsb; - struct xferstat xs; - FILE *f, *of; - size_t size, readcnt, wr; - off_t count; - char flags[8]; - const char *slash; - char *tmppath; - int r; - unsigned timeout; - char *ptr; - - f = of = NULL; - tmppath = NULL; - - timeout = 0; - *flags = 0; - count = 0; - - /* set verbosity level */ - if (v_level > 1) - strcat(flags, "v"); - if (v_level > 2) - dmDebug = 1; - - /* parse URL */ - url = NULL; - if (*URL == '\0') { - warnx("empty URL"); - goto failure; - } - if ((url = fetchParseURL(URL)) == NULL) { - warnx("%s: parse error", URL); - goto failure; - } - - /* if no scheme was specified, take a guess */ - if (!*url->scheme) { - if (!*url->host) - strcpy(url->scheme, SCHEME_FILE); - else if (strncasecmp(url->host, "ftp.", 4) == 0) - strcpy(url->scheme, SCHEME_FTP); - else if (strncasecmp(url->host, "www.", 4) == 0) - strcpy(url->scheme, SCHEME_HTTP); - } - - /* common flags */ - switch (family) { - case PF_INET: - strcat(flags, "4"); - break; - case PF_INET6: - strcat(flags, "6"); - break; - } - - /* FTP specific flags */ - if (strcmp(url->scheme, SCHEME_FTP) == 0) { - if (p_flag) - strcat(flags, "p"); - if (d_flag) - strcat(flags, "d"); - if (U_flag) - strcat(flags, "l"); - timeout = T_secs ? T_secs : ftp_timeout; - } - - /* HTTP specific flags */ - if (strcmp(url->scheme, SCHEME_HTTP) == 0 || - strcmp(url->scheme, SCHEME_HTTPS) == 0) { - if (d_flag) - strcat(flags, "d"); - if (A_flag) - strcat(flags, "A"); - timeout = T_secs ? T_secs : http_timeout; - if (i_flag) { - if (stat(i_filename, &sb)) { - warn("%s: stat()", i_filename); - goto failure; - } - url->ims_time = sb.st_mtime; - strcat(flags, "i"); - } - } - - /* set the protocol timeout. */ - dmTimeout = timeout; + struct dmreq dmreq; + dmreq.v_level = v_level; + dmreq.family = family; + dmreq.ftp_timeout = ftp_timeout; + dmreq.http_timeout = http_timeout; + dmreq.B_size = B_size; + dmreq.S_size = S_size; + dmreq.URL = URL; + printf("URL = %s\n", dmreq.URL); + dmreq.path = path; + dmreq.T_secs = T_secs; + + if (i_flag) dmreq.i_filename = i_filename; + else dmreq.i_filename = ""; + + dmreq.flags = 0; + if (A_flag != 0) dmreq.flags |= A_FLAG; + if (F_flag != 0) dmreq.flags |= F_FLAG; + if (R_flag != 0) dmreq.flags |= R_FLAG; + if (U_flag != 0) dmreq.flags |= U_FLAG; + if (d_flag != 0) dmreq.flags |= d_FLAG; + if (i_flag != 0) dmreq.flags |= i_FLAG; + if (l_flag != 0) dmreq.flags |= l_FLAG; + if (m_flag != 0) dmreq.flags |= m_FLAG; + if (n_flag != 0) dmreq.flags |= n_FLAG; + if (p_flag != 0) dmreq.flags |= p_FLAG; + if (r_flag != 0) dmreq.flags |= r_FLAG; + if (s_flag != 0) dmreq.flags |= s_FLAG; + if (o_stdout != 0) dmreq.flags |= O_STDOUT; - /* just print size */ - if (s_flag) { - if (timeout) - alarm(timeout); - r = dmStat(url, &us, flags); - if (timeout) - alarm(0); - if (sigalrm || sigint) - goto signal; - if (r == -1) { - warnx("%s", dmLastErrString); - goto failure; - } - if (us.size == -1) - printf("Unknown\n"); - else - printf("%jd\n", (intmax_t)us.size); - goto success; - } - - /* - * If the -r flag was specified, we have to compare the local - * and remote files, so we should really do a dmStat() - * first, but I know of at least one HTTP server that only - * sends the content size in response to GET requests, and - * leaves it out of replies to HEAD requests. Also, in the - * (frequent) case that the local and remote files match but - * the local file is truncated, we have sufficient information - * before the compare to issue a correct request. Therefore, - * we always issue a GET request as if we were sure the local - * file was a truncated copy of the remote file; we can drop - * the connection later if we change our minds. - */ - sb.st_size = -1; - if (!o_stdout) { - r = stat(path, &sb); - if (r == 0 && r_flag && S_ISREG(sb.st_mode)) { - url->offset = sb.st_size; - } else if (r == -1 || !S_ISREG(sb.st_mode)) { - /* - * Whatever value sb.st_size has now is either - * wrong (if stat(2) failed) or irrelevant (if the - * path does not refer to a regular file) - */ - sb.st_size = -1; - } - if (r == -1 && errno != ENOENT) { - warnx("%s: stat()", path); - goto failure; - } - } - - /* start the transfer */ - if (timeout) - alarm(timeout); - f = dmXGet(url, &us, flags); - if (timeout) - alarm(0); - if (sigalrm || sigint) - goto signal; - if (f == NULL) { - warnx("%s: %s", URL, dmLastErrString); - if (i_flag && strcmp(url->scheme, SCHEME_HTTP) == 0 - && dmLastErrCode == FETCH_OK - && strcmp(dmLastErrString, "Not Modified") == 0) { - /* HTTP Not Modified Response, return OK. */ - r = 0; - goto done; - } else - goto failure; - } - if (sigint) - goto signal; - - /* check that size is as expected */ - if (S_size) { - if (us.size == -1) { - warnx("%s: size unknown", URL); - } else if (us.size != S_size) { - warnx("%s: size mismatch: expected %jd, actual %jd", - URL, (intmax_t)S_size, (intmax_t)us.size); - goto failure; - } - } - - /* symlink instead of copy */ - if (l_flag && strcmp(url->scheme, "file") == 0 && !o_stdout) { - if (symlink(url->doc, path) == -1) { - warn("%s: symlink()", path); - goto failure; - } - goto success; - } - - if (us.size == -1 && !o_stdout && v_level > 0) - warnx("%s: size of remote file is not known", URL); - if (v_level > 1) { - if (sb.st_size != -1) - fprintf(stderr, "local size / mtime: %jd / %ld\n", - (intmax_t)sb.st_size, (long)sb.st_mtime); - if (us.size != -1) - fprintf(stderr, "remote size / mtime: %jd / %ld\n", - (intmax_t)us.size, (long)us.mtime); - } - - /* open output file */ - if (o_stdout) { - /* output to stdout */ - of = stdout; - } else if (r_flag && sb.st_size != -1) { - /* resume mode, local file exists */ - if (!F_flag && us.mtime && sb.st_mtime != us.mtime) { - /* no match! have to refetch */ - fclose(f); - /* if precious, warn the user and give up */ - if (R_flag) { - warnx("%s: local modification time " - "does not match remote", path); - goto failure_keep; - } - } else if (url->offset > sb.st_size) { - /* gap between what we asked for and what we got */ - warnx("%s: gap in resume mode", URL); - fclose(of); - of = NULL; - /* picked up again later */ - } else if (us.size != -1) { - if (us.size == sb.st_size) - /* nothing to do */ - goto success; - if (sb.st_size > us.size) { - /* local file too long! */ - warnx("%s: local file (%jd bytes) is longer " - "than remote file (%jd bytes)", path, - (intmax_t)sb.st_size, (intmax_t)us.size); - goto failure; - } - /* we got it, open local file */ - if ((of = fopen(path, "r+")) == NULL) { - warn("%s: fopen()", path); - goto failure; - } - /* check that it didn't move under our feet */ - if (fstat(fileno(of), &nsb) == -1) { - /* can't happen! */ - warn("%s: fstat()", path); - goto failure; - } - if (nsb.st_dev != sb.st_dev || - nsb.st_ino != nsb.st_ino || - nsb.st_size != sb.st_size) { - warnx("%s: file has changed", URL); - fclose(of); - of = NULL; - sb = nsb; - /* picked up again later */ - } - } - /* seek to where we left off */ - if (of != NULL && fseeko(of, url->offset, SEEK_SET) != 0) { - warn("%s: fseeko()", path); - fclose(of); - of = NULL; - /* picked up again later */ - } - } else if (m_flag && sb.st_size != -1) { - /* mirror mode, local file exists */ - if (sb.st_size == us.size && sb.st_mtime == us.mtime) - goto success; - } - - if (of == NULL) { - /* - * We don't yet have an output file; either this is a - * vanilla run with no special flags, or the local and - * remote files didn't match. - */ - - if (url->offset > 0) { - /* - * We tried to restart a transfer, but for - * some reason gave up - so we have to restart - * from scratch if we want the whole file - */ - url->offset = 0; - if ((f = dmXGet(url, &us, flags)) == NULL) { - warnx("%s: %s", URL, dmLastErrString); - goto failure; - } - if (sigint) - goto signal; - } - - /* construct a temp file name */ - if (sb.st_size != -1 && S_ISREG(sb.st_mode)) { - if ((slash = strrchr(path, '/')) == NULL) - slash = path; - else - ++slash; - asprintf(&tmppath, "%.*s.dm.XXXXXX.%s", - (int)(slash - path), path, slash); - if (tmppath != NULL) { - if (mkstemps(tmppath, strlen(slash) + 1) == -1) { - warn("%s: mkstemps()", path); - goto failure; - } - of = fopen(tmppath, "w"); - chown(tmppath, sb.st_uid, sb.st_gid); - chmod(tmppath, sb.st_mode & ALLPERMS); - } - } - if (of == NULL) - of = fopen(path, "w"); - if (of == NULL) { - warn("%s: open()", path); - goto failure; - } - } - count = url->offset; - - /* start the counter */ - stat_start(&xs, path, us.size, count); - - sigalrm = siginfo = sigint = 0; - - /* suck in the data */ - signal(SIGINFO, sig_handler); - while (!sigint) { - if (us.size != -1 && us.size - count < B_size && - us.size - count >= 0) - size = us.size - count; - else - size = B_size; - if (siginfo) { - stat_end(&xs); - siginfo = 0; - } - - if (size == 0) - break; - - if ((readcnt = fread(buf, 1, size, f)) < size) { - if (ferror(f) && errno == EINTR && !sigint) - clearerr(f); - else if (readcnt == 0) - break; - } - - stat_update(&xs, count += readcnt); - for (ptr = buf; readcnt > 0; ptr += wr, readcnt -= wr) - if ((wr = fwrite(ptr, 1, readcnt, of)) < readcnt) { - if (ferror(of) && errno == EINTR && !sigint) - clearerr(of); - else - break; - } - if (readcnt != 0) - break; - } - if (!sigalrm) - sigalrm = ferror(f) && errno == ETIMEDOUT; - signal(SIGINFO, SIG_DFL); - - stat_end(&xs); - - /* - * If the transfer timed out or was interrupted, we still want to - * set the mtime in case the file is not removed (-r or -R) and - * the user later restarts the transfer. - */ - signal: - /* set mtime of local file */ - if (!n_flag && us.mtime && !o_stdout && of != NULL && - (stat(path, &sb) != -1) && sb.st_mode & S_IFREG) { - struct timeval tv[2]; - - fflush(of); - tv[0].tv_sec = (long)(us.atime ? us.atime : us.mtime); - tv[1].tv_sec = (long)us.mtime; - tv[0].tv_usec = tv[1].tv_usec = 0; - if (utimes(tmppath ? tmppath : path, tv)) - warn("%s: utimes()", tmppath ? tmppath : path); - } - - /* timed out or interrupted? */ - if (sigalrm) - warnx("transfer timed out"); - if (sigint) { - warnx("transfer interrupted"); - goto failure; - } - - /* timeout / interrupt before connection completley established? */ - if (f == NULL) - goto failure; - - if (!sigalrm) { - /* check the status of our files */ - if (ferror(f)) - warn("%s", URL); - if (ferror(of)) - warn("%s", path); - if (ferror(f) || ferror(of)) - goto failure; - } - - /* did the transfer complete normally? */ - if (us.size != -1 && count < us.size) { - warnx("%s appears to be truncated: %jd/%jd bytes", - path, (intmax_t)count, (intmax_t)us.size); - goto failure_keep; - } - - /* - * If the transfer timed out and we didn't know how much to - * expect, assume the worst (i.e. we didn't get all of it) - */ - if (sigalrm && us.size == -1) { - warnx("%s may be truncated", path); - goto failure_keep; - } - - success: - r = 0; - if (tmppath != NULL && rename(tmppath, path) == -1) { - warn("%s: rename()", path); - goto failure_keep; - } - goto done; - failure: - if (of && of != stdout && !R_flag && !r_flag) - if (stat(path, &sb) != -1 && (sb.st_mode & S_IFREG)) - unlink(tmppath ? tmppath : path); - if (R_flag && tmppath != NULL && sb.st_size == -1) - rename(tmppath, path); /* ignore errors here */ - failure_keep: - r = -1; - goto done; - done: - if (f) - fclose(f); - if (of && of != stdout) - fclose(of); - if (url) - fetchFreeURL(url); - if (tmppath != NULL) - free(tmppath); - return (r); + return (dm_request(dmreq)); } static void *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***