Add the -W options, which acts the same as -w but will generate
unique names based on the submitted filename, a strftime(3) format string and a two digit sequence number. By default the strftime(3) format string is %Y%m%d (YYYYMMDD), but this can be changed by the -F option. PR: bin/106049 (based on patch in that PR) Approved by: grog@ (mentor)
This commit is contained in:
parent
4b07bf84dd
commit
dba0fd308e
@ -5,6 +5,7 @@ PROG= tftpd
|
||||
SRCS= tftpd.c tftpsubs.c
|
||||
DPADD= ${LIBUTIL}
|
||||
LDADD= -lutil
|
||||
WFORMAT=0
|
||||
MAN= tftpd.8
|
||||
CFLAGS+=-I${.CURDIR}/../../usr.bin/tftp
|
||||
.PATH: ${.CURDIR}/../../usr.bin/tftp
|
||||
|
@ -40,7 +40,8 @@
|
||||
.Nd Internet Trivial File Transfer Protocol server
|
||||
.Sh SYNOPSIS
|
||||
.Nm tftpd
|
||||
.Op Fl cClnw
|
||||
.Op Fl cClnwW
|
||||
.Op Fl F Ar strftime-format
|
||||
.Op Fl s Ar directory
|
||||
.Op Fl u Ar user
|
||||
.Op Fl U Ar umask
|
||||
@ -142,6 +143,13 @@ except it falls back to
|
||||
specified via
|
||||
.Fl s
|
||||
if a directory does not exist for the client's IP.
|
||||
.It Fl F
|
||||
Use this
|
||||
.Xr strftime 3
|
||||
compatible format string for the creation of the suffix if
|
||||
.Fl W
|
||||
is specified.
|
||||
By default the string "%Y%m%d" is used.
|
||||
.It Fl l
|
||||
Log all requests using
|
||||
.Xr syslog 3
|
||||
@ -184,6 +192,17 @@ Allow write requests to create new files.
|
||||
By default
|
||||
.Nm
|
||||
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 YYYYMMDD.nn sequence number to the end of the filename.
|
||||
Note that the string YYYYMMDD can be changed the
|
||||
.Fl F
|
||||
option.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr tftp 1 ,
|
||||
@ -212,10 +231,17 @@ the
|
||||
.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 F
|
||||
and
|
||||
.Fl W
|
||||
options were introduced in
|
||||
.Fx 7 .
|
||||
.Pp
|
||||
.Sh BUGS
|
||||
Files larger than 33488896 octets (65535 blocks) cannot be transferred
|
||||
without client and server supporting blocksize negotiation (RFC1783).
|
||||
|
@ -110,6 +110,8 @@ static int suppress_naks;
|
||||
static int logging;
|
||||
static int ipchroot;
|
||||
static int create_new = 0;
|
||||
static char *newfile_format = "%Y%m%d";
|
||||
static int increase_name = 0;
|
||||
static mode_t mask = S_IWGRP|S_IWOTH;
|
||||
|
||||
static const char *errtomsg(int);
|
||||
@ -134,7 +136,7 @@ main(int argc, char *argv[])
|
||||
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, "cCF:lns:u:U:wW")) != -1) {
|
||||
switch (ch) {
|
||||
case 'c':
|
||||
ipchroot = 1;
|
||||
@ -142,6 +144,9 @@ main(int argc, char *argv[])
|
||||
case 'C':
|
||||
ipchroot = 2;
|
||||
break;
|
||||
case 'F':
|
||||
newfile_format = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
logging = 1;
|
||||
break;
|
||||
@ -160,6 +165,10 @@ main(int argc, char *argv[])
|
||||
case 'w':
|
||||
create_new = 1;
|
||||
break;
|
||||
case 'W':
|
||||
create_new = 1;
|
||||
increase_name = 1;
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_WARNING, "ignoring unknown option -%c", ch);
|
||||
}
|
||||
@ -512,6 +521,57 @@ tftp(struct tftphdr *tp, int size)
|
||||
|
||||
FILE *file;
|
||||
|
||||
/*
|
||||
* Find the next value for YYYYMMDD.nn when the file to be written should
|
||||
* be unique. Due to the limitations of nn, we will fail if nn reaches 100.
|
||||
* Besides, that is four updates per hour on a file, which is kind of
|
||||
* execessive anyway.
|
||||
*/
|
||||
static int
|
||||
find_next_name(char *filename, int *fd)
|
||||
{
|
||||
int i;
|
||||
time_t tval;
|
||||
size_t len;
|
||||
struct tm lt;
|
||||
char yyyymmdd[MAXPATHLEN];
|
||||
char newname[MAXPATHLEN];
|
||||
struct stat sb;
|
||||
int ret;
|
||||
|
||||
/* Create the YYYYMMDD part of the filename */
|
||||
time(&tval);
|
||||
lt = *localtime(&tval);
|
||||
len = strftime(yyyymmdd, sizeof(yyyymmdd), newfile_format, <);
|
||||
if (len == 0) {
|
||||
syslog(LOG_WARNING,
|
||||
"Filename suffix too long (%d characters maximum)",
|
||||
MAXPATHLEN);
|
||||
return (EACCESS);
|
||||
}
|
||||
|
||||
/* Make sure the new filename is not too long */
|
||||
if (strlen(filename) > MAXPATHLEN - len - 5) {
|
||||
syslog(LOG_WARNING,
|
||||
"Filename too long (%d characters, %d maximum)",
|
||||
strlen(filename), MAXPATHLEN - len - 5);
|
||||
return (EACCESS);
|
||||
}
|
||||
|
||||
/* Find the first file which doesn't exist */
|
||||
for (i = 0; i < 100; i++) {
|
||||
sprintf(newname, "%s.%s.%02d", filename, yyyymmdd, i);
|
||||
*fd = open(newname,
|
||||
O_WRONLY | O_CREAT | O_EXCL,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP |
|
||||
S_IWGRP | S_IROTH | S_IWOTH);
|
||||
if (*fd > 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (EEXIST);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate file access. Since we
|
||||
* have no uid or gid, for now require
|
||||
@ -528,6 +588,7 @@ validate_access(char **filep, int mode)
|
||||
{
|
||||
struct stat stbuf;
|
||||
int fd;
|
||||
int error;
|
||||
struct dirlist *dirp;
|
||||
static char pathname[MAXPATHLEN];
|
||||
char *filename = *filep;
|
||||
@ -610,10 +671,18 @@ validate_access(char **filep, int mode)
|
||||
if (mode == RRQ)
|
||||
fd = open(filename, O_RDONLY);
|
||||
else {
|
||||
if (create_new)
|
||||
fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0666);
|
||||
else
|
||||
fd = open(filename, O_WRONLY|O_TRUNC);
|
||||
if (create_new) {
|
||||
if (increase_name) {
|
||||
error = find_next_name(filename, &fd);
|
||||
if (error > 0)
|
||||
return (error + 100);
|
||||
} else
|
||||
fd = open(filename,
|
||||
O_WRONLY | O_TRUNC | O_CREAT,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP |
|
||||
S_IWGRP | S_IROTH | S_IWOTH );
|
||||
} else
|
||||
fd = open(filename, O_WRONLY | O_TRUNC);
|
||||
}
|
||||
if (fd < 0)
|
||||
return (errno + 100);
|
||||
|
Loading…
Reference in New Issue
Block a user