Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Aug 2002 21:33:11 -0500 (CDT)
From:      "Chris S.J. Peron" <maneo@bsdpro.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/42179: [patch] fetch: memory leak and general optimizations
Message-ID:  <200208300233.g7U2XB7F023811@xor.sqrt.ca>

next in thread | raw e-mail | index | archive | help

>Number:         42179
>Category:       bin
>Synopsis:       [patch] fetch: memory leak and general optimizations
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Aug 29 19:40:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Chris S.J. Peron
>Release:        FreeBSD 4.6-STABLE i386
>Organization:
>Environment:
System: FreeBSD xor.sqrt.ca 4.6-STABLE FreeBSD 4.6-STABLE #3: Tue Aug 13 17:17:48 CDT 2002 cperon@xor.sqrt.ca:/usr/src/sys/compile/opcode i386


	
>Description:

	main allocates a transfer buffer that is never free'ed when fetch
	is done with it.

	Currently, fetch has used the integer storage class for essentially
	all boolean variables. (16 which takes up 16*5 bytes (64)) when it could be
	using a single integer and unique bitmasks.
	
>How-To-Repeat:

	N/A
	
>Fix:

--- /usr/src/usr.bin/fetch/fetch.c.leaks	Thu Aug 29 09:51:43 2002
+++ /usr/src/usr.bin/fetch/fetch.c	Thu Aug 29 21:14:43 2002
@@ -48,32 +48,36 @@
 
 #define MINBUFSIZE	4096
 
-/* Option flags */
-int	 A_flag;	/*    -A: do not follow 302 redirects */
-int	 a_flag;	/*    -a: auto retry */
+/*
+ * bit masks for command line options.
+ */
+#define	FL_A	(1 << 0)	/*    -A: do not follow 302 redirects */
+#define	FL_a	(1 << 1)	/*    -a: auto retry */
+#define	FL_b	(1 << 2)	/*!   -b: workaround TCP bug */
+#define	FL_d	(1 << 3)	/*    -d: direct connection */
+#define	FL_F	(1 << 4)	/*    -F: restart without checking mtime  */
+#define	FL_l	(1 << 5)	/*    -l: link rather than copy file: URLs */
+#define	FL_o	(1 << 6)	/*    -o: specify output file */
+#define	FL_m	(1 << 7)	/* -[Mm]: mirror mode */
+#define	FL_n	(1 << 8)	/*    -n: do not preserve modification time */
+#define	FL_p	(1 << 9)	/* -[Pp]: use passive FTP */
+#define	FL_R	(1 << 10)	/*    -R: don't delete partially transferred files */
+#define	FL_r	(1 << 11)	/*    -r: restart previously interrupted transfer */
+#define	FL_s	(1 << 12)	/*    -s: show size, don't fetch */
+#define	FL_t	(1 << 13)	/*!   -t: workaround TCP bug */
+#define	FL_U	(1 << 14)	/*    -U: do not use high ports */
+#define	FL_1	(1 << 15)	/*    -1: stop at first successful file */
+
+u_int	cmd_opts = 0;	/* bit field for command line options */
 off_t	 B_size;	/*    -B: buffer size */
-int	 b_flag;	/*!   -b: workaround TCP bug */
 char    *c_dirname;	/*    -c: remote directory */
-int	 d_flag;	/*    -d: direct connection */
-int	 F_flag;	/*    -F: restart without checking mtime  */
 char	*f_filename;	/*    -f: file to fetch */
 char	*h_hostname;	/*    -h: host to fetch from */
-int	 l_flag;	/*    -l: link rather than copy file: URLs */
-int	 m_flag;	/* -[Mm]: mirror mode */
-int	 n_flag;	/*    -n: do not preserve modification time */
-int	 o_flag;	/*    -o: specify output file */
 int	 o_directory;	/*        output file is a directory */
 char	*o_filename;	/*        name of output file */
 int	 o_stdout;	/*        output file is stdout */
-int	 once_flag;	/*    -1: stop at first successful file */
-int	 p_flag;	/* -[Pp]: use passive FTP */
-int	 R_flag;	/*    -R: don't delete partially transferred files */
-int	 r_flag;	/*    -r: restart previously interrupted transfer */
 off_t	 S_size;        /*    -S: require size to match */
-int	 s_flag;        /*    -s: show size, don't fetch */
 u_int	 T_secs = 120;	/*    -T: transfer timeout in seconds */
