public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/tftp] rawhide: sync patches with upstream and enable upstream test-suite
@ 2026-09-14  8:20 
  0 siblings, 0 replies; only message in thread
From:  @ 2026-09-14  8:20 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/tftp
Branch : rawhide
Commit : f2db3dbe0e72bb74d1134fa4752370eceeee947a
Author : Lukáš Zaoral <lzaoral@redhat.com>
Date   : 2026-09-11T13:18:29+02:00
Stats  : +392/-179 in 6 file(s)
URL    : https://src.fedoraproject.org/rpms/tftp/c/f2db3dbe0e72bb74d1134fa4752370eceeee947a?branch=rawhide

Log:
sync patches with upstream and enable upstream test-suite

---
diff --git a/tftp-0.42-tftpboot.patch b/tftp-0.42-tftpboot.patch
deleted file mode 100644
index fbd7218..0000000
--- a/tftp-0.42-tftpboot.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-diff --git a/README.security b/README.security
-index 8ff9e85..df2fa38 100644
---- a/README.security
-+++ b/README.security
-@@ -23,10 +23,10 @@ probably the following:
- 
- 1. Create a separate "tftpd" user and group only used for tftpd;
- 2. Have all your boot files in a single directory tree (usually called
--   /tftpboot).
--3. Specify "-p -u tftpd -s /tftpboot" on the tftpd command line; if
-+   /var/lib/tftpboot).
-+3. Specify "-p -u tftpd -s /var/lib/tftpboot" on the tftpd command line; if
-    you want clients to be able to create files use
--   "-p -c -U 002 -u tftpd -s /tftpboot" (replace 002 with whatever
-+   "-p -c -U 002 -u tftpd -s /var/lib/tftpboot" (replace 002 with whatever
-    umask is appropriate for your setup.)
- 
- When the -s (chroot) option is used, tftpd needs to be started as
-@@ -51,12 +51,12 @@ directly.  Thus, if your /etc/inetd.conf looks like this (all on one
- line):
- 
- tftp	dgram	udp	wait	root	/usr/sbin/tcpd
--/usr/sbin/in.tftpd -s /tftpboot -r blksize
-+/usr/sbin/in.tftpd -s /var/lib/tftpboot -r blksize
- 
- ... it's better to change to ...
- 
- tftp	dgram	udp	wait	root	/usr/sbin/in.tftpd
--in.tftpd -s /tftpboot -r blksize
-+in.tftpd -s /var/lib/tftpboot -r blksize
- 
- You should make sure that you are using "wait" option in tftpd; you
- also need to have tftpd spawned as root in order for chroot (-s) to
-diff --git a/tftp-xinetd b/tftp-xinetd
-index 982fe09..d04b48a 100644
---- a/tftp-xinetd
-+++ b/tftp-xinetd
-@@ -10,7 +10,7 @@ service tftp
- 	wait			= yes
- 	user			= root
- 	server			= /usr/sbin/in.tftpd
--	server_args		= -s /tftpboot
-+	server_args		= -s /var/lib/tftpboot
- 	disable			= yes
- 	per_source		= 11
- 	cps			= 100 2
-diff --git a/tftpd/sample.rules b/tftpd/sample.rules
-index 55b56be..1741a4c 100644
---- a/tftpd/sample.rules
-+++ b/tftpd/sample.rules
-@@ -29,5 +29,5 @@ rg	\\		/		# Convert backslashes to slashes
- rg	\#		@		# Convert hash marks to @ signs
- rg	/../		/..no../	# Convert /../ to /..no../
- e	^ok/				# These are always ok
--r	^[^/]		/tftpboot/\0	# Convert non-absolute files
-+r	^[^/]		/var/lib/tftpboot/\0	# Convert non-absolute files
- a	\.pvt$				# Reject requests for private files

diff --git a/tftp-enhanced-logging.patch b/tftp-enhanced-logging.patch
index 71f6e96..18b4a70 100644
--- a/tftp-enhanced-logging.patch
+++ b/tftp-enhanced-logging.patch
@@ -1,79 +1,147 @@
+From ab93a245747ada8948f4594de54a4b2b30c4b462 Mon Sep 17 00:00:00 2001
+From: "H. Peter Anvin" <hpa@zytor.com>
+Date: Tue, 8 Sep 2026 17:33:47 -0700
+Subject: [PATCH] tftpd: log failed and completed transfers
+
+Log file-not-found requests and successful transfers with the client address.
+
+Retain the requested filename before an upload reuses the request buffer for
+DATA packets, so completion logging always reports the correct name.
+
+Based on patch from the Fedora SRPM.
+
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+---
+ tftpd/tftpd.c | 42 +++++++++++++++++++++++++++++++++---------
+ tftpd/tftpd.h |  6 ++++--
+ 2 files changed, 37 insertions(+), 11 deletions(-)
+
 diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c
-index aaf1f9c..b8ef4f4 100644
+index 8287161..1109bbf 100644
 --- a/tftpd/tftpd.c
 +++ b/tftpd/tftpd.c
-@@ -1059,7 +1059,7 @@ int main(int argc, char **argv)
+@@ -1081,8 +1081,10 @@ int main(int argc, char **argv)
  static char *rewrite_access(const struct formats *,
  			    char *, int, int, const char **);
  static int validate_access(char *, int, const struct formats *, const char **);
 -static void tftp_sendfile(const struct formats *, struct tftphdr *, int);
-+static void tftp_sendfile(const struct formats *, struct tftphdr *, int, char *);
- static void tftp_recvfile(const struct formats *, struct tftphdr *, int);
+-static void tftp_recvfile(const struct formats *, struct tftphdr *, int);
++static void tftp_sendfile(const struct formats *, struct tftphdr *, int,
++                          const char *);
++static void tftp_recvfile(const struct formats *, struct tftphdr *, int,
++                          const char *);
  
  static const struct formats formats[] = {
-@@ -1152,6 +1152,9 @@ static int tftp(struct tftphdr *tp, int size)
+     {
+@@ -1101,7 +1103,7 @@ static int tftp(struct tftphdr *tp, int size)
+     char *cp, *end;
+     int argn, ecode;
+     const struct formats *pf = NULL;
+-    char *origfilename;
++    char *origfilename, *request_filename;
+     char *filename, *mode = NULL;
+     const char *errmsgptr;
+     uint16_t tp_opcode = ntohs(tp->th_opcode);
+@@ -1174,6 +1176,9 @@ static int tftp(struct tftphdr *tp, int size)
  	    if (!file) {
  		ecode =
  		    (*pf->f_validate) (filename, tp_opcode, pf, &errmsgptr);
-+		if (ecode == 1)
-+		    tftpd_log(LOG_NOTICE, "Client %s File not found %s\n",
++		if (ecode == ENOTFOUND)
++		    tftpd_log(LOG_NOTICE, "client %s: file not found: %s",
 +			      tmp_p, filename);
  		if (ecode) {
  		    nak(ecode, errmsgptr);
  		    exit(0);
-@@ -1178,12 +1181,12 @@ static int tftp(struct tftphdr *tp, int size)
+@@ -1195,17 +1200,20 @@ static int tftp(struct tftphdr *tp, int size)
+ 
+     negotiate_windowsize(&ap);
+     tftp_set_socket_buffers(peer, segsize, windowsize, tp_opcode == RRQ);
++    request_filename = xstrdup(origfilename);
+ 
+     if (ap != (ackbuf + 2)) {
          if (tp_opcode == WRQ)
-             (*pf->f_recv) (pf, (struct tftphdr *)ackbuf, ap - ackbuf);
+-            (*pf->f_recv) (pf, (struct tftphdr *)ackbuf, ap - ackbuf);
++            (*pf->f_recv) (pf, (struct tftphdr *)ackbuf, ap - ackbuf,
++                           request_filename);
          else
 -            (*pf->f_send) (pf, (struct tftphdr *)ackbuf, ap - ackbuf);
-+            (*pf->f_send) (pf, (struct tftphdr *)ackbuf, ap - ackbuf, origfilename);
++            (*pf->f_send) (pf, (struct tftphdr *)ackbuf, ap - ackbuf,
++                           request_filename);
      } else {
          if (tp_opcode == WRQ)
-             (*pf->f_recv) (pf, NULL, 0);
+-            (*pf->f_recv) (pf, NULL, 0);
++            (*pf->f_recv) (pf, NULL, 0, request_filename);
          else
 -            (*pf->f_send) (pf, NULL, 0);
-+            (*pf->f_send) (pf, NULL, 0, origfilename);
++            (*pf->f_send) (pf, NULL, 0, request_filename);
      }
      exit(0);                    /* Request completed */
  }
-@@ -1716,7 +1719,7 @@ static int validate_access(char *filename, int mode,
+@@ -1743,7 +1751,8 @@ static int validate_access(char *filename, int mode,
  /*
   * Send the requested file.
   */
 -static void tftp_sendfile(const struct formats *pf, struct tftphdr *oap, int oacklen)
-+static void tftp_sendfile(const struct formats *pf, struct tftphdr *oap, int oacklen, char *filename)
++static void tftp_sendfile(const struct formats *pf, struct tftphdr *oap,
++                          int oacklen, const char *filename)
  {
      struct tftphdr *ap;         /* ack packet */
      uint16_t ap_opcode, ap_block;
-@@ -1790,6 +1793,15 @@ static void tftp_sendfile(const struct formats *pf, struct tftphdr *oap, int oac
+@@ -1817,6 +1826,13 @@ static void tftp_sendfile(const struct formats *pf, struct tftphdr *oap, int oac
          errno = result.error;
          tftpd_log(LOG_WARNING, "tftpd: read(ack): %m");
          break;
 +    case TFTP_XFER_OK:
-+        tmp_p = (char *)inet_ntop(from.sa.sa_family, SOCKADDR_P(&from),
-+                                  tmpbuf, INET6_ADDRSTRLEN);
-+        if (!tmp_p) {
-+            tmp_p = tmpbuf;
-+            strcpy(tmpbuf, "???");
-+        }
-+        tftpd_log(LOG_NOTICE, "Client %s finished %s", tmp_p, filename);
++        tmp_p = inet_ntop(from.sa.sa_family, SOCKADDR_P(&from), tmpbuf,
++                          INET6_ADDRSTRLEN);
++        if (!tmp_p)
++            tmp_p = "???";
++        tftpd_log(LOG_NOTICE, "client %s: finished %s", tmp_p, filename);
++        break;
+     default:
+         break;
+     }
+@@ -1832,7 +1848,8 @@ static void tftp_sendfile(const struct formats *pf, struct tftphdr *oap, int oac
+  * Receive a file.
+  */
+ static void tftp_recvfile(const struct formats *pf,
+-			  struct tftphdr *oack, int oacklen)
++			  struct tftphdr *oack, int oacklen,
++                          const char *filename)
+ {
+     struct daemon_xfer_context context;
+     struct tftp_xfer xfer;
+@@ -1889,6 +1906,13 @@ static void tftp_recvfile(const struct formats *pf,
+         errno = result.error;
+         tftpd_log(LOG_WARNING, "tftpd: read: %m");
+         break;
++    case TFTP_XFER_OK:
++        tmp_p = inet_ntop(from.sa.sa_family, SOCKADDR_P(&from), tmpbuf,
++                          INET6_ADDRSTRLEN);
++        if (!tmp_p)
++            tmp_p = "???";
++        tftpd_log(LOG_NOTICE, "client %s: finished %s", tmp_p, filename);
 +        break;
      default:
          break;
      }
 diff --git a/tftpd/tftpd.h b/tftpd/tftpd.h
-index 3727ba4..4626a55 100644
+index 3727ba4..129fdfb 100644
 --- a/tftpd/tftpd.h
 +++ b/tftpd/tftpd.h
-@@ -34,7 +34,7 @@ struct formats {
+@@ -34,8 +34,10 @@ struct formats {
      const char *f_mode;
      char *(*f_rewrite) (const struct formats *, char *, int, int, const char **);
      int (*f_validate) (char *, int, const struct formats *, const char **);
 -    void (*f_send) (const struct formats *, struct tftphdr *, int);
-+    void (*f_send) (const struct formats *, struct tftphdr *, int, char *);
-     void (*f_recv) (const struct formats *, struct tftphdr *, int);
+-    void (*f_recv) (const struct formats *, struct tftphdr *, int);
++    void (*f_send) (const struct formats *, struct tftphdr *, int,
++                    const char *);
++    void (*f_recv) (const struct formats *, struct tftphdr *, int,
++                    const char *);
      bool f_convert;
  };
+ 
 -- 
 2.55.0
 

diff --git a/tftp-fedora-tftpboot.patch b/tftp-fedora-tftpboot.patch
new file mode 100644
index 0000000..fbd7218
--- /dev/null
+++ b/tftp-fedora-tftpboot.patch
@@ -0,0 +1,57 @@
+diff --git a/README.security b/README.security
+index 8ff9e85..df2fa38 100644
+--- a/README.security
++++ b/README.security
+@@ -23,10 +23,10 @@ probably the following:
+ 
+ 1. Create a separate "tftpd" user and group only used for tftpd;
+ 2. Have all your boot files in a single directory tree (usually called
+-   /tftpboot).
+-3. Specify "-p -u tftpd -s /tftpboot" on the tftpd command line; if
++   /var/lib/tftpboot).
++3. Specify "-p -u tftpd -s /var/lib/tftpboot" on the tftpd command line; if
+    you want clients to be able to create files use
+-   "-p -c -U 002 -u tftpd -s /tftpboot" (replace 002 with whatever
++   "-p -c -U 002 -u tftpd -s /var/lib/tftpboot" (replace 002 with whatever
+    umask is appropriate for your setup.)
+ 
+ When the -s (chroot) option is used, tftpd needs to be started as
+@@ -51,12 +51,12 @@ directly.  Thus, if your /etc/inetd.conf looks like this (all on one
+ line):
+ 
+ tftp	dgram	udp	wait	root	/usr/sbin/tcpd
+-/usr/sbin/in.tftpd -s /tftpboot -r blksize
++/usr/sbin/in.tftpd -s /var/lib/tftpboot -r blksize
+ 
+ ... it's better to change to ...
+ 
+ tftp	dgram	udp	wait	root	/usr/sbin/in.tftpd
+-in.tftpd -s /tftpboot -r blksize
++in.tftpd -s /var/lib/tftpboot -r blksize
+ 
+ You should make sure that you are using "wait" option in tftpd; you
+ also need to have tftpd spawned as root in order for chroot (-s) to
+diff --git a/tftp-xinetd b/tftp-xinetd
+index 982fe09..d04b48a 100644
+--- a/tftp-xinetd
++++ b/tftp-xinetd
+@@ -10,7 +10,7 @@ service tftp
+ 	wait			= yes
+ 	user			= root
+ 	server			= /usr/sbin/in.tftpd
+-	server_args		= -s /tftpboot
++	server_args		= -s /var/lib/tftpboot
+ 	disable			= yes
+ 	per_source		= 11
+ 	cps			= 100 2
+diff --git a/tftpd/sample.rules b/tftpd/sample.rules
+index 55b56be..1741a4c 100644
+--- a/tftpd/sample.rules
++++ b/tftpd/sample.rules
+@@ -29,5 +29,5 @@ rg	\\		/		# Convert backslashes to slashes
+ rg	\#		@		# Convert hash marks to @ signs
+ rg	/../		/..no../	# Convert /../ to /..no../
+ e	^ok/				# These are always ok
+-r	^[^/]		/tftpboot/\0	# Convert non-absolute files
++r	^[^/]		/var/lib/tftpboot/\0	# Convert non-absolute files
+ a	\.pvt$				# Reject requests for private files

diff --git a/tftp-hpa-5.2-osh.patch b/tftp-hpa-5.2-osh.patch
index 3296a45..b74eb4f 100644
--- a/tftp-hpa-5.2-osh.patch
+++ b/tftp-hpa-5.2-osh.patch
@@ -1,9 +1,24 @@
-# Fix leaked_handle: Handle variable "fd" going out of scope leaks the handle.
+From 43a86cbcbfd38e992d6f5d5009eea60f436711e4 Mon Sep 17 00:00:00 2001
+From: "H. Peter Anvin" <hpa@zytor.com>
+Date: Tue, 8 Sep 2026 17:33:47 -0700
+Subject: [PATCH] tftpd: close descriptors on access validation errors
+
+Close the file descriptor before returning access errors after a file has
+been opened.  This avoids leaking a descriptor for rejected read and write
+requests, including failed post-open truncation.
+
+Patch from Fedora SRPM.
+
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+---
+ tftpd/tftpd.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
 diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c
-index b8ef4f4..bfe9323 100644
+index 32e4150..8287161 100644
 --- a/tftpd/tftpd.c
 +++ b/tftpd/tftpd.c
-@@ -1680,6 +1680,7 @@ static int validate_access(char *filename, int mode,
+@@ -1701,6 +1701,7 @@ static int validate_access(char *filename, int mode,
  
      if (mode == RRQ) {
          if (!unixperms && (stbuf.st_mode & (S_IREAD >> 6)) == 0) {
@@ -11,7 +26,7 @@ index b8ef4f4..bfe9323 100644
              *errmsg = "File must have global read permissions";
              return (EACCESS);
          }
-@@ -1689,6 +1690,7 @@ static int validate_access(char *filename, int mode,
+@@ -1710,6 +1711,7 @@ static int validate_access(char *filename, int mode,
      } else {
          if (!unixperms) {
              if ((stbuf.st_mode & (S_IWRITE >> 6)) == 0) {
@@ -19,7 +34,7 @@ index b8ef4f4..bfe9323 100644
                  *errmsg = "File must have global write permissions";
                  return (EACCESS);
              }
-@@ -1697,6 +1699,7 @@ static int validate_access(char *filename, int mode,
+@@ -1718,6 +1720,7 @@ static int validate_access(char *filename, int mode,
  #ifdef HAVE_FTRUNCATE
  	/* We didn't get to truncate the file at open() time */
  	if (ftruncate(fd, (off_t) 0)) {
@@ -27,3 +42,6 @@ index b8ef4f4..bfe9323 100644
  	  *errmsg = "Cannot reset file size";
  	  return (EACCESS);
  	}
+-- 
+2.55.0
+

diff --git a/tftp-hpa-5.3-tftp-exit-code-cmdmode.patch b/tftp-hpa-5.3-tftp-exit-code-cmdmode.patch
index 83d0eb4..d884021 100644
--- a/tftp-hpa-5.3-tftp-exit-code-cmdmode.patch
+++ b/tftp-hpa-5.3-tftp-exit-code-cmdmode.patch
@@ -1,13 +1,22 @@
-From 817a17dfddca3c1213a8a5dc848b043caefee139 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zaoral?= <lzaoral@redhat.com>
-Date: Wed, 16 Jul 2025 15:03:43 +0200
-Subject: [PATCH] tftp: propagate errors to exit code in single command mode
+From 85b246c2bb3887ec19367841b342312f89090aaf Mon Sep 17 00:00:00 2001
+From: "H. Peter Anvin" <hpa@zytor.com>
+Date: Tue, 8 Sep 2026 17:33:47 -0700
+Subject: [PATCH] tftp: return failures from command mode
 
+Make command handlers and transfer routines return sysexits-compatible
+status codes so -c reports command, local I/O, and protocol failures.
+
+Commands that would otherwise prompt for missing arguments now return usage
+errors in command mode while retaining the interactive prompt behavior.
+
+Based on patch from the Fedora SRPM.
+
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
 ---
  tftp/extern.h |   4 +-
- tftp/main.c   | 152 ++++++++++++++++++++++++++++----------------------
- tftp/tftp.c   |  42 +++++++++++---
- 3 files changed, 122 insertions(+), 76 deletions(-)
+ tftp/main.c   | 209 ++++++++++++++++++++++++++++++--------------------
+ tftp/tftp.c   |  43 +++++++++--
+ 3 files changed, 164 insertions(+), 92 deletions(-)
 
 diff --git a/tftp/extern.h b/tftp/extern.h
 index 7740cb7..295b8e9 100644
@@ -25,10 +34,26 @@ index 7740cb7..295b8e9 100644
  
  #endif
 diff --git a/tftp/main.c b/tftp/main.c
-index 1b618b1..bbcab02 100644
+index 1b618b1..86d9c78 100644
 --- a/tftp/main.c
 +++ b/tftp/main.c
-@@ -84,23 +84,23 @@ static unsigned int portrange_to = 0;
+@@ -3,6 +3,7 @@
+  *
+  * Copyright (c) 1983, 1993
+  *	The Regents of the University of California.  All rights reserved.
++ * Copyright (C) 2026 H. Peter Anvin <hpa@zytor.com>
+  */
+ 
+ #include "common/tftpsubs.h"
+@@ -65,6 +66,7 @@ bool trace;
+ int verbose;
+ static bool literal;
+ static bool connected;
++static bool iscmd;
+ static const struct modes *mode;
+ #ifdef WITH_READLINE
+ static char *line = NULL;
+@@ -84,23 +86,23 @@ static unsigned int portrange_to = 0;
  unsigned int blocksize = SEGSIZE;
  unsigned int windowsize;
  
@@ -69,7 +94,7 @@ index 1b618b1..bbcab02 100644
  
  static void command(void);
  
-@@ -116,7 +116,7 @@ static void settftpmode(const struct modes *);
+@@ -116,7 +118,7 @@ static void settftpmode(const struct modes *);
  struct cmd {
      const char *name;
      const char *help;
@@ -78,16 +103,27 @@ index 1b618b1..bbcab02 100644
  };
  
  static const struct cmd cmdtab[] = {
-@@ -246,7 +246,7 @@ static const char short_options[] = "+46vVlm:cR:B:W:w:abh";
+@@ -246,9 +248,8 @@ static const char short_options[] = "+46vVlm:cR:B:W:w:abh";
  int main(int argc, char *argv[])
  {
      union sock_addr sa;
 -    int optc;
 +    int optc, ret;
      static int pargc, peerargc;
-     static bool iscmd;
+-    static bool iscmd;
      static char **pargv;
-@@ -428,9 +428,9 @@ int main(int argc, char *argv[])
+     char *peerargv[3];
+ 
+@@ -383,7 +384,7 @@ int main(int argc, char *argv[])
+         /* Set peer */
+         if (sigsetjmp(toplevel, 1) != 0)
+             exit(EX_NOHOST);
+-        setpeer(peerargc, peerargv);
++        (void)setpeer(peerargc, peerargv);
+     }
+ 
+     if (ai_fam_sock == AF_UNSPEC)
+@@ -428,9 +429,9 @@ int main(int argc, char *argv[])
          if (sigsetjmp(toplevel, 1) != 0)
              exit(EX_UNAVAILABLE);
  
@@ -99,8 +135,24 @@ index 1b618b1..bbcab02 100644
      }
  #ifdef WITH_READLINE
  #ifdef HAVE_READLINE_HISTORY_H
-@@ -485,7 +485,7 @@ static void getmoreargs(const char *partial, const char *mprompt)
+@@ -449,8 +450,11 @@ static char *hostname;
+ 
+ /* Called when a command is incomplete; modifies
+    the global variable "line" */
+-static void getmoreargs(const char *partial, const char *mprompt)
++static bool getmoreargs(const char *partial, const char *mprompt)
+ {
++    if (iscmd)
++        return false;
++
+ #ifdef WITH_READLINE
+     char *eline;
+     int len, elen;
+@@ -483,21 +487,23 @@ static void getmoreargs(const char *partial, const char *mprompt)
+         if (feof(stdin))
+             exit(0);            /* EOF */
  #endif
++    return true;
  }
  
 -static void setpeer(int argc, char *argv[])
@@ -108,7 +160,13 @@ index 1b618b1..bbcab02 100644
  {
      int err;
  
-@@ -497,7 +497,7 @@ static void setpeer(int argc, char *argv[])
+     if (argc < 2) {
+-        getmoreargs("connect ", "(to) ");
++        if (!getmoreargs("connect ", "(to) "))
++            return EX_USAGE;
+         margc = makeargv(line, margv);
+         argc = margc;
+         argv = margv;
      }
      if ((argc < 2) || (argc > 3)) {
          printf("usage: %s host-name [port]\n", argv[0]);
@@ -117,7 +175,7 @@ index 1b618b1..bbcab02 100644
      }
  
      peeraddr.sa.sa_family = ai_fam;
-@@ -506,7 +506,7 @@ static void setpeer(int argc, char *argv[])
+@@ -506,7 +512,7 @@ static void setpeer(int argc, char *argv[])
          printf("Error: %s\n", gai_strerror(err));
          printf("%s: unknown host\n", argv[1]);
          connected = false;
@@ -126,7 +184,7 @@ index 1b618b1..bbcab02 100644
      }
      ai_fam = peeraddr.sa.sa_family;
      if (f == -1) { /* socket not open */
-@@ -543,7 +543,7 @@ static void setpeer(int argc, char *argv[])
+@@ -543,7 +549,7 @@ static void setpeer(int argc, char *argv[])
              if (*ep || myport > 65535UL) {
                  printf("%s: bad port number\n", argv[2]);
                  connected = false;
@@ -135,7 +193,7 @@ index 1b618b1..bbcab02 100644
              }
              port = htons((uint16_t) myport);
          }
-@@ -560,16 +560,17 @@ static void setpeer(int argc, char *argv[])
+@@ -560,16 +566,17 @@ static void setpeer(int argc, char *argv[])
                 hostname, tp, (unsigned int)ntohs(port));
      }
      connected = true;
@@ -155,7 +213,7 @@ index 1b618b1..bbcab02 100644
      }
      if (argc == 2) {
          for (p = modes; p->m_name; p++)
-@@ -577,7 +578,7 @@ static void modecmd(int argc, char *argv[])
+@@ -577,7 +584,7 @@ static void modecmd(int argc, char *argv[])
                  break;
          if (p->m_name) {
              settftpmode(p);
@@ -164,7 +222,7 @@ index 1b618b1..bbcab02 100644
          }
          printf("%s: unknown mode\n", argv[1]);
          /* drop through and print usage message */
-@@ -591,21 +592,23 @@ static void modecmd(int argc, char *argv[])
+@@ -591,21 +598,23 @@ static void modecmd(int argc, char *argv[])
              sep = " | ";
      }
      printf(" ]\n");
@@ -191,7 +249,7 @@ index 1b618b1..bbcab02 100644
  }
  
  static void settftpmode(const struct modes *newmode)
-@@ -618,7 +621,7 @@ static void settftpmode(const struct modes *newmode)
+@@ -618,7 +627,7 @@ static void settftpmode(const struct modes *newmode)
  /*
   * Send file(s).
   */
@@ -200,7 +258,16 @@ index 1b618b1..bbcab02 100644
  {
      int fd;
      int n, err;
-@@ -633,14 +636,14 @@ static void put(int argc, char *argv[])
+@@ -626,21 +635,22 @@ static void put(int argc, char *argv[])
+     char *targ;
+ 
+     if (argc < 2) {
+-        getmoreargs("send ", "(file) ");
++        if (!getmoreargs("send ", "(file) "))
++            return EX_USAGE;
+         margc = makeargv(line, margv);
+         argc = margc;
+         argv = margv;
      }
      if (argc < 2) {
          putusage(argv[0]);
@@ -217,7 +284,7 @@ index 1b618b1..bbcab02 100644
              }
          cp = argv[argc - 1];
          targ = strchr(cp, ':');
-@@ -651,14 +654,14 @@ static void put(int argc, char *argv[])
+@@ -651,14 +661,14 @@ static void put(int argc, char *argv[])
              printf("Error: %s\n", gai_strerror(err));
              printf("%s: unknown host\n", argv[1]);
              connected = false;
@@ -234,7 +301,7 @@ index 1b618b1..bbcab02 100644
      }
      if (argc < 4) {
          cp = argc == 2 ? tail(targ) : argv[1];
-@@ -666,17 +669,18 @@ static void put(int argc, char *argv[])
+@@ -666,17 +676,17 @@ static void put(int argc, char *argv[])
          if (fd < 0) {
              fprintf(stderr, "tftp: ");
              perror(cp);
@@ -247,8 +314,7 @@ index 1b618b1..bbcab02 100644
          sa_set_port(&peeraddr, port);
 -        tftp_sendfile(fd, targ, mode->m_mode, windowsize);
 -        return;
-+        err = tftp_sendfile(fd, targ, mode->m_mode, windowsize);
-+        return err;
++        return tftp_sendfile(fd, targ, mode->m_mode, windowsize);
      }
      /* this assumes the target is a directory */
      /* on a remote unix system.  hmmmm.  */
@@ -256,28 +322,29 @@ index 1b618b1..bbcab02 100644
      for (n = 1; n < argc - 1; n++) {
          const char *base = tail(argv[n]);
          char *remotepath = xmalloc(strlen(targ) + 1 + strlen(base) + 1);
-@@ -686,6 +690,7 @@ static void put(int argc, char *argv[])
-         if (fd < 0) {
+@@ -687,15 +697,20 @@ static void put(int argc, char *argv[])
              fprintf(stderr, "tftp: ");
              perror(argv[n]);
-+            err = EX_OSERR;
              free(remotepath);
++            if (!err)
++                err = EX_OSERR;
              continue;
          }
-@@ -693,9 +698,11 @@ static void put(int argc, char *argv[])
+         if (verbose)
              printf("putting %s to %s:%s [%s]\n",
                     argv[n], hostname, remotepath, mode->m_mode);
          sa_set_port(&peeraddr, port);
 -        tftp_sendfile(fd, remotepath, mode->m_mode, windowsize);
-+        err |= tftp_sendfile(fd, remotepath, mode->m_mode, windowsize);
++        n = tftp_sendfile(fd, remotepath, mode->m_mode, windowsize);
++        if (!err)
++            err = n;
          free(remotepath);
      }
-+
 +    return err;
  }
  
  static void putusage(const char *s)
-@@ -707,10 +714,10 @@ static void putusage(const char *s)
+@@ -707,43 +722,47 @@ static void putusage(const char *s)
  /*
   * Receive file(s).
   */
@@ -290,7 +357,13 @@ index 1b618b1..bbcab02 100644
      char *cp;
      char *src;
  
-@@ -722,28 +729,28 @@ static void get(int argc, char *argv[])
+     if (argc < 2) {
+-        getmoreargs("get ", "(files) ");
++        if (!getmoreargs("get ", "(files) "))
++            return EX_USAGE;
+         margc = makeargv(line, margv);
+         argc = margc;
+         argv = margv;
      }
      if (argc < 2) {
          getusage(argv[0]);
@@ -312,18 +385,23 @@ index 1b618b1..bbcab02 100644
              src = argv[n];
          else {
 -            int err;
--
++            int resolve_error;
+ 
              *src++ = 0;
              peeraddr.sa.sa_family = ai_fam;
-             err = set_sock_addr(argv[n], &peeraddr, &hostname, false);
-             if (err) {
-                 printf("Warning: %s\n", gai_strerror(err));
+-            err = set_sock_addr(argv[n], &peeraddr, &hostname, false);
+-            if (err) {
+-                printf("Warning: %s\n", gai_strerror(err));
++            resolve_error = set_sock_addr(argv[n], &peeraddr, &hostname, false);
++            if (resolve_error) {
++                printf("Warning: %s\n", gai_strerror(resolve_error));
                  printf("%s: unknown host\n", argv[1]);
-+                err = EX_NOHOST;
++                if (!err)
++                    err = EX_NOHOST;
                  continue;
              }
              ai_fam = peeraddr.sa.sa_family;
-@@ -756,13 +763,13 @@ static void get(int argc, char *argv[])
+@@ -756,13 +775,13 @@ static void get(int argc, char *argv[])
              if (fd < 0) {
                  fprintf(stderr, "tftp: ");
                  perror(cp);
@@ -339,11 +417,12 @@ index 1b618b1..bbcab02 100644
              break;
          }
          cp = tail(src);         /* new .. jdg */
-@@ -771,14 +778,16 @@ static void get(int argc, char *argv[])
+@@ -771,14 +790,19 @@ static void get(int argc, char *argv[])
          if (fd < 0) {
              fprintf(stderr, "tftp: ");
              perror(cp);
-+            err = EX_OSERR;
++            if (!err)
++                err = EX_OSERR;
              continue;
          }
          if (verbose)
@@ -351,13 +430,15 @@ index 1b618b1..bbcab02 100644
                     hostname, src, cp, mode->m_mode);
          sa_set_port(&peeraddr, port);
 -        tftp_recvfile(fd, src, mode->m_mode, windowsize);
-+        err |= tftp_recvfile(fd, src, mode->m_mode, windowsize);
++        n = tftp_recvfile(fd, src, mode->m_mode, windowsize);
++        if (!err)
++            err = n;
      }
 +    return err;
  }
  
  static void getusage(const char *s)
-@@ -790,7 +799,7 @@ static void getusage(const char *s)
+@@ -790,91 +814,104 @@ static void getusage(const char *s)
  int rexmtval = TIMEOUT;
  int maxtimeout = TIMEOUT_LIMIT * TIMEOUT;
  
@@ -366,7 +447,12 @@ index 1b618b1..bbcab02 100644
  {
      int t;
  
-@@ -801,7 +810,7 @@ static void setrexmt(int argc, char *argv[])
+     if (argc < 2) {
+-        getmoreargs("rexmt-timeout ", "(value) ");
++        if (!getmoreargs("rexmt-timeout ", "(value) "))
++            return EX_USAGE;
+         argc = margc = makeargv(line, margv);
+         argv = margv;
      }
      if (argc != 2) {
          printf("usage: %s value\n", argv[0]);
@@ -374,8 +460,12 @@ index 1b618b1..bbcab02 100644
 +        return EX_USAGE;
      }
      t = atoi(argv[1]);
-     if (t < 1)
-@@ -810,9 +819,10 @@ static void setrexmt(int argc, char *argv[])
+-    if (t < 1)
++    if (t < 1) {
+         printf("%s: bad value\n", argv[1]);
+-    else {
++        return EX_USAGE;
++    } else {
          rexmtval = t;
          maxtimeout = rexmtval * TIMEOUT_LIMIT;
      }
@@ -387,7 +477,12 @@ index 1b618b1..bbcab02 100644
  {
      int t;
  
-@@ -823,16 +833,17 @@ static void settimeout(int argc, char *argv[])
+     if (argc < 2) {
+-        getmoreargs("maximum-timeout ", "(value) ");
++        if (!getmoreargs("maximum-timeout ", "(value) "))
++            return EX_USAGE;
+         argc = margc = makeargv(line, margv);
+         argv = margv;
      }
      if (argc != 2) {
          printf("usage: %s value\n", argv[0]);
@@ -395,9 +490,12 @@ index 1b618b1..bbcab02 100644
 +        return EX_USAGE;
      }
      t = atoi(argv[1]);
-     if (t < 1)
+-    if (t < 1)
++    if (t < 1) {
          printf("%s: bad value\n", argv[1]);
-     else
+-    else
++        return EX_USAGE;
++    } else
          maxtimeout = t;
 +    return 0;
  }
@@ -406,8 +504,11 @@ index 1b618b1..bbcab02 100644
 +static int setblocksize(int argc, char *argv[])
  {
      if (argc < 2) {
-         getmoreargs("blocksize ", "(size) ");
-@@ -841,15 +852,16 @@ static void setblocksize(int argc, char *argv[])
+-        getmoreargs("blocksize ", "(size) ");
++        if (!getmoreargs("blocksize ", "(size) "))
++            return EX_USAGE;
+         argc = margc = makeargv(line, margv);
+         argv = margv;
      }
      if (argc != 2) {
          printf("usage: %s size\n", argv[0]);
@@ -417,6 +518,7 @@ index 1b618b1..bbcab02 100644
      if (!parse_uint_range(argv[1], 8, MAX_SEGSIZE, &blocksize)) {
          printf("%s: bad block size (valid range is 8-%d)\n",
                 argv[1], MAX_SEGSIZE);
++        return EX_USAGE;
      }
 +    return 0;
  }
@@ -425,8 +527,11 @@ index 1b618b1..bbcab02 100644
 +static int setwindowsize(int argc, char *argv[])
  {
      if (argc < 2) {
-         getmoreargs("windowsize ", "(size) ");
-@@ -858,23 +870,25 @@ static void setwindowsize(int argc, char *argv[])
+-        getmoreargs("windowsize ", "(size) ");
++        if (!getmoreargs("windowsize ", "(size) "))
++            return EX_USAGE;
+         argc = margc = makeargv(line, margv);
+         argv = margv;
      }
      if (argc != 2) {
          printf("usage: %s size\n", argv[0]);
@@ -436,6 +541,7 @@ index 1b618b1..bbcab02 100644
      if (!parse_uint_range(argv[1], 1, TFTP_MAX_WINDOWSIZE, &windowsize)) {
          printf("%s: bad window size (valid range is 1-%u)\n",
                 argv[1], TFTP_MAX_WINDOWSIZE);
++        return EX_USAGE;
      }
 +    return 0;
  }
@@ -455,7 +561,7 @@ index 1b618b1..bbcab02 100644
  {
      (void)argc;
      (void)argv;                 /* Quiet unused warning */
-@@ -889,6 +903,7 @@ static void status(int argc, char *argv[])
+@@ -889,6 +926,7 @@ static void status(int argc, char *argv[])
             rexmtval, maxtimeout);
      printf("Blocksize: %u, windowsize: %u\n", blocksize,
             windowsize ? windowsize : 1);
@@ -463,7 +569,16 @@ index 1b618b1..bbcab02 100644
  }
  
  static void intr(int sig)
-@@ -1031,7 +1046,7 @@ static int makeargv(char *str, char **argp)
+@@ -958,7 +996,7 @@ static void command(void)
+             printf("Error: %s command: %s\n", errtype, margv[0]);
+             continue;
+         }
+-        (*c->handler) (margc, margv);
++        (void)(*c->handler) (margc, margv);
+     }
+ }
+ 
+@@ -1031,7 +1069,7 @@ static int makeargv(char *str, char **argp)
      return argc;
  }
  
@@ -472,7 +587,7 @@ index 1b618b1..bbcab02 100644
  {
      (void)argc;
      (void)argv;                 /* Quiet unused warning */
-@@ -1041,7 +1056,7 @@ static void quit(int argc, char *argv[])
+@@ -1041,7 +1079,7 @@ static void quit(int argc, char *argv[])
  /*
   * Help command.
   */
@@ -481,7 +596,7 @@ index 1b618b1..bbcab02 100644
  {
      const struct cmd *c;
  
-@@ -1051,7 +1066,7 @@ static void help(int argc, char *argv[])
+@@ -1051,7 +1089,7 @@ static void help(int argc, char *argv[])
          printf("Commands may be abbreviated.  Commands are:\n\n");
          for (c = cmdtab; c->name; c++)
              printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help);
@@ -490,7 +605,7 @@ index 1b618b1..bbcab02 100644
      }
      while (--argc > 0) {
          const char *errtype;
-@@ -1063,18 +1078,20 @@ static void help(int argc, char *argv[])
+@@ -1063,18 +1101,20 @@ static void help(int argc, char *argv[])
          else
              printf("%s\n", c->help);
      }
@@ -513,7 +628,7 @@ index 1b618b1..bbcab02 100644
  {
      const char *name;
  
-@@ -1090,7 +1107,7 @@ static void set_verbosity(const char *to, bool startup)
+@@ -1090,7 +1130,7 @@ static void set_verbosity(const char *to, bool startup)
                  exit(EX_USAGE);
              } else {
                  printf("Invalid verbosity level: %s\n", to);
@@ -522,7 +637,7 @@ index 1b618b1..bbcab02 100644
              }
          }
      } else {
-@@ -1111,10 +1128,11 @@ static void set_verbosity(const char *to, bool startup)
+@@ -1111,10 +1151,11 @@ static void set_verbosity(const char *to, bool startup)
  
      if (!startup)
          printf("Verbosity set to level %d (%s).\n", verbose, name);
@@ -537,40 +652,42 @@ index 1b618b1..bbcab02 100644
 +    return set_verbosity(argv[1], false);
  }
 diff --git a/tftp/tftp.c b/tftp/tftp.c
-index b752787..4968ae3 100644
+index 992d7a6..03967cc 100644
 --- a/tftp/tftp.c
 +++ b/tftp/tftp.c
-@@ -128,7 +128,7 @@ static const struct tftp_xfer_ops client_xfer_ops = {
+@@ -120,8 +120,8 @@ static const struct tftp_xfer_ops client_xfer_ops = {
  /*
   * Send the requested file.
   */
 -void tftp_sendfile(int fd, const char *name, const char *mode,
+-                   unsigned int requested_window)
 +int tftp_sendfile(int fd, const char *name, const char *mode,
-                    unsigned int requested_window)
++                  unsigned int requested_window)
  {
      struct tftphdr *ap;
-@@ -140,7 +140,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
-     struct client_xfer_context context;
+     char response[REQBUFSIZE];
+@@ -133,6 +133,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
      struct tftp_xfer xfer;
      struct tftp_xfer_result result;
--    int n, size;
-+    int n, size, err = 0;
+     int n, size;
++    volatile int err = 0;
      bool convert = !strcmp(mode, "netascii");
      unsigned int window;
      unsigned int negotiated_block, negotiated_window;
-@@ -151,8 +151,10 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
+@@ -147,8 +148,11 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
  
      startclock();
      file = fdopen(fd, convert ? "rt" : "rb");
 -    if (!file)
 +    if (!file) {
++        close(fd);
 +        err = EX_OSERR;
          goto abort;
 +    }
      ap = (struct tftphdr *)ackbuf;
  
      tftp_signal(SIGALRM, timer, 0);
-@@ -160,6 +162,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
+@@ -156,6 +160,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
                         sizeof(ackbuf));
      if (size < 0) {
          fprintf(stderr, "tftp: %s: %s\n", name, strerror(errno));
@@ -578,7 +695,7 @@ index b752787..4968ae3 100644
          goto abort;
      }
  
-@@ -171,6 +174,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
+@@ -167,6 +172,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
              tpacket("sent", ap, size);
          if (sendto(f, ap, size, 0, &peeraddr.sa, SOCKLEN(&peeraddr)) != size) {
              perror("tftp: sendto");
@@ -586,7 +703,7 @@ index b752787..4968ae3 100644
              goto abort;
          }
          r_timeout = timeout;
-@@ -178,6 +182,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
+@@ -175,6 +181,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
          n = client_recv_time(response, sizeof(response), &from, &r_timeout);
          if (n < 0) {
              perror("tftp: recvfrom");
@@ -594,7 +711,7 @@ index b752787..4968ae3 100644
              goto abort;
          }
          if (n < 2)
-@@ -188,12 +193,14 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
+@@ -185,12 +192,14 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
          ap_block = ntohs(rp->th_block);
          if (ap_opcode == ERROR) {
              printf("Error code %d: %s\n", ap_block, rp->th_msg);
@@ -609,7 +726,7 @@ index b752787..4968ae3 100644
                  goto abort;
              }
              segsize = (int)negotiated_block;
-@@ -213,6 +220,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
+@@ -210,6 +219,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
      io = tftp_io_reader_start(file, convert, window, window, segsize, false);
      if (!io) {
          nak(errno + 100, NULL);
@@ -617,7 +734,7 @@ index b752787..4968ae3 100644
          goto abort;
      }
  
-@@ -234,17 +242,21 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
+@@ -231,17 +241,21 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
      switch (result.status) {
      case TFTP_XFER_READ_ERROR:
          nak(result.error + 100, NULL);
@@ -639,11 +756,10 @@ index b752787..4968ae3 100644
          break;
      default:
          break;
-@@ -256,13 +268,15 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
+@@ -256,13 +270,14 @@ void tftp_sendfile(int fd, const char *name, const char *mode,
      stopclock();
      if (amount > 0)
          printstats("Sent", amount);
-+
 +    return err;
  }
  
@@ -657,21 +773,21 @@ index b752787..4968ae3 100644
  {
      struct tftphdr *ap;
      union sock_addr from;
-@@ -275,7 +289,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
-     const struct tftphdr * volatile initial_reply = NULL;
+@@ -276,6 +291,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
      volatile int initial_reply_len = 0;
      volatile int initial_packet_len = -1;
--    int n, size;
-+    int n, size, err = 0;
+     int n, size;
++    volatile int err = 0;
      bool convert = !strcmp(mode, "netascii");
      unsigned int window;
      unsigned int negotiated_block, negotiated_window;
-@@ -286,14 +300,17 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
+@@ -288,14 +304,18 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
  
      startclock();
      file = fdopen(fd, convert ? "wt" : "wb");
 -    if (!file)
 +    if (!file) {
++        close(fd);
 +        err = EX_OSERR;
          goto abort;
 +    }
@@ -685,7 +801,7 @@ index b752787..4968ae3 100644
          goto abort;
      }
      tftp_signal(SIGALRM, timer, 0);
-@@ -306,6 +323,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
+@@ -308,6 +328,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
              tpacket("sent", ap, size);
          if (sendto(f, ap, size, 0, &peeraddr.sa, SOCKLEN(&peeraddr)) != size) {
              perror("tftp: sendto");
@@ -693,7 +809,7 @@ index b752787..4968ae3 100644
              goto abort;
          }
          r_timeout = timeout;
-@@ -314,6 +332,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
+@@ -316,6 +337,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
                               &from, &r_timeout);
          if (n < 0) {
              perror("tftp: recvfrom");
@@ -701,7 +817,7 @@ index b752787..4968ae3 100644
              goto abort;
          }
          if (n < 2)
-@@ -324,12 +343,14 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
+@@ -326,12 +348,14 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
          if (opcode == ERROR) {
              printf("Error code %d: %s\n",
                     ntohs(initial_packet->th_code), initial_packet->th_msg);
@@ -716,7 +832,7 @@ index b752787..4968ae3 100644
                  goto abort;
              }
              segsize = (int)negotiated_block;
-@@ -355,6 +376,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
+@@ -357,6 +381,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
      io = tftp_io_writer_start(file, convert, window, segsize, false);
      if (!io) {
          nak(errno + 100, NULL);
@@ -724,7 +840,7 @@ index b752787..4968ae3 100644
          goto abort;
      }
  
-@@ -381,21 +403,26 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
+@@ -383,21 +408,26 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
      switch (result.status) {
      case TFTP_XFER_BAD_DATA:
          nak(EBADOP, "Data packet too large");
@@ -751,7 +867,7 @@ index b752787..4968ae3 100644
          break;
      default:
          break;
-@@ -412,6 +439,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
+@@ -416,6 +446,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode,
      stopclock();
      if (amount > 0)
          printstats("Received", amount);

diff --git a/tftp.spec b/tftp.spec
index ce542a4..76ab0e8 100644
--- a/tftp.spec
+++ b/tftp.spec
@@ -1,7 +1,7 @@
 Summary: The client for the Trivial File Transfer Protocol (TFTP)
 Name: tftp
 Version: 6.1
-Release: 2%{?dist}
+Release: 3%{?dist}
 License: BSD-4-Clause-UC
 URL: http://www.kernel.org/pub/software/network/tftp/
 Source0: https://www.kernel.org/pub/software/network/tftp/tftp-hpa-%{version}.tar.gz
@@ -14,14 +14,18 @@ Source4: tftp.service
 Source5: tftp-server-sysusers.conf
 Source6: tftp-server-tmpfiles.conf
 
-# To-be upstreamed patches
+# Upstreamed patches
+# https://github.com/hpax/tftp-hpa/commit/ab93a245747ada8948f4594de54a4b2b30c4b462
 Patch: tftp-enhanced-logging.patch
+# https://github.com/hpax/tftp-hpa/commit/43a86cbcbfd38e992d6f5d5009eea60f436711e4
 Patch: tftp-hpa-5.2-osh.patch
+# https://github.com/hpax/tftp-hpa/commit/85b246c2bb3887ec19367841b342312f89090aaf
 Patch: tftp-hpa-5.3-tftp-exit-code-cmdmode.patch
 
 # Downstream-only patches
-Patch: tftp-0.42-tftpboot.patch
+Patch: tftp-fedora-tftpboot.patch
 
+BuildRequires: bc
 BuildRequires: gcc
 BuildRequires: gpgverify
 BuildRequires: make
@@ -70,6 +74,9 @@ install -D -p -m 644 %SOURCE6 %{buildroot}%{_tmpfilesdir}/%{name}.conf
 mkdir -p %{buildroot}%{_sysconfdir}/tftp
 echo '# See tftpd(8) for the definition of remap rules' > %{buildroot}%{_sysconfdir}/%{name}/map-file
 
+%check
+tests/test-tftp.sh
+
 %post server
 %systemd_post tftp.socket
 
@@ -99,6 +106,10 @@ echo '# See tftpd(8) for the definition of remap rules' > %{buildroot}%{_sysconf
 %{_unitdir}/tftp.socket
 
 %changelog
+* Fri Sep 11 2026 Lukáš Zaoral <lzaoral@redhat.com> - 6.1-3
+- sync patches with upstream
+- execute testsuite in %%check
+
 * Fri Sep 11 2026 Lukáš Zaoral <lzaoral@redhat.com> - 6.1-2
 - tftp systemd service improvements
   - use the same verbosity level as older releases (-v is now necessary)

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-14  8:20 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-14  8:20 [rpms/tftp] rawhide: sync patches with upstream and enable upstream test-suite 

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox