Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Nov 2006 16:31:40 +1100 (EST)
From:      Edwin Groothuis <edwin@mavetju.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/106049: [patch] tftpd - improve -w option to support unique filenames
Message-ID:  <20061130053140.8BD5CFB@k7.mavetju>
Resent-Message-ID: <200611300540.kAU5eI4x025297@freefall.freebsd.org>

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

>Number:         106049
>Category:       bin
>Synopsis:       [patch] tftpd - improve -w option to support unique filenames
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Nov 30 05:40:12 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Edwin Groothuis
>Release:        FreeBSD 6.1-RELEASE i386
>Organization:
-
>Environment:
System: FreeBSD k7.mavetju 6.1-RELEASE FreeBSD 6.1-RELEASE #0: Sun May 7 04:42:56 UTC 2006 root@opus.cse.buffalo.edu:/usr/obj/usr/src/sys/SMP i386


>Description:

I'm managing a large collection of network devices which, once per
month, I want to download the configuration from for safekeeping
and historical reasons.

Up to now it always was a fight with keeping track of the names of
new devices to make sure their filenames were touched in /tftpboot
and set with the proper permissions. The -w option resolved this a
little bit, but it still caused the configurations to be overwritten
without my knowledge.

So I added the -W option, which behaves the same as -w, but adds a
three digit postfix to the file to be created so it will never
overwrite old ones.

>How-To-Repeat:
>Fix:


--- tftpd.c.orig	Tue Nov 28 22:54:43 2006
+++ tftpd.c	Thu Nov 30 16:17:32 2006
@@ -110,6 +110,7 @@
 static int	logging;
 static int	ipchroot;
 static int	create_new = 0;
+static int	increase_name = 0;
 static mode_t	mask = S_IWGRP|S_IWOTH;
 
 static const char *errtomsg(int);
@@ -134,7 +135,7 @@
 	tzset();			/* syslog in localtime */
 
 	openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
-	while ((ch = getopt(argc, argv, "cClns:u:U:w")) != -1) {
+	while ((ch = getopt(argc, argv, "cClns:u:U:wW")) != -1) {
 		switch (ch) {
 		case 'c':
 			ipchroot = 1;
@@ -160,6 +161,10 @@
 		case 'w':
 			create_new = 1;
 			break;
+		case 'W':
+			create_new = 1;
+			increase_name = 1;
+			break;
 		default:
 			syslog(LOG_WARNING, "ignoring unknown option -%c", ch);
 		}
@@ -610,9 +615,41 @@
 	if (mode == RRQ)
 		fd = open(filename, O_RDONLY);
 	else {
-		if (create_new)
-			fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0666);
-		else
+		if (create_new) {
+			if (increase_name) {
+				int i;
+
+				/* Make sure the new filename is not too long */
+				if (strlen(filename) > MAXPATHLEN-4) {
+					syslog(LOG_WARNING,
+						"Filename too long (%ld characters, %d maximum)",
+						strlen(filename), MAXPATHLEN);
+					return (EACCESS);
+				}
+
+				/* If we can't find anything, fail */
+				fd = -1;
+
+				/* Find the first file which doesn't exist */
+				for (i = 0; i < 1000; i++) {
+					char newname[MAXPATHLEN];
+					struct stat sb;
+					int ret;
+
+					sprintf(newname, "%s.%d", filename, i);
+					ret = stat(newname, &sb);
+					if (ret == -1 && errno == ENOENT) {
+						fd = open(newname,
+							O_WRONLY|O_TRUNC|
+							O_CREAT, 0666);
+						break;
+					}
+				}
+			} else {
+				fd = open(filename,
+					O_WRONLY|O_TRUNC|O_CREAT, 0666);
+			}
+		} else
 			fd = open(filename, O_WRONLY|O_TRUNC);
 	}
 	if (fd < 0)

--- tftpd.8.orig	Tue Nov 28 22:54:51 2006
+++ tftpd.8	Thu Nov 30 16:23:34 2006
@@ -40,7 +40,7 @@
 .Nd Internet Trivial File Transfer Protocol server
 .Sh SYNOPSIS
 .Nm /usr/libexec/tftpd
-.Op Fl cClnw
+.Op Fl cClnwW
 .Op Fl s Ar directory
 .Op Fl u Ar user
 .Op Fl U Ar umask
@@ -171,10 +171,17 @@
 The default is 022
 .Pq Dv S_IWGRP | S_IWOTH .
 .It Fl w
-Allow writes requests to create new files.
+Allow write requests to create new files.
 By default
 .Nm
-requires that the file specified in a write request exist.
+requires that the file specified in a write request exist. Note that this
+only works in directories writable by the user specified with
+.Fl u
+option.
+.It Fl W
+As
+.Fl w
+but append a three digit sequence number to the end of the filename.
 .El
 .Sh SEE ALSO
 .Xr tftp 1 ,
@@ -200,10 +207,14 @@
 .Fl u
 option was introduced in
 .Fx 4.2 ,
-and the
+the
 .Fl c
 option was introduced in
-.Fx 4.3 .
+.Fx 4.3 ,
+and the
+.Fl W
+option was introduced in
+.Fx 6.3 .
 .Sh BUGS
 Files larger than 33488896 octets (65535 blocks) cannot be transferred
 without client and server supporting blocksize negotiation (RFC1783).
>Release-Note:
>Audit-Trail:
>Unformatted:



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