socsvn commit: r254504 - in soc2013/ambarisha/head/usr.bin: dmget dms

ambarisha at FreeBSD.org ambarisha at FreeBSD.org
Tue Jul 9 18:31:51 UTC 2013


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 <bsd.own.mk>
 
-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 <sys/param.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+#include <fetch.h>
+
+/* 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 <sys/socket.h>
 #include <sys/time.h>
 #include <sys/un.h>
@@ -9,7 +8,9 @@
 #include <string.h>
 
 
+#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 <stdio.h>
 #include <fetch.h>
 
-/* 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 <fetch.h>
 
 #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 ***


More information about the svn-soc-all mailing list