-int	 t_flag;	/*!   -t: workaround TCP bug */
-int	 U_flag;	/*    -U: do not use high ports */
 int	 v_level = 1;	/*    -v: verbosity level */
 int	 v_tty;		/*        stdout is a tty */
 pid_t	 pgrp;		/*        our process group */
@@ -304,20 +308,20 @@
 
 	/* FTP specific flags */
 	if (strcmp(url->scheme, "ftp") == 0) {
-		if (p_flag)
+		if (cmd_opts & FL_p)
 			strcat(flags, "p");
-		if (d_flag)
+		if (cmd_opts & FL_d)
 			strcat(flags, "d");
-		if (U_flag)
+		if (cmd_opts & FL_U)
 			strcat(flags, "l");
 		timeout = T_secs ? T_secs : ftp_timeout;
 	}
 
 	/* HTTP specific flags */
 	if (strcmp(url->scheme, "http") == 0) {
-		if (d_flag)
+		if (cmd_opts & FL_d)
 			strcat(flags, "d");
-		if (A_flag)
+		if (cmd_opts & FL_A)
 			strcat(flags, "A");
 		timeout = T_secs ? T_secs : http_timeout;
 	}
@@ -326,7 +330,7 @@
 	fetchTimeout = timeout;
 
 	/* just print size */
-	if (s_flag) {
+	if (cmd_opts & FL_s) {
 		if (fetchStat(url, &us, flags) == -1)
 			goto failure;
 		if (us.size == -1)
@@ -354,7 +358,7 @@
 		warnx("%s: stat()", path);
 		goto failure;
 	}
-	if (!o_stdout && r_flag && S_ISREG(sb.st_mode))
+	if (!o_stdout && (cmd_opts & FL_r) && S_ISREG(sb.st_mode))
 		url->offset = sb.st_size;
 
 	/* start the transfer */
@@ -378,7 +382,7 @@
 	}
 
 	/* symlink instead of copy */
-	if (l_flag && strcmp(url->scheme, "file") == 0 && !o_stdout) {
+	if ((cmd_opts & FL_l) && strcmp(url->scheme, "file") == 0 && !o_stdout) {
 		if (symlink(url->doc, path) == -1) {
 			warn("%s: symlink()", path);
 			goto failure;
@@ -401,13 +405,13 @@
 	if (o_stdout) {
 		/* output to stdout */
 		of = stdout;
-	} else if (r_flag && sb.st_size != -1) {
+	} else if ((cmd_opts & FL_r) && sb.st_size != -1) {
 		/* resume mode, local file exists */
-		if (!F_flag && us.mtime && sb.st_mtime != us.mtime) {
+		if (!(cmd_opts & FL_F) && 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) {
+			if (cmd_opts & FL_R) {
 				warnx("%s: local modification time "
 				    "does not match remote", path);
 				goto failure_keep;
@@ -443,7 +447,7 @@
 				sb = nsb;
 			}
 		}
-	} else if (m_flag && sb.st_size != -1) {
+	} else if ((cmd_opts & FL_m) && sb.st_size != -1) {
 		/* mirror mode, local file exists */
 		if (sb.st_size == us.size && sb.st_mtime == us.mtime)
 			goto success;
@@ -535,13 +539,16 @@
 	}
 	signal(SIGINFO, SIG_DFL);
 
+	/* free transfer buffer */
+	free(buf);
+
 	if (timeout)
 		alarm(0);
 
 	stat_end(&xs);
 
 	/* set mtime of local file */
-	if (!n_flag && us.mtime && !o_stdout
+	if (!(cmd_opts & FL_n) && us.mtime && !o_stdout
 	    && (stat(path, &sb) != -1) && sb.st_mode & S_IFREG) {
 		struct timeval tv[2];
 	
@@ -596,10 +603,10 @@
 	}
 	goto done;
  failure:
-	if (of && of != stdout && !R_flag && !r_flag)
+	if (of && of != stdout && !(cmd_opts & FL_R) && !(cmd_opts & FL_r))
 		if (stat(path, &sb) != -1 && (sb.st_mode & S_IFREG))
 			unlink(tmppath ? tmppath : path);
-	if (R_flag && tmppath != NULL && sb.st_size == -1)
+	if ((cmd_opts & FL_R) && tmppath != NULL && sb.st_size == -1)
 		rename(tmppath, path); /* ignore errors here */
  failure_keep:
 	r = -1;
@@ -658,7 +665,7 @@
 	    "146AaB:bc:dFf:Hh:lMmnPpo:qRrS:sT:tUvw:")) != EOF)
 		switch (c) {
 		case '1':
-			once_flag = 1;
+			cmd_opts |= FL_1;
 			break;
 		case '4':
 			family = PF_INET;
@@ -667,10 +674,10 @@
 			family = PF_INET6;
 			break;
 		case 'A':
-			A_flag = 1;
+			cmd_opts |= FL_A;
 			break;
 		case 'a':
-			a_flag = 1;
+			cmd_opts |= FL_a;
 			break;
 		case 'B':
 			if (parseoff(optarg, &B_size) == -1)
@@ -678,16 +685,16 @@
 			break;
 		case 'b':
 			warnx("warning: the -b option is deprecated");
-			b_flag = 1;
+			cmd_opts |= FL_b;
 			break;
 		case 'c':
 			c_dirname = optarg;
 			break;
 		case 'd':
-			d_flag = 1;
+			cmd_opts |= FL_d;
 			break;
 		case 'F':
-			F_flag = 1;
+			cmd_opts |= FL_F;
 			break;
 		case 'f':
 			f_filename = optarg;
@@ -700,61 +707,61 @@
 			h_hostname = optarg;
 			break;
 		case 'l':
-			l_flag = 1;
+			cmd_opts |= FL_l;
 			break;
 		case 'o':
-			o_flag = 1;
+			cmd_opts |= FL_o;
 			o_filename = optarg;
 			break;
 		case 'M':
 		case 'm':
-			if (r_flag)
+			if (cmd_opts & FL_r)
 				errx(1, "the -m and -r flags "
 				    "are mutually exclusive");
-			m_flag = 1;
+			cmd_opts |= FL_m;
 			break;
 		case 'n':
-			n_flag = 1;
+			cmd_opts |= FL_n;
 			break;
 		case 'P':
 		case 'p':
-			p_flag = 1;
+			cmd_opts |= FL_p;
 			break;
 		case 'q':
 			v_level = 0;
 			break;
 		case 'R':
-			R_flag = 1;
+			cmd_opts |= FL_R;
 			break;
 		case 'r':
-			if (m_flag)
+			if (cmd_opts & FL_m)
 				errx(1, "the -m and -r flags "
 				    "are mutually exclusive");
-			r_flag = 1;
+			cmd_opts |= FL_r;
 			break;
 		case 'S':
 			if (parseoff(optarg, &S_size) == -1)
 				errx(1, "invalid size (%s)", optarg);
 			break;
 		case 's':
-			s_flag = 1;
+			cmd_opts |= FL_s;
 			break;
 		case 'T':
 			if (parseint(optarg, &T_secs) == -1)
 				errx(1, "invalid timeout (%s)", optarg);
 			break;
 		case 't':
-			t_flag = 1;
+			cmd_opts |= FL_t;
 			warnx("warning: the -t option is deprecated");
 			break;
 		case 'U':
-			U_flag = 1;
+			cmd_opts |= FL_U;
 			break;
 		case 'v':
 			v_level++;
 			break;
 		case 'w':
-			a_flag = 1;
+			cmd_opts |= FL_a;
 			if (parseint(optarg, &w_secs) == -1)
 				errx(1, "invalid delay (%s)", optarg);
 			break;
@@ -788,6 +795,7 @@
 	/* allocate buffer */
 	if (B_size < MINBUFSIZE)
 		B_size = MINBUFSIZE;
+
 	if ((buf = malloc(B_size)) == NULL)
 		errx(1, "%s", strerror(ENOMEM));
 
@@ -817,7 +825,7 @@
 	fetchRestartCalls = 0;
 
 	/* output file */
-	if (o_flag) {
+	if (cmd_opts & FL_o) {
 		if (strcmp(o_filename, "-") == 0) {
 			o_stdout = 1;
 		} else if (stat(o_filename, &sb) == -1) {
@@ -856,7 +864,7 @@
 	
 		fetchLastErrCode = 0;
 	
-		if (o_flag) {
+		if (cmd_opts & FL_o) {
 			if (o_stdout) {
 				e = fetch(*argv, "-");
 			} else if (o_directory) {
@@ -873,8 +881,8 @@
 		if (sigint)
 			kill(getpid(), SIGINT);
 	
-		if (e == 0 && once_flag)
-			exit(0);
+		if (e == 0 && (cmd_opts & FL_1))
+			exit(EX_OK);
 	
 		if (e) {
 			r = 1;
@@ -889,7 +897,7 @@
 					    "before retrying\n", w_secs);
 				if (w_secs)
 					sleep(w_secs);
-				if (a_flag)
+				if (cmd_opts & FL_a)
 					continue;
 			}
 		}
	


>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200208300233.g7U2XB7F023811>