uncommitted - gesftpserver
Ready changes
Summary
Import uploads missing from VCS:Diff
diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches
new file mode 100644
index 0000000..6857a8d
--- /dev/null
+++ b/.pc/.quilt_patches
@@ -0,0 +1 @@
+debian/patches
diff --git a/.pc/.quilt_series b/.pc/.quilt_series
new file mode 100644
index 0000000..c206706
--- /dev/null
+++ b/.pc/.quilt_series
@@ -0,0 +1 @@
+series
diff --git a/.pc/.version b/.pc/.version
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/.pc/.version
@@ -0,0 +1 @@
+2
diff --git a/.pc/applied-patches b/.pc/applied-patches
new file mode 100644
index 0000000..e69de29
diff --git a/CHANGES.md b/CHANGES.md
index 54c1c82..5e29aeb 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,12 @@
# Release History
+## Changes in version 2
+
+* Fix interpretation of malformed handles
+* Correct attribute ordering. Bug fix from Bernd Holzmüller.
+* Tests use Python 3
+* Build fixes
+
## Changes in version 1
* Fix attribute formatting in v3 directory listings.
diff --git a/Makefile.am b/Makefile.am
index 9645424..e59b867 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
# This file is part of the Green End SFTP Server.
-# Copyright (C) 2007, 2011, 2014 Richard Kettlewell
+# Copyright (C) 2007, 2011,14,16,18 Richard Kettlewell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -52,15 +52,15 @@ all: ${SEDOUTPUTS}
check: gesftpserver sftpclient pwtest aliases
rm -f *.gcda *.gcov
./pwtest
- srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory tests $(TESTS)
- srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory rotests --server ./gesftpserver-ro $(ROTESTS)
- ${GCOV} ${srcdir}/*.c | ${PYTHON24} ${srcdir}/format-gconv-report --html .
+ srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --directory tests $(TESTS)
+ srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --directory rotests --server ./gesftpserver-ro $(ROTESTS)
+ ${GCOV} ${srcdir}/*.c | ${PYTHON3} ${srcdir}/format-gconv-report --html .
#${srcdir}/paramiko-test
check-valgrind: gesftpserver-valgrind sftpclient pwtest aliases
rm -f ,valgrind*
- srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory tests --server ./gesftpserver-valgrind $(TESTS)
+ srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --debug --directory tests --server ./gesftpserver-valgrind $(TESTS)
aliases: gesftpserver-ro gesftpserver-debug gesftpserver-ro-debug \
gesftpserver-valgrind
diff --git a/README.md b/README.md
index ae3ba2b..da8c6a2 100644
--- a/README.md
+++ b/README.md
@@ -9,14 +9,15 @@ possible to use it as a drop-in replacement for the OpenSSH server.
Requirements
------------
-This software runs under Linux, Mac OS X and FreeBSD. It may work
-on other UNIX platforms.
+This software runs under Linux and macOS.
+It may work on other UNIX platforms.
Installation
------------
The general procedure is:
+ ./autogen.sh
./configure
make check # builds software and runs tests
make install # probably as root
@@ -36,7 +37,9 @@ don’t care.
You will need iconv and readline libraries.
It’s best to run `make check` before installing. This requires
-[Python](http://www.python.org/) to be installed.
+[Python 3](http://www.python.org/) to be installed:
+
+ apt install python3 python3-termcolors
Status
------
@@ -84,7 +87,7 @@ If you send patches, please use `diff -u` format.
Licence
-------
-Copyright (C) 2007, 2009-2011, 2014, 2016 Richard Kettlewell
+Copyright (C) 2007, 2009-2011, 2014-18 Richard Kettlewell
Portions copyright (C) 2015 Michel Kraus
diff --git a/acinclude.m4 b/acinclude.m4
index a3b2111..3862f9c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1,5 +1,5 @@
# This file is part of the Green End SFTP Server.
-# Copyright (C) 2007, 2011 Richard Kettlewell
+# Copyright (C) 2007, 2011,14,15,18 Richard Kettlewell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -45,7 +45,7 @@ AC_DEFUN([RJK_BUILDSYS_MISC],[
# extra includes
if test "$host" = "$build"; then
case $host_os in
- freebsd* )
+ freebsd* )
rjk_cv_extraincludes=/usr/local/include
;;
esac
@@ -62,7 +62,7 @@ AC_DEFUN([RJK_BUILDSYS_MISC],[
rjk_cv_extralibs=none
if test "$host" = "$build"; then
case $host_os in
- freebsd* )
+ freebsd* )
rjk_cv_extralibs=/usr/local/lib
;;
esac
@@ -250,28 +250,26 @@ AC_DEFUN([RJK_GETOPT],[
])
])
-AC_DEFUN([RJK_PYTHON24],[
- AC_CACHE_CHECK([for Python 2.4 or better],[rjk_cv_python24],[
- if python24 -V >/dev/null 2>&1; then
- rjk_cv_python24=python24
- elif python2.4 -V >/dev/null 2>&1; then
- rjk_cv_python24=python2.4
+AC_DEFUN([RJK_PYTHON3],[
+ AC_CACHE_CHECK([for Python 3],[rjk_cv_python3],[
+ if python3 -V >/dev/null 2>&1; then
+ rjk_cv_python3=python3
elif python -V >confpyver 2>&1; then
read p v < confpyver
case "$v" in
- 1* | 2.0* | 2.1* | 2.2* | 2.3* )
+ 1* | 2* )
;;
* )
- rjk_cv_python24=python
+ rjk_cv_python3=python
;;
esac
fi
rm -f confpyver
- if test "$rjk_cv_python24" = ""; then
- AC_MSG_ERROR([cannot find Python 2.4 or better])
+ if test "$rjk_cv_python3" = ""; then
+ AC_MSG_ERROR([cannot find Python 3.x])
fi
])
- AC_SUBST([PYTHON24],[$rjk_cv_python24])
+ AC_SUBST([PYTHON3],[$rjk_cv_python3])
])
dnl Local Variables:
diff --git a/alloc.c b/alloc.c
index ceb318e..326efca 100644
--- a/alloc.c
+++ b/alloc.c
@@ -83,7 +83,7 @@ struct allocator *sftp_alloc_init(struct allocator *a) {
* @return Number of blocks necessary to contain @p nbytes
*/
static inline size_t blocks(size_t nbytes) {
- return nbytes / sizeof (union block) + !!(nbytes % sizeof (union block));
+ return nbytes / sizeof(union block) + !!(nbytes % sizeof(union block));
}
void *sftp_alloc(struct allocator *a, size_t n) {
@@ -94,15 +94,15 @@ void *sftp_alloc(struct allocator *a, size_t n) {
if(!m)
return 0;
assert(a != 0);
- assert(m != SIZE_MAX); /* ...and so m+1 > 0 */
+ assert(m != SIZE_MAX); /* ...and so m+1 > 0 */
/* See if there's enough room */
if(!(c = a->chunks) || c->left < m) {
/* Make sure we allocate enough space */
const size_t cs = m >= NBLOCKS ? m + 1 : NBLOCKS;
- /* xcalloc -> calloc which 0-fills */
+ /* sftp_xcalloc -> calloc which 0-fills */
union block *nb;
- nb = xcalloc(cs, sizeof (union block));
+ nb = sftp_xcalloc(cs, sizeof(union block));
c = &nb->c;
c->next = a->chunks;
c->ptr = nb + 1;
@@ -112,20 +112,21 @@ void *sftp_alloc(struct allocator *a, size_t n) {
assert(m <= c->left);
/* We always return 0-filled memory. In this case we fill by block, which is
* guaranteed to be at least enough (compare below). */
- memset(c->ptr, 0, m * sizeof (union block));
+ sftp_memset(c->ptr, 0, m * sizeof(union block));
c->left -= m;
c->ptr += m;
return c->ptr - m;
}
-void *sftp_alloc_more(struct allocator *a, void *ptr, size_t oldn, size_t newn) {
+void *sftp_alloc_more(struct allocator *a, void *ptr, size_t oldn,
+ size_t newn) {
const size_t oldm = blocks(oldn), newm = blocks(newn);
void *newptr;
if(ptr) {
assert(a->chunks != 0);
- D(("ptr=%p oldm=%zu a->chunks->ptr=%p blocksize=%zu",
- ptr, oldm, a->chunks->ptr, sizeof(union block)));
+ D(("ptr=%p oldm=%zu a->chunks->ptr=%p blocksize=%zu", ptr, oldm,
+ a->chunks->ptr, sizeof(union block)));
if((union block *)ptr + oldm == a->chunks->ptr) {
/* ptr is the most recently allocated block. We could do better and
* search all the chunks for it. */
@@ -141,7 +142,7 @@ void *sftp_alloc_more(struct allocator *a, void *ptr, size_t oldn, size_t newn)
/* 0-fill the new space. Note that we do this in byte terms (compare
* above), to deal with the case where the allocation shrinks by (say)
* a single non-zero byte but then expands again. */
- memset((char *)ptr + oldn, 0, newn - oldn);
+ sftp_memset((char *)ptr + oldn, 0, newn - oldn);
return ptr;
}
/* If we get here then we are expanding but there is not enough space to
@@ -153,7 +154,7 @@ void *sftp_alloc_more(struct allocator *a, void *ptr, size_t oldn, size_t newn)
}
/* We have no choice but to allocate new space */
newptr = sftp_alloc(a, newn);
- memcpy(newptr, ptr, oldn);
+ sftp_memcpy(newptr, ptr, oldn);
return newptr;
} else
/* There was no old allocation, just create a new one the easy way */
diff --git a/alloc.h b/alloc.h
index 37a0ee2..c267b0f 100644
--- a/alloc.h
+++ b/alloc.h
@@ -21,7 +21,7 @@
/** @file alloc.h @brief Allocator interface */
#ifndef ALLOC_H
-#define ALLOC_H
+# define ALLOC_H
struct chunk;
diff --git a/charset.c b/charset.c
index bdb8013..8611178 100644
--- a/charset.c
+++ b/charset.c
@@ -32,13 +32,13 @@ wchar_t *sftp_mbs2wcs(const char *s) {
wchar_t *ws;
size_t len;
mbstate_t ps;
-
- memset(&ps, 0, sizeof ps);
+
+ sftp_memset(&ps, 0, sizeof ps);
len = mbsrtowcs(0, &s, 0, &ps);
if(len == (size_t)-1)
return 0;
- ws = xcalloc(len + 1, sizeof *ws);
- memset(&ps, 0, sizeof ps);
+ ws = sftp_xcalloc(len + 1, sizeof *ws);
+ sftp_memset(&ps, 0, sizeof ps);
mbsrtowcs(ws, &s, len, &ps);
return ws;
}
@@ -51,7 +51,7 @@ int sftp_iconv(struct allocator *a, iconv_t cd, char **sp) {
const char *inbuf;
char *outbuf, *output;
size_t inbytesleft, outbytesleft;
-
+
assert(cd != 0);
do {
output = sftp_alloc(a, outputsize);
diff --git a/charset.h b/charset.h
index dc03192..c73325f 100644
--- a/charset.h
+++ b/charset.h
@@ -21,10 +21,10 @@
/** @file charset.h @brief Character conversion interface */
#ifndef CHARSET_H
-#define CHARSET_H
+# define CHARSET_H
-#include <wchar.h>
-#include <iconv.h>
+# include <wchar.h>
+# include <iconv.h>
/** @brief Convert a multibyte string to a wide string
* @param s Multibyte string to convert
diff --git a/configure.ac b/configure.ac
index 29ffee1..4de626c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
# This file is part of the Green End SFTP Server.
-# Copyright (C) 2007, 2011, 2014, 2015 Richard Kettlewell
+# Copyright (C) 2007, 2011, 2014-2016, 2018 Richard Kettlewell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
# USA
# Process this file with autoconf to produce a configure script.
-AC_INIT(sftpserver, 1, rjk@greenend.org.uk)
+AC_INIT(sftpserver, 2, rjk@greenend.org.uk)
AC_CONFIG_AUX_DIR([config.aux])
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_SRCDIR([alloc.c])
@@ -55,7 +55,7 @@ RJK_GCC_WARNINGS
RJK_GCC_ATTRS
RJK_STAT_TIMESPEC
RJK_GETOPT
-RJK_PYTHON24
+RJK_PYTHON3
dnl See commentary in v3.c for what's going on here
AC_MSG_CHECKING([whether to reverse SSH_FXP_SYMLINK arguments])
diff --git a/daemon.c b/daemon.c
index 4a26229..5e0bb7c 100644
--- a/daemon.c
+++ b/daemon.c
@@ -1,3 +1,4 @@
+// clang-format off
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
diff --git a/debian/changelog b/debian/changelog
index a69769f..b7cec20 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,25 @@
+gesftpserver (2~ds-1) unstable; urgency=medium
+
+ [ upstream ]
+ * new release
+
+ [ Jonas Smedegaard ]
+ * update git-buildpackage config:
+ + use DEP-14 git branches
+ + enable automatic DEP-14 branch name handling
+ + add usage config
+ * update watch file:
+ + set dversionmangle=auto
+ + set pgpmode=auto
+ * add upstream PGP signing-key
+ * update copyright info: update coverage
+ * declare compliance with Debian Policy 4.6.1
+ * use debhelper compatibility level 13;
+ tighten build-dependency on debhelper-compat
+ * drop patch 1001 to use python3, fixed upstream
+
+ -- Jonas Smedegaard <dr@jones.dk> Fri, 12 Aug 2022 08:00:23 +0200
+
gesftpserver (1~ds-3) unstable; urgency=medium
[ lintian brush ]
diff --git a/debian/control b/debian/control
index fa7b596..f91aee4 100644
--- a/debian/control
+++ b/debian/control
@@ -3,10 +3,10 @@ Section: utils
Priority: optional
Maintainer: Jonas Smedegaard <dr@jones.dk>
Build-Depends:
- debhelper-compat (= 12),
+ debhelper-compat (= 13),
libreadline-dev,
python3
-Standards-Version: 4.5.0
+Standards-Version: 4.6.1
Vcs-Git: https://salsa.debian.org/debian/gesftpserver.git
Vcs-Browser: https://salsa.debian.org/debian/gesftpserver
Homepage: https://www.greenend.org.uk/rjk/sftpserver/
diff --git a/debian/copyright b/debian/copyright
index c68747e..c1047a4 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -19,7 +19,8 @@ Files-Excluded:
tests/truncate6~
Files: *
-Copyright: 2007,2009-2011,2014-2016, Richard Kettlewell
+Copyright:
+ 2007,2009-2011,2014-2016, 2018 Richard Kettlewell
License-Grant:
This program is free software;
you can redistribute it and/or modify it
@@ -29,7 +30,8 @@ License-Grant:
License: GPL-2+
Files: getopt*
-Copyright: 1987-2000, Free Software Foundation, Inc.
+Copyright:
+ 1987-2000 Free Software Foundation, Inc.
License-Grant:
The GNU C Library is free software;
you can redistribute it and/or modify it
@@ -39,11 +41,13 @@ License-Grant:
License: LGPL-2+
Files: daemon.c
-Copyright: 1990, 1993
+Copyright:
+ 1990, 1993 The Regents of the University of California
License: BSD-3-Clause~Regents~4
Files: debian/*
-Copyright: 2012-2019, Jonas Smedegaard <dr@jones.dk>
+Copyright:
+ 2012-2020, 2022 Jonas Smedegaard <dr@jones.dk>
License-Grant:
This program is free software;
you can redistribute it and/or modify it
@@ -53,7 +57,8 @@ License-Grant:
License: GPL-3+
Files: debian/patches/0*
-Copyright: Richard Kettlewell
+Copyright:
+ Richard Kettlewell
License: GPL-2+
Comment:
Patches cherry-picked upstream is assumed to be covered
diff --git a/debian/copyright_hints b/debian/copyright_hints
index cc9d42e..b3000f8 100644
--- a/debian/copyright_hints
+++ b/debian/copyright_hints
@@ -5,13 +5,16 @@ Source: FIXME
Disclaimer: Autogenerated by CDBS
Files: CHANGES.md
- debian/compat
+ debian/NEWS
debian/control
debian/gbp.conf
debian/patches/README
debian/patches/series
debian/rules
debian/source/format
+ debian/source/lintian-overrides
+ debian/upstream
+ debian/upstream/signing-key.asc
debian/watch
rotests/rotest3456
rotests/rotest56
@@ -84,9 +87,7 @@ Copyright: NONE
License: UNKNOWN
FIXME
-Files: Makefile.am
- acinclude.m4
- alloc.c
+Files: alloc.c
alloc.h
charset.c
charset.h
@@ -141,38 +142,43 @@ Copyright: 2007, 2009, 2011, 2014, Richard Kettlewell
2007, 2010-2011, 2014, 2016, Richard Kettlewell
2007, 2010-2011, Richard Kettlewell
2007, 2011, 2014, Richard Kettlewell
- 2007, 2011, 2014-2015, Richard Kettlewell
+ 2007, 2011, 2014-2016, 2018, Richard Kettlewell
+ 2007, 2011, 2016, 2018, Richard Kettlewell
2007, 2011, 2016, Richard Kettlewell
2007, 2011, Richard Kettlewell
2007, 2016, Richard Kettlewell
+ 2007, 2018, Richard Kettlewell
2007, Richard Kettlewell
2014, Richard Kettlewell
License: GPL-2+
FIXME
Files: daemon.c
-Copyright: 1990, 1993, The Regents of the University of California.
+Copyright: 1990, 1993
License: BSD-3-clause
FIXME
Files: COPYING
Copyright: 1989, 1991, Free Software Foundation, Inc.,
- <year> <name of author>
- disclaimer" for the program, if
- ed by the Free
- ed interfaces, the
- interest in the program
- the software, and
- year name of author
-License: GPL-2+
+License: GPL-2
FIXME
Files: README.md
-Copyright: 2007, 2009-2011, 2014, 2016, Richard Kettlewell
+Copyright: 2007, 2009-2011, 2014, -18 Richard Kettlewell
2015, Michel Kraus
License: GPL-2+
FIXME
+Files: acinclude.m4
+Copyright: 2007, 2011, 14,15,18 Richard Kettlewell
+License: GPL-2+
+ FIXME
+
+Files: Makefile.am
+Copyright: 2007, 2011, 14,16,18 Richard Kettlewell
+License: GPL-2+
+ FIXME
+
Files: debian/copyright-check
Copyright: 2016-2019, Jonas Smedegaard <dr@jones.dk>
License: GPL-3+
@@ -199,13 +205,3 @@ Copyright: 2007, 2011, 2016, Richard Kettlewell
License: UNKNOWN
FIXME
-Files: debian/source/lintian-overrides
-Copyright: GPL-2+
- GPL-3+
- LGPL-2+
- gpl-2+
- gpl-3+
- lgpl-2+
-License: UNKNOWN
- FIXME
-
diff --git a/debian/gbp.conf b/debian/gbp.conf
index 2a594ca..c6859d1 100644
--- a/debian/gbp.conf
+++ b/debian/gbp.conf
@@ -1,6 +1,15 @@
-# Configuration file for git-buildpackage and friends
+# clone this source: gbp clone $PKG_GIT_URL
+# track upstream source: git remote add upstream-git $UPSTREAM_GIT_URL
+# update this source: gbp pull
+# update upstream source: git fetch upstream-git --tags
+# import upstream release: gbp import-orig --upstream-vcs-tag=$VERSION --uscan
+# build package: gbp buildpackage
+# publish source release: gbp tag && gbp push
[DEFAULT]
pristine-tar = True
sign-tags = True
filter = */.git*
+debian-branch = debian/latest
+upstream-branch = upstream/latest
+dist = DEP14
diff --git a/debian/patches/1001_python3.patch b/debian/patches/1001_python3.patch
deleted file mode 100644
index d76fc08..0000000
--- a/debian/patches/1001_python3.patch
+++ /dev/null
@@ -1,162 +0,0 @@
-Description: Use Python 3
-Author: Jonas Smedegaard <dr@jones.dk>
-Last-Update: 2019-08-30
----
-This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -52,15 +52,15 @@
- check: gesftpserver sftpclient pwtest aliases
- rm -f *.gcda *.gcov
- ./pwtest
-- srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory tests $(TESTS)
-- srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory rotests --server ./gesftpserver-ro $(ROTESTS)
-- ${GCOV} ${srcdir}/*.c | ${PYTHON24} ${srcdir}/format-gconv-report --html .
-+ srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --directory tests $(TESTS)
-+ srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --directory rotests --server ./gesftpserver-ro $(ROTESTS)
-+ ${GCOV} ${srcdir}/*.c | ${PYTHON3} ${srcdir}/format-gconv-report --html .
-
- #${srcdir}/paramiko-test
-
- check-valgrind: gesftpserver-valgrind sftpclient pwtest aliases
- rm -f ,valgrind*
-- srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory tests --server ./gesftpserver-valgrind $(TESTS)
-+ srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --directory tests --server ./gesftpserver-valgrind $(TESTS)
-
- aliases: gesftpserver-ro gesftpserver-debug gesftpserver-ro-debug \
- gesftpserver-valgrind
---- a/acinclude.m4
-+++ b/acinclude.m4
-@@ -250,28 +250,26 @@
- ])
- ])
-
--AC_DEFUN([RJK_PYTHON24],[
-- AC_CACHE_CHECK([for Python 2.4 or better],[rjk_cv_python24],[
-- if python24 -V >/dev/null 2>&1; then
-- rjk_cv_python24=python24
-- elif python2.4 -V >/dev/null 2>&1; then
-- rjk_cv_python24=python2.4
-+AC_DEFUN([RJK_PYTHON3],[
-+ AC_CACHE_CHECK([for Python 3 or better],[rjk_cv_python3],[
-+ if python3 -V >/dev/null 2>&1; then
-+ rjk_cv_python3=python3
- elif python -V >confpyver 2>&1; then
- read p v < confpyver
- case "$v" in
-- 1* | 2.0* | 2.1* | 2.2* | 2.3* )
-+ 1* | 2* )
- ;;
- * )
-- rjk_cv_python24=python
-+ rjk_cv_python3=python
- ;;
- esac
- fi
- rm -f confpyver
-- if test "$rjk_cv_python24" = ""; then
-- AC_MSG_ERROR([cannot find Python 2.4 or better])
-+ if test "$rjk_cv_python3" = ""; then
-+ AC_MSG_ERROR([cannot find Python 3 or better])
- fi
- ])
-- AC_SUBST([PYTHON24],[$rjk_cv_python24])
-+ AC_SUBST([PYTHON3],[$rjk_cv_python3])
- ])
-
- dnl Local Variables:
---- a/configure.ac
-+++ b/configure.ac
-@@ -55,7 +55,7 @@
- RJK_GCC_ATTRS
- RJK_STAT_TIMESPEC
- RJK_GETOPT
--RJK_PYTHON24
-+RJK_PYTHON3
-
- dnl See commentary in v3.c for what's going on here
- AC_MSG_CHECKING([whether to reverse SSH_FXP_SYMLINK arguments])
---- a/format-gconv-report
-+++ b/format-gconv-report
-@@ -1,4 +1,4 @@
--#! /usr/bin/env python
-+#! /usr/bin/env python3
- # This file is part of the Green End SFTP Server.
- # Copyright (C) 2007 Richard Kettlewell
- #
-@@ -29,7 +29,7 @@
- return c
-
- def sgmlquote(s):
-- return string.join(map(sgmlquotechar, s),'')
-+ return string.join(list(map(sgmlquotechar, s)),'')
-
- percent = {}
- total_lines = 0
-@@ -64,13 +64,13 @@
- elif percent[a] > percent[b]: return 1
- else: return 0
-
--keys = percent.keys()
-+keys = list(percent.keys())
- keys.sort(cmp)
-
- if len(keys):
- for k in keys:
-- print "%20s: %d%%" % (k, percent[k])
-- print "Total coverage: %d%%" % (100 * (covered_lines / total_lines))
-+ print("%20s: %d%%" % (k, percent[k]))
-+ print("Total coverage: %d%%" % (100 * (covered_lines / total_lines)))
-
- if htmldir is not None and len(keys):
- index = open(os.path.join(htmldir, "index.html"), "w")
---- a/run-tests
-+++ b/run-tests
-@@ -1,4 +1,4 @@
--#! /usr/bin/env python
-+#! /usr/bin/env python3
- #
- # This file is part of the Green End SFTP Server.
- # Copyright (C) 2007, 2011, 2016 Richard Kettlewell
-@@ -29,7 +29,7 @@
- def rmrf(path):
- if os.path.lexists(path):
- if (not os.path.islink(path)) and os.path.isdir(path):
-- os.chmod(path, 0700)
-+ os.chmod(path, 0o700)
- for name in os.listdir(path):
- rmrf(os.path.join(path,name))
- os.rmdir(path)
-@@ -43,7 +43,7 @@
- if os.getuid() == 0:
- fatal("These tests are not suitable for running as root.")
-
--os.umask(022) # for consistent permissions
-+os.umask(0o22) # for consistent permissions
- failed = 0
- protocols = ['2', '3', '4', '5', '6', '7']
- dir = 'tests'
-@@ -120,7 +120,7 @@
- errors.append("EXPECTED[%d]: %s" % (n + 1, expected))
- errors.append(" GOT[%d]: %s" % (n + 1, got))
- except:
-- print "\n\nPossible invalid regexp:\n%s\n" % expected
-+ print("\n\nPossible invalid regexp:\n%s\n" % expected)
- raise
- else:
- if expected != got:
-@@ -145,12 +145,12 @@
- sys.stderr.write("passed\n")
-
- if failed:
-- print "%d tests failed" % failed
-+ print("%d tests failed" % failed)
- sys.exit(1)
- else:
- os.chdir("/")
- rmrf(os.path.join(builddir, ',testroot'))
-- print "OK"
-+ print("OK")
-
- # Local Variables:
- # mode:python
diff --git a/debian/patches/README b/debian/patches/README
deleted file mode 100644
index 80c1584..0000000
--- a/debian/patches/README
+++ /dev/null
@@ -1,3 +0,0 @@
-0xxx: Grabbed from upstream development.
-1xxx: Possibly relevant for upstream adoption.
-2xxx: Only relevant for official Debian release.
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index ec0fa51..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1 +0,0 @@
-1001_python3.patch
diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc
new file mode 100644
index 0000000..0ed4846
--- /dev/null
+++ b/debian/upstream/signing-key.asc
@@ -0,0 +1,284 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQENBEvSp5oBCACpVQe+NLiM90Y+c03CiRXUAK1NhmxcEefNLa18Layt4qQYVe+r
+4PSkF4EGJJFpaRGKvTzSqabAtnscfn5rKn9HPx2zEibd+71h7sVwGzw+k0yL0Rzx
+KlbLZUq5OPIAOMh3WS1RnqAE9yFf/D0EhSQDsieZinfmxJfpo6iCTS4d6aYQ/L5j
+6+hfLyuNQtQxgAz8v319lLTDG6uhFKbcRfVPvM5mHsKDtN0fZksCedxall6qMbeN
+ib5alV/492zok8m+kvnhz+GpcMwujo6MFwRFWLgzVQMyDO8s7i06rz8WOHxoaQOn
+4F+R7VsVfiYaoy8NDMt21al26pBLWT44xjnxABEBAAG0O1JpY2hhcmQgS2V0dGxl
+d2VsbCAoZGF5LXRvLWRheSB1c2FnZSkgPHJqa0BncmVlbmVuZC5vcmcudWs+iQFR
+BBMBCAA7AhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAhkBFiEEkAaw7XENuBt2
+02jZ0ziLoYp0G+8FAl5dhJsACgkQ0ziLoYp0G+/40QgAm4I+MnYz++Bjb+L+zOqW
+hcjLSwioy/UbfNKQyvLeLJzrusMfNXNjuemDSwK7Ht+P2unOotowbib1+hmYSAP5
+9LDqvFJ++eEvMSLlRnhVz8F+0owANASiFYZcuw9jWXw+DVLzlOHSyl1wdyhs/quP
+pGU6H8dQiPIy3Md1o/EpG2aOEM6DYrj7JsQYGRUuBXHWJ6FxZ0Y5ui4NVP69zPjy
+q1KUcbk/6MRsG78ywIuT3P1dCyNda48qhCCMnrjqAHWp5hNnMx9sbtU+4nARQMRj
+QMOztcNn2OWp7EnIdY2sSmSw1nbRNECOoPM1FW74VdqVQIum7zrkkKzk6z+8CkBE
+J7QoUmljaGFyZCBLZXR0bGV3ZWxsIDxyamtAZ3JlZW5lbmQub3JnLnVrPokBTgQT
+AQgAOAIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgBYhBJAGsO1xDbgbdtNo2dM4
+i6GKdBvvBQJeXYSbAAoJENM4i6GKdBvv4mQIAJX5EYkE5C/R2fdJxonZaWJkQxAl
+O67skqR2+JKCxELtmE1/S7hBZssJzVMU7VBBSyGnzGWp4L4tCHHl8sQDYG8ketnv
+rTAqqOAQQMSm4lQux0wOQQuh3cg/3fQLdwDCwOpWzIUB1TgPOxRzYn84WFcq1ErL
+YDEiYdpZ6PL9nZeZ0txfaX+Guv7qHToF1EUKY+67ladlpBy6jlMRPsRkyjhyAyBa
+x1GkSRSILDGHv3vVT/buVbL3mznp902t6QXJr3DnvuCENXbKWNDzhDwszMlhYOrs
+89E0uYoAtofEEoB2BUHtM7qI0YNE1VaDwXneSaX4OMiUaekvGqWlFXdrwje0MlJp
+Y2hhcmQgS2V0dGxld2VsbCA8cmljaGFyZEBzZmVyZS5ncmVlbmVuZC5vcmcudWs+
+iQFOBDABCAA4BQJZHwaxMR0gc2ZlcmUuZ3JlZW5lbmQub3JnLnVrIG1haWwgZG9t
+YWluIGlzIGdvaW5nIGF3YXkACgkQ0ziLoYp0G+8Vxwf+I2yhHdR1idOfyG6qpwCH
+SNvCSBTmgAlY711+W649zLv/7gKsRAM+Ea4S99nMq337skIcAHWaBoEmzzociXXe
+9VYyhdqowgJPTRVKrCypO0qjFVYfcl84Wn2PdXRMV+9qh5KkP+Fi0qOETylK1bqi
+WVlvKSHI9ngbxP+34kpbd6n6WzgnrrRWpJkRqhJwV5Q6EmsuOX19Mm1hHl26NwV7
+dgzXkZAJ8HJ0mhKObHo/q1wlZin9nr15uGP1ROmdVi46GbenRwSaoyxR+LjkFDGQ
+Ww627jKPrzxN77JLPWrRqznsTMG49lCgHlc6unyIn1vCCsc/Rvkwl1aTBuxELpUA
+ErQoUmljaGFyZCBLZXR0bGV3ZWxsIDxyamtAdGVycmFyYXEub3JnLnVrPokBTgQT
+AQgAOAIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgBYhBJAGsO1xDbgbdtNo2dM4
+i6GKdBvvBQJeXYSbAAoJENM4i6GKdBvvk5IH/07rIIgc4PC7ceRxTIOpPU/pVlhD
+aiibpOInk3SQNSnokbMHfdrq2Jo0GTYqawxIxKser4I4oILzbFJ9E5Gm/9Eay2W4
+wKnEZNnODpCFYA2I21oAaSSnOzBNnCPhkyGDjvtK7uQxg2239/gn03mjk0kAquv5
+bBsMbbacE0RBRHpM21eI+GEQyApQRnKfNq6BMrV9MfxTlaKyKLgCqc/2VXseRSQV
+ggPCQKOCRy6QR+y9h1MjooYkaeY67naKKDSekjJPNv8rzZQ5U2yFeasvJGltJCiw
+29Q3pkPBXkF/G0q1cSXqaKpL4q++xDrzf1ZROHk2I319Ru79Jo8ow/T2fbvR3nTe
+cgEQAAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAQEASABIAAD/4QJERXhpZgAA
+SUkqAAgAAAAKAA8BAgAIAAAAhgAAABABAgAJAAAAjgAAABIBAwABAAAAAQAAABoB
+BQABAAAAmAAAABsBBQABAAAAoAAAACgBAwABAAAAAgAAADEBAgAMAAAAqAAAADIB
+AgAUAAAAtAAAABMCAwABAAAAAQAAAGmHBAABAAAAyAAAAAAAAABTQU1TVU5HAFNN
+LU45MTBGAABIAAAAAQAAAEgAAAABAAAAR0lNUCAyLjguMTQAMjAxNTowNDoxOSAx
+NTozOToyMAARAJ2CBQABAAAAmgEAACKIAwABAAAAAgAAAACQBwAEAAAAMDIyMAOQ
+AgAUAAAAogEAAASQAgAUAAAAtgEAAAWSBQABAAAAygEAAAeSAwABAAAAAgAAAAqS
+BQABAAAA0gEAAHySBwBiAAAA2gEAAACgBwAEAAAAMDEwMAGgAwABAAAAAQAAAAKg
+BAABAAAA8AAAAAOgBAABAAAAIAEAAAKkAwABAAAAAAAAAAOkAwABAAAAAAAAAAWk
+AwABAAAAFgAAAAakAwABAAAAAgAAAAAAAAC+AAAAZAAAADIwMTU6MDQ6MTkgMTU6
+MjA6NDAAMjAxNTowNDoxOSAxNToyMDo0MAC5AAAAZAAAAKAAAABkAAAABwABAAcA
+BAAAADAxMDACAAQAAQAAAAAgAQAMAAQAAQAAAAAAAAAQAAUAAQAAAFoAAABAAAQA
+AQAAAAAAAABQAAQAAQAAAAEAAAAAAQMAAQAAAAAAAAAAAAAAAAAAAAAAAAD/4QcB
+aHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49J++7
+vycgaWQ9J1c1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCc/Pgo8eDp4bXBtZXRhIHht
+bG5zOng9J2Fkb2JlOm5zOm1ldGEvJz4KPHJkZjpSREYgeG1sbnM6cmRmPSdodHRw
+Oi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjJz4KCiA8cmRm
+OkRlc2NyaXB0aW9uIHhtbG5zOmV4aWY9J2h0dHA6Ly9ucy5hZG9iZS5jb20vZXhp
+Zi8xLjAvJz4KICA8ZXhpZjpJbWFnZVdpZHRoPjI1NjA8L2V4aWY6SW1hZ2VXaWR0
+aD4KICA8ZXhpZjpJbWFnZUxlbmd0aD4xNDQwPC9leGlmOkltYWdlTGVuZ3RoPgog
+IDxleGlmOk1ha2U+U0FNU1VORzwvZXhpZjpNYWtlPgogIDxleGlmOk1vZGVsPlNN
+LU45MTBGPC9leGlmOk1vZGVsPgogIDxleGlmOk9yaWVudGF0aW9uPkxlZnQtYm90
+dG9tPC9leGlmOk9yaWVudGF0aW9uPgogIDxleGlmOlhSZXNvbHV0aW9uPjcyPC9l
+eGlmOlhSZXNvbHV0aW9uPgogIDxleGlmOllSZXNvbHV0aW9uPjcyPC9leGlmOllS
+ZXNvbHV0aW9uPgogIDxleGlmOlJlc29sdXRpb25Vbml0PkluY2g8L2V4aWY6UmVz
+b2x1dGlvblVuaXQ+CiAgPGV4aWY6U29mdHdhcmU+TjkxMEZYWFUxQU5LNDwvZXhp
+ZjpTb2Z0d2FyZT4KICA8ZXhpZjpEYXRlVGltZT4yMDE1OjA0OjE5IDE1OjIwOjQw
+PC9leGlmOkRhdGVUaW1lPgogIDxleGlmOllDYkNyUG9zaXRpb25pbmc+Q2VudGVy
+ZWQ8L2V4aWY6WUNiQ3JQb3NpdGlvbmluZz4KICA8ZXhpZjpGTnVtYmVyPmYvMS45
+PC9leGlmOkZOdW1iZXI+CiAgPGV4aWY6RXhwb3N1cmVQcm9ncmFtPk5vcm1hbCBw
+cm9ncmFtPC9leGlmOkV4cG9zdXJlUHJvZ3JhbT4KICA8ZXhpZjpFeGlmVmVyc2lv
+bj5FeGlmIFZlcnNpb24gMi4yPC9leGlmOkV4aWZWZXJzaW9uPgogIDxleGlmOkRh
+dGVUaW1lT3JpZ2luYWw+MjAxNTowNDoxOSAxNToyMDo0MDwvZXhpZjpEYXRlVGlt
+ZU9yaWdpbmFsPgogIDxleGlmOkRhdGVUaW1lRGlnaXRpemVkPjIwMTU6MDQ6MTkg
+MTU6MjA6NDA8L2V4aWY6RGF0ZVRpbWVEaWdpdGl6ZWQ+CiAgPGV4aWY6TWF4QXBl
+cnR1cmVWYWx1ZT4xLjg1IEVWIChmLzEuOSk8L2V4aWY6TWF4QXBlcnR1cmVWYWx1
+ZT4KICA8ZXhpZjpNZXRlcmluZ01vZGU+Q2VudGVyLXdlaWdodGVkIGF2ZXJhZ2U8
+L2V4aWY6TWV0ZXJpbmdNb2RlPgogIDxleGlmOkZvY2FsTGVuZ3RoPjEuNiBtbTwv
+ZXhpZjpGb2NhbExlbmd0aD4KICA8ZXhpZjpNYWtlck5vdGU+OTggYnl0ZXMgdW5k
+ZWZpbmVkIGRhdGE8L2V4aWY6TWFrZXJOb3RlPgogIDxleGlmOkZsYXNoUGl4VmVy
+c2lvbj5GbGFzaFBpeCBWZXJzaW9uIDEuMDwvZXhpZjpGbGFzaFBpeFZlcnNpb24+
+CiAgPGV4aWY6Q29sb3JTcGFjZT5zUkdCPC9leGlmOkNvbG9yU3BhY2U+CiAgPGV4
+aWY6UGl4ZWxYRGltZW5zaW9uPjI1NjA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgog
+IDxleGlmOlBpeGVsWURpbWVuc2lvbj4xNDQwPC9leGlmOlBpeGVsWURpbWVuc2lv
+bj4KICA8ZXhpZjpFeHBvc3VyZU1vZGU+QXV0byBleHBvc3VyZTwvZXhpZjpFeHBv
+c3VyZU1vZGU+CiAgPGV4aWY6V2hpdGVCYWxhbmNlPkF1dG8gd2hpdGUgYmFsYW5j
+ZTwvZXhpZjpXaGl0ZUJhbGFuY2U+CiAgPGV4aWY6Rm9jYWxMZW5ndGhJbjM1bW1G
+aWxtPjIyPC9leGlmOkZvY2FsTGVuZ3RoSW4zNW1tRmlsbT4KICA8ZXhpZjpTY2Vu
+ZUNhcHR1cmVUeXBlPlBvcnRyYWl0PC9leGlmOlNjZW5lQ2FwdHVyZVR5cGU+CiA8
+L3JkZjpEZXNjcmlwdGlvbj4KCjwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cjw/eHBh
+Y2tldCBlbmQ9J3InPz4K/9sAQwATDQ4RDgwTEQ8RFRQTFx0wHx0aGh06KiwjMEU9
+SUdEPUNBTFZtXUxRaFJBQ1+CYGhxdXt8e0pchpCFd49teHt2/9sAQwEUFRUdGR04
+Hx84dk9DT3Z2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2
+dnZ2dnZ2dnZ2/8IAEQgBIADwAwESAAIRAQMRAf/EABkAAAMBAQEAAAAAAAAAAAAA
+AAABAgMEBf/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB9AAA
+AAAABDyNOWt/HPR8s9Tyj0vNOzjjp5zs4j0fNPd8Svf4Dv5DrwjdDAAAAABMAAAA
+AEHIZ+cXmaZl5AimKQRVDzKYNSQk2xPb8o93zz0s00AAAAAAAAAzOXzhIQTZKJsg
+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
+kzFA37mlFKD4rUQPQ43O/EcqOAly
+=T5PZ
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/debian/watch b/debian/watch
index 699d756..faad1cf 100644
--- a/debian/watch
+++ b/debian/watch
@@ -3,5 +3,7 @@ version=4
# update: gbp import-orig --upstream-vcs-tag=vX.Y.Z --uscan
opts=\
-dversionmangle=s/[~+](dfsg|ds)\d*$//,repacksuffix=~ds \
+repacksuffix=~ds,\
+pgpmode=auto,\
+dversionmangle=auto \
https://www.greenend.org.uk/rjk/sftpserver/sftpserver-@ANY_VERSION@@ARCHIVE_EXT@
diff --git a/debug.c b/debug.c
index 831a321..74c1325 100644
--- a/debug.c
+++ b/debug.c
@@ -45,7 +45,7 @@ static void opendebug(void) {
if(sftp_debugpath) {
int fd;
- if((fd = open(sftp_debugpath, O_WRONLY|O_CREAT|O_TRUNC, 0600)) >= 0)
+ if((fd = open(sftp_debugpath, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0)
debugfp = fdopen(fd, "w");
else
fprintf(stderr, "%s: %s\n", sftp_debugpath, strerror(errno));
@@ -66,7 +66,7 @@ void sftp_debug_hexdump(const void *ptr, size_t n) {
output += sprintf(output, "%4lx ", (unsigned long)i);
for(j = 0; j < 16; ++j)
if(i + j < n)
- output += sprintf(output, " %02x", p[i + j]);
+ output += sprintf(output, " %02x", p[i + j]);
else {
strcpy(output, " ");
output += 3;
@@ -75,7 +75,7 @@ void sftp_debug_hexdump(const void *ptr, size_t n) {
output += 2;
for(j = 0; j < 16; ++j)
if(i + j < n)
- *output++ = isprint(p[i + j]) ? p[i+j] : '.';
+ *output++ = isprint(p[i + j]) ? p[i + j] : '.';
*output++ = '\n';
*output = 0;
fputs(buffer, debugfp);
diff --git a/debug.h b/debug.h
index 6e763ee..35175f0 100644
--- a/debug.h
+++ b/debug.h
@@ -21,7 +21,7 @@
/** @file debug.h @brief Debug support interface */
#ifndef DEBUG_H
-#define DEBUG_H
+# define DEBUG_H
/* Debug support */
@@ -45,7 +45,7 @@ void sftp_debug_hexdump(const void *ptr, size_t n);
*
* @ref sftp_debugging must be nonzero.
*/
-void sftp_debug_printf(const char *fmt, ...) attribute((format(printf,1,2)));
+void sftp_debug_printf(const char *fmt, ...) attribute((format(printf, 1, 2)));
/** @brief Issue a debug message
* @param x Parenthesized format string and arguments
@@ -56,10 +56,11 @@ void sftp_debug_printf(const char *fmt, ...) attribute((format(printf,1,2)));
* D(("the value of x is %d", x));
* @endcode
*/
-#define D(x) do { \
- if(sftp_debugging) \
- sftp_debug_printf x; \
-} while(0)
+# define D(x) \
+ do { \
+ if(sftp_debugging) \
+ sftp_debug_printf x; \
+ } while(0)
#endif /* DEBUG_H */
diff --git a/dirname.c b/dirname.c
index 3c478f1..bf08459 100644
--- a/dirname.c
+++ b/dirname.c
@@ -34,7 +34,7 @@ const char *sftp_dirname(struct allocator *a, const char *path) {
assert(len + 1 != 0);
d = sftp_alloc(a, len + 1);
- memcpy(d, path, len);
+ sftp_memcpy(d, path, len);
return d;
} else
return "/";
diff --git a/format-gconv-report b/format-gconv-report
index 6b50e5d..019a63f 100755
--- a/format-gconv-report
+++ b/format-gconv-report
@@ -1,6 +1,6 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
# This file is part of the Green End SFTP Server.
-# Copyright (C) 2007 Richard Kettlewell
+# Copyright (C) 2007, 2018 Richard Kettlewell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -59,18 +59,13 @@ for line in sys.stdin:
covered_lines += this_lines * this_pc / 100.0
name = None
-def cmp(a,b):
- if percent[a] < percent[b]: return -1
- elif percent[a] > percent[b]: return 1
- else: return 0
-
-keys = percent.keys()
-keys.sort(cmp)
+keys = list(percent.keys())
+keys.sort(key=lambda a: percent[a])
if len(keys):
for k in keys:
- print "%20s: %d%%" % (k, percent[k])
- print "Total coverage: %d%%" % (100 * (covered_lines / total_lines))
+ print("%20s: %d%%" % (k, percent[k]))
+ print("Total coverage: %d%%" % (100 * (covered_lines / total_lines)))
if htmldir is not None and len(keys):
index = open(os.path.join(htmldir, "index.html"), "w")
diff --git a/getopt.c b/getopt.c
index 4744e43..97198ba 100644
--- a/getopt.c
+++ b/getopt.c
@@ -1,3 +1,4 @@
+// clang-format off
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to drepper@gnu.org
diff --git a/getopt.h b/getopt.h
index b0147e9..157b45d 100644
--- a/getopt.h
+++ b/getopt.h
@@ -1,3 +1,4 @@
+// clang-format off
/* Declarations for getopt.
Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/getopt1.c b/getopt1.c
index 3d264f2..987c804 100644
--- a/getopt1.c
+++ b/getopt1.c
@@ -1,3 +1,4 @@
+// clang-format off
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
Free Software Foundation, Inc.
diff --git a/globals.c b/globals.c
index 592f47f..805ae31 100644
--- a/globals.c
+++ b/globals.c
@@ -21,11 +21,32 @@
#include "sftpcommon.h"
#include "types.h"
#include "globals.h"
+#include "thread.h"
+#include "utils.h"
+#include <stdlib.h>
+#include <string.h>
#if NTHREADS > 1
struct queue *workqueue = 0;
#endif
+static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER;
+static enum sftp_state state;
+
+void sftp_state_set(enum sftp_state s) {
+ ferrcheck(pthread_mutex_lock(&state_lock));
+ state = s;
+ ferrcheck(pthread_mutex_unlock(&state_lock));
+}
+
+enum sftp_state sftp_state_get(void) {
+ enum sftp_state r;
+ ferrcheck(pthread_mutex_lock(&state_lock));
+ r = state;
+ ferrcheck(pthread_mutex_unlock(&state_lock));
+ return r;
+}
+
/*
Local Variables:
c-basic-offset:2
diff --git a/globals.h b/globals.h
index 1ae5f43..2e7382b 100644
--- a/globals.h
+++ b/globals.h
@@ -21,14 +21,14 @@
/** @file globals.h @brief Global variables interface */
#ifndef GLOBALS_H
-#define GLOBALS_H
+# define GLOBALS_H
-#if NTHREADS > 1
+# if NTHREADS > 1
/** @brief Work queue for the thread pool */
extern struct queue *workqueue;
-#else
-# define workqueue 0
-#endif
+# else
+# define workqueue 0
+# endif
/** @brief V6 protocol callbacks */
extern const struct sftpprotocol sftp_v6;
diff --git a/handle.c b/handle.c
index eb7bf26..33cad28 100644
--- a/handle.c
+++ b/handle.c
@@ -34,14 +34,14 @@
/** @brief Handle data structure */
struct handle {
- int type; /**< @brief @ref SSH_FXP_OPEN or @ref SSH_FXP_OPENDIR */
- uint32_t tag; /**< @brief Unique tag or 0 for unused */
+ int type; /**< @brief @ref SSH_FXP_OPEN or @ref SSH_FXP_OPENDIR */
+ uint32_t tag; /**< @brief Unique tag or 0 for unused */
union {
- int fd; /**< @brief File descriptor for a file */
- DIR *dir; /**< @brief Directory stream */
+ int fd; /**< @brief File descriptor for a file */
+ DIR *dir; /**< @brief Directory stream */
} u;
- char *path; /**< @brief Name of file or directory */
- unsigned flags; /**< @brief Flags */
+ char *path; /**< @brief Name of file or directory */
+ unsigned flags; /**< @brief Flags */
};
/** @brief Table of handles */
@@ -71,23 +71,23 @@ static void find_free_handle(struct handleid *id, int type) {
/* need more space */
nhandles = (nhandles ? 2 * nhandles : 16);
assert(nhandles != 0);
- handles = xrecalloc(handles, nhandles, sizeof (*handles));
- memset(handles + n, 0, (nhandles - n) * sizeof (*handles));
+ handles = sftp_xrecalloc(handles, nhandles, sizeof(*handles));
+ sftp_memset(handles + n, 0, (nhandles - n) * sizeof(*handles));
}
while(!sequence)
- ++sequence; /* never have a tag of 0 */
+ ++sequence; /* never have a tag of 0 */
handles[n].tag = sequence++;
handles[n].type = type;
id->id = n;
id->tag = handles[n].tag;
}
-void sftp_handle_new_file(struct handleid *id,
- int fd, const char *path, unsigned flags) {
+void sftp_handle_new_file(struct handleid *id, int fd, const char *path,
+ unsigned flags) {
ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
find_free_handle(id, SSH_FXP_OPEN);
handles[id->id].u.fd = fd;
- handles[id->id].path = xstrdup(path);
+ handles[id->id].path = sftp_xstrdup(path);
handles[id->id].flags = flags;
ferrcheck(pthread_mutex_unlock(&sftp_handle_lock));
}
@@ -96,18 +96,17 @@ void sftp_handle_new_dir(struct handleid *id, DIR *dp, const char *path) {
ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
find_free_handle(id, SSH_FXP_OPENDIR);
handles[id->id].u.dir = dp;
- handles[id->id].path = xstrdup(path);
+ handles[id->id].path = sftp_xstrdup(path);
ferrcheck(pthread_mutex_unlock(&sftp_handle_lock));
}
-uint32_t sftp_handle_get_fd(const struct handleid *id,
- int *fd, unsigned *flagsp) {
+uint32_t sftp_handle_get_fd(const struct handleid *id, int *fd,
+ unsigned *flagsp) {
uint32_t rc;
ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
- if(id->id < nhandles
- && id->tag == handles[id->id].tag
- && handles[id->id].type == SSH_FXP_OPEN) {
+ if(id->id < nhandles && id->tag == handles[id->id].tag &&
+ handles[id->id].type == SSH_FXP_OPEN) {
*fd = handles[id->id].u.fd;
if(flagsp)
*flagsp = handles[id->id].flags;
@@ -118,14 +117,13 @@ uint32_t sftp_handle_get_fd(const struct handleid *id,
return rc;
}
-uint32_t sftp_handle_get_dir(const struct handleid *id,
- DIR **dp, const char **pathp) {
+uint32_t sftp_handle_get_dir(const struct handleid *id, DIR **dp,
+ const char **pathp) {
uint32_t rc;
ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
- if(id->id < nhandles
- && id->tag == handles[id->id].tag
- && handles[id->id].type == SSH_FXP_OPENDIR) {
+ if(id->id < nhandles && id->tag == handles[id->id].tag &&
+ handles[id->id].type == SSH_FXP_OPENDIR) {
*dp = handles[id->id].u.dir;
if(pathp)
*pathp = handles[id->id].path;
@@ -142,9 +140,8 @@ uint32_t sftp_handle_close(const struct handleid *id) {
if(!id->tag)
return SSH_FX_INVALID_HANDLE;
ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
- if(id->id < nhandles
- && id->tag == handles[id->id].tag) {
- handles[id->id].tag = 0; /* free up */
+ if(id->id < nhandles && id->tag == handles[id->id].tag) {
+ handles[id->id].tag = 0; /* free up */
switch(handles[id->id].type) {
case SSH_FXP_OPEN:
if(close(handles[id->id].u.fd) < 0)
@@ -163,8 +160,7 @@ uint32_t sftp_handle_close(const struct handleid *id) {
}
free(handles[id->id].path);
handles[id->id].path = NULL;
- }
- else
+ } else
rc = SSH_FX_INVALID_HANDLE;
ferrcheck(pthread_mutex_unlock(&sftp_handle_lock));
return rc;
@@ -174,8 +170,7 @@ unsigned sftp_handle_flags(const struct handleid *id) {
unsigned rc;
ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
- if(id->id < nhandles
- && id->tag == handles[id->id].tag)
+ if(id->id < nhandles && id->tag == handles[id->id].tag)
rc = handles[id->id].flags;
else
rc = 0;
diff --git a/handle.h b/handle.h
index 2f65d02..fa5a27d 100644
--- a/handle.h
+++ b/handle.h
@@ -21,9 +21,9 @@
/** @file handle.h @brief File handle interface */
#ifndef HANDLE_H
-#define HANDLE_H
+# define HANDLE_H
-#include <dirent.h>
+# include <dirent.h>
/** @brief Definition of a handle */
struct handleid {
@@ -52,20 +52,20 @@ struct handleid {
* - @ref HANDLE_TEXT
* - @ref HANDLE_APPEND
*/
-void sftp_handle_new_file(struct handleid *id, int fd, const char *path,
+void sftp_handle_new_file(struct handleid *id, int fd, const char *path,
unsigned flags);
/** @brief Handle flag for text files
*
* See sftp_handle_new_file().
*/
-#define HANDLE_TEXT 0x0001
+# define HANDLE_TEXT 0x0001
/** @brief Handle flag for append-mode files
*
* See sftp_handle_new_file().
*/
-#define HANDLE_APPEND 0x0002
+# define HANDLE_APPEND 0x0002
/** @brief Create a new directory handle
* @param id Where to store new handle
@@ -88,8 +88,7 @@ unsigned sftp_handle_flags(const struct handleid *id);
* @param flagsp Where to store flags, or a null pointer
* @return 0 on success, @ref SSH_FX_INVALID_HANDLE on error
*/
-uint32_t sftp_handle_get_fd(const struct handleid *id,
- int *fd,
+uint32_t sftp_handle_get_fd(const struct handleid *id, int *fd,
unsigned *flagsp);
/** @brief Retrieve the directory stream attached to handle @p id
@@ -102,8 +101,8 @@ uint32_t sftp_handle_get_fd(const struct handleid *id,
* points to the handle's copy of the path name. It will not outlive the
* handle.
*/
-uint32_t sftp_handle_get_dir(const struct handleid *id,
- DIR **dp, const char **pathp);
+uint32_t sftp_handle_get_dir(const struct handleid *id, DIR **dp,
+ const char **pathp);
/** @brief Destroy a handle
* @param id Handle to close
diff --git a/parse.c b/parse.c
index 92a6be0..10e45b9 100644
--- a/parse.c
+++ b/parse.c
@@ -27,6 +27,7 @@
#include "sftp.h"
#include "globals.h"
#include "putword.h"
+#include "utils.h"
#include <string.h>
uint32_t sftp_parse_uint8(struct sftpjob *job, uint8_t *ur) {
@@ -71,14 +72,14 @@ uint32_t sftp_parse_string(struct sftpjob *job, char **strp, size_t *lenp) {
if((rc = sftp_parse_uint32(job, &len)) != SSH_FX_OK)
return rc;
if(len == 0xFFFFFFFF)
- return SSH_FX_BAD_MESSAGE; /* overflow */
+ return SSH_FX_BAD_MESSAGE; /* overflow */
if(job->left < len)
- return SSH_FX_BAD_MESSAGE; /* not enough bytes to satisfy */
+ return SSH_FX_BAD_MESSAGE; /* not enough bytes to satisfy */
if(lenp)
*lenp = len;
if(strp) {
- str = sftp_alloc(job->a, len + 1); /* 0-fills */
- memcpy(str, job->ptr, len);
+ str = sftp_alloc(job->a, len + 1); /* 0-fills */
+ sftp_memcpy(str, job->ptr, len);
*strp = str;
}
job->ptr += len;
@@ -88,7 +89,7 @@ uint32_t sftp_parse_string(struct sftpjob *job, char **strp, size_t *lenp) {
uint32_t sftp_parse_path(struct sftpjob *job, char **strp) {
uint32_t rc;
-
+
if((rc = sftp_parse_string(job, strp, 0)) != SSH_FX_OK)
return rc;
return protocol->decode(job, strp);
@@ -97,10 +98,12 @@ uint32_t sftp_parse_path(struct sftpjob *job, char **strp) {
uint32_t sftp_parse_handle(struct sftpjob *job, struct handleid *id) {
uint32_t len, rc;
- if((rc = sftp_parse_uint32(job, &len)) != SSH_FX_OK
- || len != 8
- || (rc = sftp_parse_uint32(job, &id->id)) != SSH_FX_OK
- || (rc = sftp_parse_uint32(job, &id->tag) != SSH_FX_OK))
+ if((rc = sftp_parse_uint32(job, &len)) != SSH_FX_OK)
+ return rc;
+ if(len != 8)
+ return SSH_FX_BAD_MESSAGE;
+ if((rc = sftp_parse_uint32(job, &id->id)) != SSH_FX_OK ||
+ (rc = sftp_parse_uint32(job, &id->tag) != SSH_FX_OK))
return rc;
return SSH_FX_OK;
}
diff --git a/parse.h b/parse.h
index 6ef3a64..6a27a08 100644
--- a/parse.h
+++ b/parse.h
@@ -21,7 +21,7 @@
/** @file parse.h @brief Message parsing interface */
#ifndef PARSE_H
-#define PARSE_H
+# define PARSE_H
/** @brief Retrieve the next byte from a message
* @param job Job containing message
@@ -84,34 +84,36 @@ uint32_t sftp_parse_path(struct sftpjob *job, char **strp);
*/
uint32_t sftp_parse_handle(struct sftpjob *job, struct handleid *id);
-#if CLIENT
+# if CLIENT
/** @brief Error checking wrapper for sftp_parse_... functions
* @param E expression to check
*
- * If the parse fails, @ref fatal() is called. This macro is only used in the
- * client.
+ * If the parse fails, @ref sftp_fatal() is called. This macro is only used in
+ * the client.
*/
-#define cpcheck(E) do { \
- const uint32_t rc = (E); \
- if(rc) { \
- D(("%s:%d: %s returned %"PRIu32, __FILE__, __LINE__, #E, rc)); \
- fatal("error parsing response from server"); \
- } \
-} while(0)
-#else
+# define cpcheck(E) \
+ do { \
+ const uint32_t rc = (E); \
+ if(rc) { \
+ D(("%s:%d: %s returned %" PRIu32, __FILE__, __LINE__, #E, rc)); \
+ sftp_fatal("error parsing response from server"); \
+ } \
+ } while(0)
+# else
/** @brief Error checking wrapper for sftp_parse_... functions
* @param E expression to check
*
* If the parse fails, @c return is invoked with the error code.
*/
-#define pcheck(E) do { \
- const uint32_t rc = (E); \
- if(rc != SSH_FX_OK) { \
- D(("%s:%d: %s: %"PRIu32, __FILE__, __LINE__, #E, rc)); \
- return rc; \
- } \
-} while(0)
-#endif
+# define pcheck(E) \
+ do { \
+ const uint32_t rc = (E); \
+ if(rc != SSH_FX_OK) { \
+ D(("%s:%d: %s: %" PRIu32, __FILE__, __LINE__, #E, rc)); \
+ return rc; \
+ } \
+ } while(0)
+# endif
#endif /* PARSE_H */
diff --git a/putword.h b/putword.h
index 9e185ad..9657654 100644
--- a/putword.h
+++ b/putword.h
@@ -21,28 +21,29 @@
/** @file putword.h @brief Macros for storing network-order values */
#ifndef PUTWORD_H
-#define PUTWORD_H
+# define PUTWORD_H
-#include <arpa/inet.h>
+# include <arpa/inet.h>
-#ifndef ASM
-# define ASM 1
-#endif
+# ifndef ASM
+# define ASM 1
+# endif
/** @brief Unaligned 16-bit network-order store
* @param where Where to store value
* @param u Value to store
*/
static inline void put16(void *where, uint16_t u) {
-#if (__i386__ || __amd64__) && __GNUC__ && ASM
+# if(__i386__ || __amd64__) && __GNUC__ && ASM
__asm__ volatile("xchg %h[U],%b[U]\n\tmovw %[U],%[WHERE]"
- : [U] "+Q" (u)
- : [WHERE] "m" (*(uint16_t *)where));
-#else
+ : [U] "+Q"(u)
+ : [WHERE] "m"(*(uint16_t *)where)
+ : "memory");
+# else
uint8_t *ptr = where;
*ptr++ = (uint8_t)(u >> 8);
*ptr = (uint8_t)u;
-#endif
+# endif
}
/** @brief Unaligned 32-bit network-order store
@@ -50,17 +51,18 @@ static inline void put16(void *where, uint16_t u) {
* @param u Value to store
*/
static inline void put32(void *where, uint32_t u) {
-#if (__i386__ || __amd64__) && __GNUC__ && ASM
+# if(__i386__ || __amd64__) && __GNUC__ && ASM
__asm__ volatile("bswapl %[U]\n\tmovl %[U],%[WHERE]"
- : [U] "+r" (u)
- : [WHERE] "m" (*(uint32_t *)where));
-#else
+ : [U] "+r"(u)
+ : [WHERE] "m"(*(uint32_t *)where)
+ : "memory");
+# else
uint8_t *ptr = where;
*ptr++ = (uint8_t)(u >> 24);
*ptr++ = (uint8_t)(u >> 16);
*ptr++ = (uint8_t)(u >> 8);
*ptr++ = (uint8_t)(u);
-#endif
+# endif
}
/** @brief Unaligned 64-bit network-order store
@@ -68,14 +70,15 @@ static inline void put32(void *where, uint32_t u) {
* @param u Value to store
*/
static inline void put64(void *where, uint64_t u) {
-#if __amd64__ && __GNUC__ && ASM
+# if __amd64__ && __GNUC__ && ASM
__asm__ volatile("bswapq %[U]\n\tmovq %[U],%[WHERE]"
- : [U] "+r" (u)
- : [WHERE] "m" (*(uint64_t *)where));
-#else
+ : [U] "+r"(u)
+ : [WHERE] "m"(*(uint64_t *)where)
+ : "memory");
+# else
put32(where, u >> 32);
put32((char *)where + 4, (uint32_t)u);
-#endif
+# endif
}
/** @brief Unaligned 16-bit network-order fetch
@@ -83,16 +86,16 @@ static inline void put64(void *where, uint64_t u) {
* @return Fetched value
*/
static inline uint16_t get16(const void *where) {
-#if (__i386__ || __amd64__) && __GNUC__ && ASM
+# if(__i386__ || __amd64__) && __GNUC__ && ASM
uint16_t r;
__asm__("movw %[WHERE],%[R]\t\nxchg %h[R],%b[R]"
- : [R] "=Q" (r)
- : [WHERE] "m" (*(const uint16_t *)where));
+ : [R] "=Q"(r)
+ : [WHERE] "m"(*(const uint16_t *)where));
return r;
-#else
+# else
const uint8_t *ptr = where;
return (ptr[0] << 8) + ptr[1];
-#endif
+# endif
}
/** @brief Unaligned 32-bit network-order fetch
@@ -100,16 +103,16 @@ static inline uint16_t get16(const void *where) {
* @return Fetched value
*/
static inline uint32_t get32(const void *where) {
-#if (__i386__ || __amd64__) && __GNUC__ && ASM
+# if(__i386__ || __amd64__) && __GNUC__ && ASM
uint32_t r;
__asm__("movl %[WHERE],%[R]\n\tbswapl %[R]"
- : [R] "=r" (r)
- : [WHERE] "m" (*(const uint32_t *)where));
+ : [R] "=r"(r)
+ : [WHERE] "m"(*(const uint32_t *)where));
return r;
-#else
+# else
const uint8_t *ptr = where;
return ((unsigned)ptr[0] << 24) + (ptr[1] << 16) + (ptr[2] << 8) + ptr[3];
-#endif
+# endif
}
/** @brief Unaligned 64-bit network-order fetch
@@ -117,15 +120,15 @@ static inline uint32_t get32(const void *where) {
* @return Fetched value
*/
static inline uint64_t get64(const void *where) {
-#if __amd64__ && __GNUC__ && ASM
+# if __amd64__ && __GNUC__ && ASM
uint64_t r;
__asm__("movq %[WHERE],%[R]\n\tbswapq %[R]"
- : [R] "=r" (r)
- : [WHERE] "m" (*(const uint64_t *)where));
+ : [R] "=r"(r)
+ : [WHERE] "m"(*(const uint64_t *)where));
return r;
-#else
+# else
return ((uint64_t)get32(where) << 32) + get32((const char *)where + 4);
-#endif
+# endif
}
#endif /* PUTWORD_H */
diff --git a/pwtest.c b/pwtest.c
index 1910462..7adb290 100644
--- a/pwtest.c
+++ b/pwtest.c
@@ -19,6 +19,7 @@
*/
#include "sftpcommon.h"
#include "putword.h"
+#include "utils.h"
#include <string.h>
#include <assert.h>
@@ -27,7 +28,7 @@ int main() {
int n, m;
for(n = 0; n <= 14; ++n) {
- memset(buffer, 0xAF, 16);
+ sftp_memset(buffer, 0xAF, 16);
put16(buffer + n, 0x0102);
assert(get16(buffer + n) == 0x0102);
for(m = 0; m < 16; ++m) {
@@ -39,9 +40,9 @@ int main() {
}
for(n = 0; n <= 12; ++n) {
- memset(buffer, 0xAF, 16);
+ sftp_memset(buffer, 0xAF, 16);
put32(buffer + n, 0x01020304);
- //assert(get32(buffer + n) == 0x01020304);
+ // assert(get32(buffer + n) == 0x01020304);
for(m = 0; m < 16; ++m) {
if(m >= n && m < n + 4)
assert(buffer[m] == 1 + m - n);
@@ -51,9 +52,9 @@ int main() {
}
for(n = 0; n <= 8; ++n) {
- memset(buffer, 0xAF, 16);
+ sftp_memset(buffer, 0xAF, 16);
put64(buffer + n, 0x0102030405060708ULL);
- //assert(get64(buffer + n) == 0x0102030405060708ULL);
+ // assert(get64(buffer + n) == 0x0102030405060708ULL);
for(m = 0; m < 16; ++m) {
if(m >= n && m < n + 8)
assert(buffer[m] == 1 + m - n);
diff --git a/queue.c b/queue.c
index 81c3327..bd87bad 100644
--- a/queue.c
+++ b/queue.c
@@ -103,21 +103,20 @@ static void *queue_thread(void *vq) {
return 0;
}
-void queue_init(struct queue **qr,
- const struct queuedetails *details,
- int nthreads) {
+void queue_init(struct queue **qr, const struct queuedetails *details,
+ int nthreads) {
int n;
struct queue *q;
- q = xmalloc(sizeof *q);
- memset(q, 0, sizeof *q);
+ q = sftp_xmalloc(sizeof *q);
+ sftp_memset(q, 0, sizeof *q);
q->jobs = 0;
q->jobstail = &q->jobs;
ferrcheck(pthread_mutex_init(&q->m, 0));
ferrcheck(pthread_cond_init(&q->c, 0));
q->details = details;
q->nthreads = nthreads;
- q->threads = xcalloc(nthreads, sizeof (pthread_t));
+ q->threads = sftp_xcalloc(nthreads, sizeof(pthread_t));
q->join = 0;
for(n = 0; n < q->nthreads; ++n)
ferrcheck(pthread_create(&q->threads[n], 0, queue_thread, q));
@@ -127,7 +126,7 @@ void queue_init(struct queue **qr,
void queue_add(struct queue *q, void *job) {
struct queuejob *qj;
- qj = xmalloc(sizeof *qj);
+ qj = sftp_xmalloc(sizeof *qj);
qj->next = 0;
qj->job = job;
ferrcheck(pthread_mutex_lock(&q->m));
@@ -139,7 +138,7 @@ void queue_add(struct queue *q, void *job) {
void queue_destroy(struct queue *q) {
int n;
-
+
if(q) {
ferrcheck(pthread_mutex_lock(&q->m));
q->join = 1;
diff --git a/queue.h b/queue.h
index 552d533..cbebc23 100644
--- a/queue.h
+++ b/queue.h
@@ -21,18 +21,18 @@
/** @file queue.h @brief Thread pool/queue interface */
#ifndef QUEUE_H
-#define QUEUE_H
+# define QUEUE_H
struct allocator;
-#if NTHREADS > 1
+# if NTHREADS > 1
/** @brief Queue-specific callbacks */
struct queuedetails {
/** @brief Per-thread initialization
* @return Per-thread value to be passed to other callbacks
*/
- void *(*init)();
+ void *(*init)(void);
/** @brief Worker method
* @param job Job to process
@@ -52,9 +52,8 @@ struct queuedetails {
* @param details Queue-specific callbacks (not copied)
* @param nthreads Number of threads to create
*/
-void queue_init(struct queue **qp,
- const struct queuedetails *details,
- int nthreads);
+void queue_init(struct queue **qp, const struct queuedetails *details,
+ int nthreads);
/** @brief Add a job to a thread pool's queue
* @param q Queue pointer
@@ -71,7 +70,7 @@ void queue_add(struct queue *q, void *job);
* All unprocessed jobs are executed before completion. */
void queue_destroy(struct queue *q);
-#endif
+# endif
#endif /* QUEUE_H */
diff --git a/readwrite.c b/readwrite.c
index aabe878..7a1af21 100644
--- a/readwrite.c
+++ b/readwrite.c
@@ -19,4 +19,3 @@
*/
int readonly;
-
diff --git a/realpath.c b/realpath.c
index 5702883..56e0a88 100644
--- a/realpath.c
+++ b/realpath.c
@@ -32,9 +32,10 @@
#include <limits.h>
static char *process_path(struct allocator *a, char *result, size_t *nresultp,
- const char *path, unsigned flags);
+ const char *path, unsigned flags);
-char *sftp_find_realpath(struct allocator *a, const char *path, unsigned flags) {
+char *sftp_find_realpath(struct allocator *a, const char *path,
+ unsigned flags) {
char *cwd, *abspath, *result = 0;
size_t nresult = 0;
@@ -58,7 +59,7 @@ char *sftp_find_realpath(struct allocator *a, const char *path, unsigned flags)
}
/* The result always starts with a / */
- result = append(a, result, &nresult, "/");
+ result = sftp_str_append(a, result, &nresult, "/");
/* All the work happens below */
return process_path(a, result, &nresult, path, flags);
@@ -73,7 +74,7 @@ char *sftp_find_realpath(struct allocator *a, const char *path, unsigned flags)
* @return Modified result
*/
static char *process_path(struct allocator *a, char *result, size_t *nresultp,
- const char *path, unsigned flags) {
+ const char *path, unsigned flags) {
D(("process_path path='%s' result='%s'", path, result));
while(*path) {
if(*path == '/')
@@ -92,20 +93,20 @@ static char *process_path(struct allocator *a, char *result, size_t *nresultp,
if(ls != result)
*ls = 0;
else
- strcpy(result, "/"); /* /.. = / */
+ strcpy(result, "/"); /* /.. = / */
D(("result[0] -> '%s'", result));
} else {
const size_t oldresultlen = strlen(result);
/* Append the new path element */
if(result[1])
- result = append(a, result, nresultp, "/");
- result = appendn(a, result, nresultp, path, elementlen);
+ result = sftp_str_append(a, result, nresultp, "/");
+ result = sftp_str_appendn(a, result, nresultp, path, elementlen);
D(("result[1] -> '%s'", result));
/* If we're following symlinks, see if the path so far points to a
* link */
if(flags & RP_READLINK) {
const char *const target = sftp_do_readlink(a, result);
-
+
if(target) {
if(target[0] == '/')
/* Absolute symlink, go back to the root */
@@ -134,7 +135,7 @@ static char *process_path(struct allocator *a, char *result, size_t *nresultp,
}
D(("result[2] -> '%s'", result));
}
- path += elementlen;
+ path += elementlen;
}
}
D(("returning '%s'", result));
diff --git a/run-tests b/run-tests
index c43fe40..cf89d0d 100755
--- a/run-tests
+++ b/run-tests
@@ -1,7 +1,7 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
#
# This file is part of the Green End SFTP Server.
-# Copyright (C) 2007, 2011, 2016 Richard Kettlewell
+# Copyright (C) 2007, 2011, 2016, 2018 Richard Kettlewell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -18,32 +18,38 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
-import os,sys,re,string
-from subprocess import Popen,PIPE,STDOUT
+import os
+import sys
+import re
+import string
+from subprocess import Popen, PIPE, STDOUT
srcdir = os.path.abspath(os.getenv('srcdir'))
builddir = os.path.abspath('.')
client = os.path.abspath("sftpclient")
server = "gesftpserver"
+
def rmrf(path):
if os.path.lexists(path):
if (not os.path.islink(path)) and os.path.isdir(path):
- os.chmod(path, 0700)
+ os.chmod(path, 0o700)
for name in os.listdir(path):
- rmrf(os.path.join(path,name))
+ rmrf(os.path.join(path, name))
os.rmdir(path)
else:
os.remove(path)
+
def fatal(msg):
sys.stderr.write("%s\n" % msg)
sys.exit(1)
+
if os.getuid() == 0:
fatal("These tests are not suitable for running as root.")
-os.umask(022) # for consistent permissions
+os.umask(0o22) # for consistent permissions
failed = 0
protocols = ['2', '3', '4', '5', '6', '7']
dir = 'tests'
@@ -56,7 +62,7 @@ while len(args) > 0 and args[0][0] == '-':
args = args[2:]
elif args[0] == "--server":
server = args[1]
- args = args[2:]
+ args = args[2:]
elif args[0] == "--directory":
dir = args[1]
args = args[2:]
@@ -72,85 +78,127 @@ if len(args) > 0:
tests = args
else:
tests = os.listdir(os.path.join(srcdir, dir))
+# Execute tests in a consistent order
tests.sort()
# Clean up
rmrf(os.path.join(builddir, ',testroot'))
+# Colorize output (if possible)
+
+
+def colored(text, color=None, on_color=None, attrs=None):
+ """Uncolorized output"""
+ return text
+
+
+if sys.stdout.isatty():
+ try:
+ import termcolor
+ colored = termcolor.colored
+ except:
+ pass
+
for test in tests:
for proto in protocols:
+ # Skip dotfiles, backup files, and tests that don't apply to the
+ # current protocol
if ('.' in test
or not proto in test
or '#' in test
- or '~' in test):
+ or '~' in test):
continue
sys.stderr.write("Testing %s/%s protocol %s ... " % (dir, test, proto))
- root = os.path.join(builddir, ',testroot','%s.%s' % (test, proto))
+ # Make a working directory for the test
+ root = os.path.join(builddir, ',testroot', '%s.%s' % (test, proto))
os.makedirs(root)
os.chdir(root)
- clientcmd=[client,
- "--force-version", proto,
- "-P", server,
- "-b", os.path.join(srcdir, dir, test),
- '--echo',
- '--fix-sigpipe', # stupid Python
- '--no-stop-on-error']
+ # Run the client with the server as a child process
+ clientcmd = [client,
+ "--force-version", proto,
+ "-P", server,
+ "-b", os.path.join(srcdir, dir, test),
+ '--echo',
+ '--fix-sigpipe', # stupid Python
+ '--no-stop-on-error']
if debug:
- clientcmd+=["--program-debug-path",
- "%s/%s-%s.debug" % (builddir, test, proto)]
+ debug_path = "%s/%s-%s.debug" % (builddir, test, proto)
+ # Save server debug output
+ clientcmd += ["--program-debug-path", debug_path]
+ # Run the client
output = Popen(clientcmd,
stdout=PIPE,
- stderr=STDOUT).communicate()[0].split('\n')
+ stderr=STDOUT).communicate()[0].split(b'\n')
+ # Get the output, with newlines stripped
+ output = [str(s, "ASCII") for s in output]
if output[len(output)-1] == "":
output = output[:-1]
- n = 0
- errors = []
- for expected in file(os.path.join(srcdir, dir, '%s' % test)):
- expected = expected[:-1] # strip newline
- if n >= len(output):
- errors.append("EXPECTED[%d]: %s" % (n, expected))
- errors.append(" GOT[%d]: EOF" % n)
- break
- got = output[n]
- n += 1
- if len(expected) > 0 and expected[0] == '#':
- expected = expected[1:]
- try:
- if not re.match(expected, got):
- errors.append("EXPECTED[%d]: %s" % (n + 1, expected))
- errors.append(" GOT[%d]: %s" % (n + 1, got))
- except:
- print "\n\nPossible invalid regexp:\n%s\n" % expected
- raise
+ # Get the script, with newlines stripped
+ with open(os.path.join(srcdir, dir, '%s' % test), "r") as f:
+ script = [l[:-1] for l in f]
+ # Find the maximum line length in each
+ omax = max([len(l) for l in output])
+ smax = max([len(l) for l in script])
+ errors = 0
+ report = []
+ # Iterate over the lines, checking them and formatting the results
+ for lineno in range(0, max(len(output), len(script))):
+ if lineno >= len(output):
+ # Truncated output is bad
+ ok = False
+ sline = script[lineno]
+ oline = ""
+ elif lineno >= len(script):
+ # Excessive output is bad
+ ok = False
+ sline = ""
+ oline = output[lineno]
+ else:
+ sline = script[lineno]
+ oline = output[lineno]
+ if len(sline) > 0 and sline[0] == '#':
+ # Lines starting # are regexps matching expected output
+ pattern = sline[1:]
+ ok = re.match(pattern, oline)
+ else:
+ # Other lines are the commands, which we expect to be
+ # echoed back.
+ ok = (oline == sline)
+ if ok:
+ marker = " "
+ def f(t): return t
else:
- if expected != got:
- errors.append("EXPECTED[%d]: %s" % (n + 1, expected))
- errors.append(" GOT[%d]: %s" % (n + 1, got))
- if n < len(output):
- while n < len(output):
- errors.append(" EXTRA[%d]: %s" % (n + 1, output[n]))
- n += 1
- if len(errors) > 0:
- sys.stderr.write("FAILED\n")
- sys.stderr.write("---errors---\n");
- for n in range(0, len(errors)):
- sys.stderr.write("%3d: %s\n" % (n+1, errors[n]))
- sys.stderr.write("\n")
- sys.stderr.write("---output---\n");
- for n in range(0, len(output)):
- sys.stderr.write("%3d: %s\n" % (n+1, output[n]))
- sys.stderr.write("---end---\n");
+ # Mismatching lines are marked with a * and colored red (if
+ # possible)
+ marker = "*"
+ errors += 1
+ def f(t): return colored(t, "red")
+ report.append(f("%s %-*s %-*s\n" %
+ (marker, smax, sline, omax, oline)))
+ if errors > 0:
+ sys.stderr.write(colored("FAILED\n", "red"))
+ sys.stderr.write("Command:\n %s\n" % " ".join(clientcmd))
+ sys.stderr.write("Output discrepancies:\n")
+ for l in report:
+ sys.stderr.write(l)
+ if debug:
+ sys.stderr.write("Server debug:\n")
+ with open(debug_path, "r") as f:
+ for l in f.readlines():
+ sys.stderr.write(l)
failed += 1
else:
- sys.stderr.write("passed\n")
+ sys.stderr.write(colored("passed\n", "green"))
if failed:
- print "%d tests failed" % failed
+ print(colored("%d tests failed" % failed, "red"))
sys.exit(1)
else:
+ # On success, delete the test root. It's preserved for inspection on
+ # failure.
os.chdir("/")
rmrf(os.path.join(builddir, ',testroot'))
- print "OK"
+ print(colored("OK", "green"))
# Local Variables:
# mode:python
diff --git a/send.c b/send.c
index 57df723..42669cb 100644
--- a/send.c
+++ b/send.c
@@ -41,25 +41,28 @@
static pthread_mutex_t output_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
-int sftpout = 1; /* default is stdout */
+int sftpout = 1; /* default is stdout */
/** @brief Store a 16-bit value */
-#define sftp_send_raw16(u) do { \
- put16(&w->buffer[w->bufused], u); \
- w->bufused += 2; \
-} while(0)
+#define sftp_send_raw16(u) \
+ do { \
+ put16(&w->buffer[w->bufused], u); \
+ w->bufused += 2; \
+ } while(0)
/** @brief Store a 32-bit value */
-#define sftp_send_raw32(u) do { \
- put32(&w->buffer[w->bufused], u); \
- w->bufused += 4; \
-} while(0)
+#define sftp_send_raw32(u) \
+ do { \
+ put32(&w->buffer[w->bufused], u); \
+ w->bufused += 4; \
+ } while(0)
/** @brief Store a 64-bit value */
-#define sftp_send_raw64(u) do { \
- put64(&w->buffer[w->bufused], u); \
- w->bufused += 8; \
-} while(0)
+#define sftp_send_raw64(u) \
+ do { \
+ put64(&w->buffer[w->bufused], u); \
+ w->bufused += 8; \
+ } while(0)
void sftp_send_need(struct worker *w, size_t n) {
assert(w->bufused < 0x80000000);
@@ -68,14 +71,14 @@ void sftp_send_need(struct worker *w, size_t n) {
while(newsize && newsize < w->bufsize + n)
newsize <<= 1;
if(!newsize)
- fatal("sftp_send_need: out of memory (%zu)", n);
- w->buffer = xrealloc(w->buffer, w->bufsize = newsize);
+ sftp_fatal("sftp_send_need: out of memory (%zu)", n);
+ w->buffer = sftp_xrealloc(w->buffer, w->bufsize = newsize);
}
}
void sftp_send_begin(struct worker *w) {
w->bufused = 0;
- sftp_send_uint32(w, 0); /* placeholder for length */
+ sftp_send_uint32(w, 0); /* placeholder for length */
}
void sftp_send_end(struct worker *w) {
@@ -98,7 +101,7 @@ void sftp_send_end(struct worker *w) {
if((n = write(sftpout, w->buffer + written, w->bufused - written)) > 0)
written += n;
else if(n < 0)
- fatal("error sending response: %s", strerror(errno));
+ sftp_fatal("error sending response: %s", strerror(errno));
ferrcheck(pthread_mutex_unlock(&output_lock));
w->bufused = 0x80000000;
}
@@ -126,7 +129,7 @@ void sftp_send_uint64(struct worker *w, uint64_t u) {
void sftp_send_bytes(struct worker *w, const void *bytes, size_t n) {
sftp_send_need(w, n + 4);
sftp_send_raw32(n);
- memcpy(w->buffer + w->bufused, bytes, n);
+ sftp_memcpy(w->buffer + w->bufused, bytes, n);
w->bufused += n;
}
@@ -136,7 +139,7 @@ void sftp_send_string(struct worker *w, const char *s) {
void sftp_send_path(struct sftpjob *job, struct worker *w, const char *path) {
if(protocol->encode(job, (char **)&path))
- fatal("cannot encode local path name '%s'", path);
+ sftp_fatal("cannot encode local path name '%s'", path);
sftp_send_string(w, path);
}
diff --git a/send.h b/send.h
index 93e06b6..351f227 100644
--- a/send.h
+++ b/send.h
@@ -21,7 +21,7 @@
/** @file send.h @brief Message sending interface */
#ifndef SEND_H
-#define SEND_H
+# define SEND_H
/** @brief Ensure there are @p n bytes spare in the message buffer
* @param w Worker containing message
diff --git a/serialize.c b/serialize.c
index c3acdbc..9ce8837 100644
--- a/serialize.c
+++ b/serialize.c
@@ -53,10 +53,10 @@
* to be clever and allow re-ordering of operations where different orders
* couldn't make a difference.
*
- * 4) Reads don't include @ref SSH_FXP_READDIR. Therefore such requests are always
- * serialized, which saves us having to worry about the thread safety of the
- * <dirent.h> functions. Indeed you could say this about any other operation
- * but readdir() is the most obvious one to worry about.
+ * 4) Reads don't include @ref SSH_FXP_READDIR. Therefore such requests are
+ * always serialized, which saves us having to worry about the thread safety of
+ * the <dirent.h> functions. Indeed you could say this about any other
+ * operation but readdir() is the most obvious one to worry about.
*
*/
@@ -110,12 +110,11 @@ static inline int handles_equal(const struct handleid *h1,
* @param b Serialization queue entry
* @return Nonzero if the IO ranges for @p a and @p b overlap
*/
-static int ranges_overlap(const struct sqnode *a,
- const struct sqnode *b) {
+static int ranges_overlap(const struct sqnode *a, const struct sqnode *b) {
if(a->len && b->len) {
const uint64_t aend = a->offset + a->len - 1;
const uint64_t bend = b->offset + b->len - 1;
-
+
if(aend >= b->offset && aend <= bend)
return 1;
if(bend >= a->offset && bend <= aend)
@@ -135,8 +134,8 @@ static int ranges_overlap(const struct sqnode *a,
*/
static int reorderable(const struct sqnode *q1, const struct sqnode *q2,
unsigned flags) {
- if((q1->type == SSH_FXP_READ || q1->type == SSH_FXP_WRITE)
- && (q2->type == SSH_FXP_READ || q2->type == SSH_FXP_WRITE)) {
+ if((q1->type == SSH_FXP_READ || q1->type == SSH_FXP_WRITE) &&
+ (q2->type == SSH_FXP_READ || q2->type == SSH_FXP_WRITE)) {
/* We allow reads and writes to be re-ordered up to a point */
if(!handles_equal(&q1->hid, &q2->hid)) {
/* Operations on different handles can always be re-ordered. */
@@ -148,7 +147,7 @@ static int reorderable(const struct sqnode *q1, const struct sqnode *q2,
* measure). */
if(q1->type == SSH_FXP_READ && q2->type == SSH_FXP_READ)
return 0;
- if(flags & (HANDLE_TEXT|HANDLE_APPEND))
+ if(flags & (HANDLE_TEXT | HANDLE_APPEND))
/* Operations on text or append-write files cannot be re-oredered. */
return 0;
if(q1->type == SSH_FXP_WRITE || q2->type == SSH_FXP_WRITE)
@@ -173,24 +172,26 @@ void queue_serializable_job(struct sftpjob *job) {
job->ptr = job->data;
job->left = job->len;
- if(!sftp_parse_uint8(job, &type)
- && (type == SSH_FXP_READ || type == SSH_FXP_WRITE)
- && sftp_parse_uint32(job, &id) == SSH_FX_OK
- && sftp_parse_handle(job, &hid) == SSH_FX_OK
- && sftp_parse_uint64(job, &offset) == SSH_FX_OK
- && sftp_parse_uint32(job, &len) == SSH_FX_OK) {
+ type = 0; // First sftp_parse_uint8 can't fail, but GCC LTO doesn't know this
+ // and moans
+ if(!sftp_parse_uint8(job, &type) &&
+ (type == SSH_FXP_READ || type == SSH_FXP_WRITE) &&
+ sftp_parse_uint32(job, &id) == SSH_FX_OK &&
+ sftp_parse_handle(job, &hid) == SSH_FX_OK &&
+ sftp_parse_uint64(job, &offset) == SSH_FX_OK &&
+ sftp_parse_uint32(job, &len) == SSH_FX_OK) {
/* This is a well-formed read or write operation */
len64 = len;
handleflags = sftp_handle_flags(&hid);
} else {
/* Anything else has dummy values */
- memset(&hid, 0, sizeof hid);
+ sftp_memset(&hid, 0, sizeof hid);
offset = 0;
len64 = ~(uint64_t)0;
handleflags = 0;
}
ferrcheck(pthread_mutex_lock(&sq_mutex));
- q = xmalloc(sizeof *q);
+ q = sftp_xmalloc(sizeof *q);
q->older = newest;
q->job = job;
q->type = type;
diff --git a/serialize.h b/serialize.h
index a3b1815..559916e 100644
--- a/serialize.h
+++ b/serialize.h
@@ -21,7 +21,7 @@
/** @file serialize.h @brief Request serialization interface */
#ifndef SERIALIZE_H
-#define SERIALIZE_H
+# define SERIALIZE_H
/** @brief Establish a job's place in the serialization queue
* @param job Job to establish
diff --git a/sftp.h b/sftp.h
index 9a576b7..c6bbc52 100644
--- a/sftp.h
+++ b/sftp.h
@@ -21,10 +21,14 @@
/** @file sftp.h @brief SFTP definitions
*
* Specifications:
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-02.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-04.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-13.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-02.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-04.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-13.txt
*
* See also:
* - @ref type
@@ -40,183 +44,183 @@
*/
#ifndef SFTP_H
-#define SFTP_H
+# define SFTP_H
/** @defgroup type SFTP 'type' definitions
* @{
*/
/** @brief Protocol initialization */
-#define SSH_FXP_INIT 1
+# define SSH_FXP_INIT 1
/** @brief Server version */
-#define SSH_FXP_VERSION 2
+# define SSH_FXP_VERSION 2
/** @brief Open file */
-#define SSH_FXP_OPEN 3
+# define SSH_FXP_OPEN 3
/** @brief Close handle */
-#define SSH_FXP_CLOSE 4
+# define SSH_FXP_CLOSE 4
/** @brief Read bytes */
-#define SSH_FXP_READ 5
+# define SSH_FXP_READ 5
/** @brief Write bytes */
-#define SSH_FXP_WRITE 6
+# define SSH_FXP_WRITE 6
/** @brief Get file attributes by name
*
* Do not follow symlinks.
*/
-#define SSH_FXP_LSTAT 7
+# define SSH_FXP_LSTAT 7
/** @brief Get file attributes by handle */
-#define SSH_FXP_FSTAT 8
+# define SSH_FXP_FSTAT 8
/** @brief Set file attributes by name */
-#define SSH_FXP_SETSTAT 9
+# define SSH_FXP_SETSTAT 9
/** @brief Set file attributes by handle */
-#define SSH_FXP_FSETSTAT 10 /* 0x0A */
+# define SSH_FXP_FSETSTAT 10 /* 0x0A */
/** @brief Open directory */
-#define SSH_FXP_OPENDIR 11 /* 0x0B */
+# define SSH_FXP_OPENDIR 11 /* 0x0B */
/** @brief Read from directory */
-#define SSH_FXP_READDIR 12 /* 0x0C */
+# define SSH_FXP_READDIR 12 /* 0x0C */
/** @brief Remove file */
-#define SSH_FXP_REMOVE 13 /* 0x0D */
+# define SSH_FXP_REMOVE 13 /* 0x0D */
/** @brief Create directory */
-#define SSH_FXP_MKDIR 14 /* 0x0E */
+# define SSH_FXP_MKDIR 14 /* 0x0E */
/** @brief Remove directory */
-#define SSH_FXP_RMDIR 15 /* 0x0F */
+# define SSH_FXP_RMDIR 15 /* 0x0F */
/** @brief Canonicalize path */
-#define SSH_FXP_REALPATH 16 /* 0x10 */
+# define SSH_FXP_REALPATH 16 /* 0x10 */
/** @brief Get file attributes by name
*
* Do follow symlinks.
*/
-#define SSH_FXP_STAT 17 /* 0x11 */
+# define SSH_FXP_STAT 17 /* 0x11 */
/** @brief Rename file */
-#define SSH_FXP_RENAME 18 /* 0x12 */
+# define SSH_FXP_RENAME 18 /* 0x12 */
/** @brief Read symbolic link */
-#define SSH_FXP_READLINK 19 /* 0x13 */
+# define SSH_FXP_READLINK 19 /* 0x13 */
/** @brief Create symbolic link */
-#define SSH_FXP_SYMLINK 20 /* 0x14 */
+# define SSH_FXP_SYMLINK 20 /* 0x14 */
/** @brief Create hard link */
-#define SSH_FXP_LINK 21 /* 0x15 */
+# define SSH_FXP_LINK 21 /* 0x15 */
/** @brief Lock byte range */
-#define SSH_FXP_BLOCK 22 /* 0x16 */
+# define SSH_FXP_BLOCK 22 /* 0x16 */
/** @brief Unlock byte range */
-#define SSH_FXP_UNBLOCK 23 /* 0x17 */
+# define SSH_FXP_UNBLOCK 23 /* 0x17 */
/** @brief Response with a status */
-#define SSH_FXP_STATUS 101 /* 0x65 */
+# define SSH_FXP_STATUS 101 /* 0x65 */
/** @brief Response with a handle */
-#define SSH_FXP_HANDLE 102 /* 0x66 */
+# define SSH_FXP_HANDLE 102 /* 0x66 */
/** @brief Response with data bytes */
-#define SSH_FXP_DATA 103 /* 0x67 */
+# define SSH_FXP_DATA 103 /* 0x67 */
/** @brief Response with a name */
-#define SSH_FXP_NAME 104 /* 0x68 */
+# define SSH_FXP_NAME 104 /* 0x68 */
/** @brief Response with attributes */
-#define SSH_FXP_ATTRS 105 /* 0x69 */
+# define SSH_FXP_ATTRS 105 /* 0x69 */
/** @brief Execute an extended command */
-#define SSH_FXP_EXTENDED 200 /* 0xC8 */
+# define SSH_FXP_EXTENDED 200 /* 0xC8 */
/** @brief Extended response format */
-#define SSH_FXP_EXTENDED_REPLY 201 /* 0xC9 */
+# define SSH_FXP_EXTENDED_REPLY 201 /* 0xC9 */
/** @} */
-#define SSH_ACL_CAP_ALLOW 0x00000001
-#define SSH_ACL_CAP_DENY 0x00000002
-#define SSH_ACL_CAP_AUDIT 0x00000004
-#define SSH_ACL_CAP_ALARM 0x00000008
-#define SSH_ACL_CAP_INHERIT_ACCESS 0x00000010
-#define SSH_ACL_CAP_INHERIT_AUDIT_ALARM 0x00000020
+# define SSH_ACL_CAP_ALLOW 0x00000001
+# define SSH_ACL_CAP_DENY 0x00000002
+# define SSH_ACL_CAP_AUDIT 0x00000004
+# define SSH_ACL_CAP_ALARM 0x00000008
+# define SSH_ACL_CAP_INHERIT_ACCESS 0x00000010
+# define SSH_ACL_CAP_INHERIT_AUDIT_ALARM 0x00000020
/** @defgroup valid_attribute_flags SFTP 'valid-attribute-flags' definitions
* @{
*/
/** @brief @c size field is present */
-#define SSH_FILEXFER_ATTR_SIZE 0x00000001
+# define SSH_FILEXFER_ATTR_SIZE 0x00000001
/** @brief @c uid and @c gid fiels are present
*
* This is for v3 only.
*/
-#define SSH_FILEXFER_ATTR_UIDGID 0x00000002
+# define SSH_FILEXFER_ATTR_UIDGID 0x00000002
/** @brief @c permissions field is present */
-#define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
+# define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
/** @brief @c atime field is present
*
* This is for v4 and later.
*/
-#define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008
+# define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008
/** @brief @c atime and @c mtime fiels are present
*
* This is for v3 only.
*/
-#define SSH_FILEXFER_ACMODTIME 0x00000008
+# define SSH_FILEXFER_ACMODTIME 0x00000008
/** @brief @c createtime field is present */
-#define SSH_FILEXFER_ATTR_CREATETIME 0x00000010
+# define SSH_FILEXFER_ATTR_CREATETIME 0x00000010
/** @brief @c mtime field is present */
-#define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020
+# define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020
/** @brief @c ACL field is present */
-#define SSH_FILEXFER_ATTR_ACL 0x00000040
+# define SSH_FILEXFER_ATTR_ACL 0x00000040
/** @brief @c owner and @c group fields are present */
-#define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080
+# define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080
/** @brief Times include subsecond fields */
-#define SSH_FILEXFER_ATTR_SUBSECOND_TIMES 0x00000100
+# define SSH_FILEXFER_ATTR_SUBSECOND_TIMES 0x00000100
/** @brief @c attrib-bits and @c attrib-bits-valid fields are present */
-#define SSH_FILEXFER_ATTR_BITS 0x00000200
+# define SSH_FILEXFER_ATTR_BITS 0x00000200
/** @brief @c allocaiton-size field is present */
-#define SSH_FILEXFER_ATTR_ALLOCATION_SIZE 0x00000400
+# define SSH_FILEXFER_ATTR_ALLOCATION_SIZE 0x00000400
/** @brief @c text-hint field is present */
-#define SSH_FILEXFER_ATTR_TEXT_HINT 0x00000800
+# define SSH_FILEXFER_ATTR_TEXT_HINT 0x00000800
/** @brief @c mime-type field is present */
-#define SSH_FILEXFER_ATTR_MIME_TYPE 0x00001000
+# define SSH_FILEXFER_ATTR_MIME_TYPE 0x00001000
/** @brief @c link-count field is present */
-#define SSH_FILEXFER_ATTR_LINK_COUNT 0x00002000
+# define SSH_FILEXFER_ATTR_LINK_COUNT 0x00002000
/** @brief @c untranslated-name field is present */
-#define SSH_FILEXFER_ATTR_UNTRANSLATED_NAME 0x00004000
+# define SSH_FILEXFER_ATTR_UNTRANSLATED_NAME 0x00004000
/** @brief @c time field is present */
-#define SSH_FILEXFER_ATTR_CTIME 0x00008000
+# define SSH_FILEXFER_ATTR_CTIME 0x00008000
/** @brief Extended attributes present */
-#define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
+# define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
/** @} */
@@ -225,111 +229,111 @@
*/
/** @brief Regular file */
-#define SSH_FILEXFER_TYPE_REGULAR 1
+# define SSH_FILEXFER_TYPE_REGULAR 1
/** @brief Directory */
-#define SSH_FILEXFER_TYPE_DIRECTORY 2
+# define SSH_FILEXFER_TYPE_DIRECTORY 2
/** @brief Symbolic link */
-#define SSH_FILEXFER_TYPE_SYMLINK 3
+# define SSH_FILEXFER_TYPE_SYMLINK 3
/** @brief Special file
*
* This is for files where the type is known but cannot be exprssed in SFTP. */
-#define SSH_FILEXFER_TYPE_SPECIAL 4
+# define SSH_FILEXFER_TYPE_SPECIAL 4
/** @brief Unknown file type */
-#define SSH_FILEXFER_TYPE_UNKNOWN 5
+# define SSH_FILEXFER_TYPE_UNKNOWN 5
/** @brief Socket */
-#define SSH_FILEXFER_TYPE_SOCKET 6
+# define SSH_FILEXFER_TYPE_SOCKET 6
/** @brief Character device */
-#define SSH_FILEXFER_TYPE_CHAR_DEVICE 7
+# define SSH_FILEXFER_TYPE_CHAR_DEVICE 7
/** @brief Block device */
-#define SSH_FILEXFER_TYPE_BLOCK_DEVICE 8
+# define SSH_FILEXFER_TYPE_BLOCK_DEVICE 8
/** @brief Named pipe */
-#define SSH_FILEXFER_TYPE_FIFO 9
+# define SSH_FILEXFER_TYPE_FIFO 9
/** @} */
-#define SFX_ACL_CONTROL_INCLUDED 0x00000001
-#define SFX_ACL_CONTROL_PRESENT 0x00000002
-#define SFX_ACL_CONTROL_INHERITED 0x00000004
-#define SFX_ACL_AUDIT_ALARM_INCLUDED 0x00000010
-
-#define ACE4_ACCESS_ALLOWED_ACE_TYPE 0x00000000
-#define ACE4_ACCESS_DENIED_ACE_TYPE 0x00000001
-#define ACE4_SYSTEM_AUDIT_ACE_TYPE 0x00000002
-#define ACE4_SYSTEM_ALARM_ACE_TYPE 0x00000003
-
-#define ACE4_FILE_INHERIT_ACE 0x00000001
-#define ACE4_DIRECTORY_INHERIT_ACE 0x00000002
-#define ACE4_NO_PROPAGATE_INHERIT_ACE 0x00000004
-#define ACE4_INHERIT_ONLY_ACE 0x00000008
-#define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010
-#define ACE4_FAILED_ACCESS_ACE_FLAG 0x00000020
-#define ACE4_IDENTIFIER_GROUP 0x00000040
-
-#define ACE4_READ_DATA 0x00000001
-#define ACE4_LIST_DIRECTORY 0x00000001
-#define ACE4_WRITE_DATA 0x00000002
-#define ACE4_ADD_FILE 0x00000002
-#define ACE4_APPEND_DATA 0x00000004
-#define ACE4_ADD_SUBDIRECTORY 0x00000004
-#define ACE4_READ_NAMED_ATTRS 0x00000008
-#define ACE4_WRITE_NAMED_ATTRS 0x00000010
-#define ACE4_EXECUTE 0x00000020
-#define ACE4_DELETE_CHILD 0x00000040
-#define ACE4_READ_ATTRIBUTES 0x00000080
-#define ACE4_WRITE_ATTRIBUTES 0x00000100
-#define ACE4_DELETE 0x00010000
-#define ACE4_READ_ACL 0x00020000
-#define ACE4_WRITE_ACL 0x00040000
-#define ACE4_WRITE_OWNER 0x00080000
-#define ACE4_SYNCHRONIZE 0x00100000
+# define SFX_ACL_CONTROL_INCLUDED 0x00000001
+# define SFX_ACL_CONTROL_PRESENT 0x00000002
+# define SFX_ACL_CONTROL_INHERITED 0x00000004
+# define SFX_ACL_AUDIT_ALARM_INCLUDED 0x00000010
+
+# define ACE4_ACCESS_ALLOWED_ACE_TYPE 0x00000000
+# define ACE4_ACCESS_DENIED_ACE_TYPE 0x00000001
+# define ACE4_SYSTEM_AUDIT_ACE_TYPE 0x00000002
+# define ACE4_SYSTEM_ALARM_ACE_TYPE 0x00000003
+
+# define ACE4_FILE_INHERIT_ACE 0x00000001
+# define ACE4_DIRECTORY_INHERIT_ACE 0x00000002
+# define ACE4_NO_PROPAGATE_INHERIT_ACE 0x00000004
+# define ACE4_INHERIT_ONLY_ACE 0x00000008
+# define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010
+# define ACE4_FAILED_ACCESS_ACE_FLAG 0x00000020
+# define ACE4_IDENTIFIER_GROUP 0x00000040
+
+# define ACE4_READ_DATA 0x00000001
+# define ACE4_LIST_DIRECTORY 0x00000001
+# define ACE4_WRITE_DATA 0x00000002
+# define ACE4_ADD_FILE 0x00000002
+# define ACE4_APPEND_DATA 0x00000004
+# define ACE4_ADD_SUBDIRECTORY 0x00000004
+# define ACE4_READ_NAMED_ATTRS 0x00000008
+# define ACE4_WRITE_NAMED_ATTRS 0x00000010
+# define ACE4_EXECUTE 0x00000020
+# define ACE4_DELETE_CHILD 0x00000040
+# define ACE4_READ_ATTRIBUTES 0x00000080
+# define ACE4_WRITE_ATTRIBUTES 0x00000100
+# define ACE4_DELETE 0x00010000
+# define ACE4_READ_ACL 0x00020000
+# define ACE4_WRITE_ACL 0x00040000
+# define ACE4_WRITE_OWNER 0x00080000
+# define ACE4_SYNCHRONIZE 0x00100000
/** @defgroup attrib_bits SFTP 'attrib-bits' definitions
* @{
*/
/** @brief File is read-only (advisory) */
-#define SSH_FILEXFER_ATTR_FLAGS_READONLY 0x00000001
+# define SSH_FILEXFER_ATTR_FLAGS_READONLY 0x00000001
/** @brief File is part of the OS */
-#define SSH_FILEXFER_ATTR_FLAGS_SYSTEM 0x00000002
+# define SSH_FILEXFER_ATTR_FLAGS_SYSTEM 0x00000002
/** @brief File is hidden */
-#define SSH_FILEXFER_ATTR_FLAGS_HIDDEN 0x00000004
+# define SSH_FILEXFER_ATTR_FLAGS_HIDDEN 0x00000004
/** @brief Filenames in this directory are case-insensitive */
-#define SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE 0x00000008
+# define SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE 0x00000008
/** @brief File should be archived */
-#define SSH_FILEXFER_ATTR_FLAGS_ARCHIVE 0x00000010
+# define SSH_FILEXFER_ATTR_FLAGS_ARCHIVE 0x00000010
/** @brief File is stored on encrypted media */
-#define SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED 0x00000020
+# define SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED 0x00000020
/** @brief File is stored on compressed media */
-#define SSH_FILEXFER_ATTR_FLAGS_COMPRESSED 0x00000040
+# define SSH_FILEXFER_ATTR_FLAGS_COMPRESSED 0x00000040
/** @brief File is sparse */
-#define SSH_FILEXFER_ATTR_FLAGS_SPARSE 0x00000080
+# define SSH_FILEXFER_ATTR_FLAGS_SPARSE 0x00000080
/** @brief File is append-only */
-#define SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY 0x00000100
+# define SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY 0x00000100
/** @brief File cannot be delete, renamed, linked to or written */
-#define SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE 0x00000200
+# define SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE 0x00000200
/** @brief Modifications to file are synchronous */
-#define SSH_FILEXFER_ATTR_FLAGS_SYNC 0x00000400
+# define SSH_FILEXFER_ATTR_FLAGS_SYNC 0x00000400
/** @brief Filename could not be converted to UTF-8 */
-#define SSH_FILEXFER_ATTR_FLAGS_TRANSLATION_ERR 0x00000800
+# define SSH_FILEXFER_ATTR_FLAGS_TRANSLATION_ERR 0x00000800
/** @} */
@@ -338,16 +342,16 @@
*/
/** @brief Server knows file is a text file */
-#define SSH_FILEXFER_ATTR_KNOWN_TEXT 0x00
+# define SSH_FILEXFER_ATTR_KNOWN_TEXT 0x00
/** @brief Server believes file is a text file */
-#define SSH_FILEXFER_ATTR_GUESSED_TEXT 0x01
+# define SSH_FILEXFER_ATTR_GUESSED_TEXT 0x01
/** @brief Server knows file is a binary file */
-#define SSH_FILEXFER_ATTR_KNOWN_BINARY 0x02
+# define SSH_FILEXFER_ATTR_KNOWN_BINARY 0x02
/** @brief Server believes file is a binary file */
-#define SSH_FILEXFER_ATTR_GUESSED_BINARY 0x03
+# define SSH_FILEXFER_ATTR_GUESSED_BINARY 0x03
/** @} */
@@ -356,61 +360,61 @@
*/
/** @brief Mask of file open bits */
-#define SSH_FXF_ACCESS_DISPOSITION 0x00000007
+# define SSH_FXF_ACCESS_DISPOSITION 0x00000007
/** @brief Must create a new file */
-#define SSH_FXF_CREATE_NEW 0x00000000
+# define SSH_FXF_CREATE_NEW 0x00000000
/** @brief Create new file or truncate existing one */
-#define SSH_FXF_CREATE_TRUNCATE 0x00000001
+# define SSH_FXF_CREATE_TRUNCATE 0x00000001
/** @brief File must already exist */
-#define SSH_FXF_OPEN_EXISTING 0x00000002
+# define SSH_FXF_OPEN_EXISTING 0x00000002
/** @brief Open existing file or create new one */
-#define SSH_FXF_OPEN_OR_CREATE 0x00000003
+# define SSH_FXF_OPEN_OR_CREATE 0x00000003
/** @brief Truncate an existing file */
-#define SSH_FXF_TRUNCATE_EXISTING 0x00000004
+# define SSH_FXF_TRUNCATE_EXISTING 0x00000004
/** @brief Lossy append only */
-#define SSH_FXF_APPEND_DATA 0x00000008
+# define SSH_FXF_APPEND_DATA 0x00000008
/** @brief Append only */
-#define SSH_FXF_APPEND_DATA_ATOMIC 0x00000010
+# define SSH_FXF_APPEND_DATA_ATOMIC 0x00000010
/** @brief Convert newlines */
-#define SSH_FXF_TEXT_MODE 0x00000020
+# define SSH_FXF_TEXT_MODE 0x00000020
/** @brief Exclusive read access */
-#define SSH_FXF_BLOCK_READ 0x00000040
+# define SSH_FXF_BLOCK_READ 0x00000040
/** @brief Exclusive write access */
-#define SSH_FXF_BLOCK_WRITE 0x00000080
+# define SSH_FXF_BLOCK_WRITE 0x00000080
/** @brief Exclusive delete access */
-#define SSH_FXF_BLOCK_DELETE 0x00000100
+# define SSH_FXF_BLOCK_DELETE 0x00000100
/** @brief Other @c SSH_FXF_BLOCK_... bits are advisory */
-#define SSH_FXF_BLOCK_ADVISORY 0x00000200
+# define SSH_FXF_BLOCK_ADVISORY 0x00000200
/** @brief Do not follow symlinks */
-#define SSH_FXF_NOFOLLOW 0x00000400
+# define SSH_FXF_NOFOLLOW 0x00000400
/** @brief Delete when last handle closed */
-#define SSH_FXF_DELETE_ON_CLOSE 0x00000800
+# define SSH_FXF_DELETE_ON_CLOSE 0x00000800
/** @brief Enable audit/alarm privileges */
-#define SSH_FXF_ACCESS_AUDIT_ALARM_INFO 0x00001000
+# define SSH_FXF_ACCESS_AUDIT_ALARM_INFO 0x00001000
/** @brief Enable backup privileges */
-#define SSH_FXF_ACCESS_BACKUP 0x00002000
+# define SSH_FXF_ACCESS_BACKUP 0x00002000
/** @brief Read or write backup stream */
-#define SSH_FXF_BACKUP_STREAM 0x00004000
+# define SSH_FXF_BACKUP_STREAM 0x00004000
/** @brief Enable owner privileges */
-#define SSH_FXF_OVERRIDE_OWNER 0x00008000
+# define SSH_FXF_OVERRIDE_OWNER 0x00008000
/** @} */
@@ -419,13 +423,14 @@
*/
/** @brief Overwrite target if it exists */
-#define SSH_FXF_RENAME_OVERWRITE 0x00000001
+# define SSH_FXF_RENAME_OVERWRITE 0x00000001
-/** @brief Ensure target name always exists and refers to original or new file */
-#define SSH_FXF_RENAME_ATOMIC 0x00000002
+/** @brief Ensure target name always exists and refers to original or new file
+ */
+# define SSH_FXF_RENAME_ATOMIC 0x00000002
/** @brief Remove requirements on server */
-#define SSH_FXF_RENAME_NATIVE 0x00000004
+# define SSH_FXF_RENAME_NATIVE 0x00000004
/** @} */
@@ -434,13 +439,13 @@
*/
/** @brief Don't check for existence or accessibility, don't resolve links */
-#define SSH_FXP_REALPATH_NO_CHECK 0x00000001
+# define SSH_FXP_REALPATH_NO_CHECK 0x00000001
/** @brief Get file attribtues if it exists */
-#define SSH_FXP_REALPATH_STAT_IF 0x00000002
+# define SSH_FXP_REALPATH_STAT_IF 0x00000002
/** @brief Get file attributes, fail if unavailable */
-#define SSH_FXP_REALPATH_STAT_ALWAYS 0x00000003
+# define SSH_FXP_REALPATH_STAT_ALWAYS 0x00000003
/** @} */
@@ -449,25 +454,25 @@
*/
/** @brief Open file for reading */
-#define SSH_FXF_READ 0x00000001
+# define SSH_FXF_READ 0x00000001
/** @brief Open file for writing */
-#define SSH_FXF_WRITE 0x00000002
+# define SSH_FXF_WRITE 0x00000002
/** @brief Append to end of file */
-#define SSH_FXF_APPEND 0x00000004
+# define SSH_FXF_APPEND 0x00000004
/** @brief Create file if it does not exist */
-#define SSH_FXF_CREAT 0x00000008
+# define SSH_FXF_CREAT 0x00000008
/** @brief Truncate file if it already exists */
-#define SSH_FXF_TRUNC 0x00000010
+# define SSH_FXF_TRUNC 0x00000010
/** @brief File must not exist */
-#define SSH_FXF_EXCL 0x00000020
+# define SSH_FXF_EXCL 0x00000020
/** @brief Convert newlines */
-#define SSH_FXF_TEXT 0x00000040
+# define SSH_FXF_TEXT 0x00000040
/** @} */
@@ -476,100 +481,100 @@
*/
/** @brief Success */
-#define SSH_FX_OK 0
+# define SSH_FX_OK 0
/** @brief End of file */
-#define SSH_FX_EOF 1
+# define SSH_FX_EOF 1
/** @brief File does not exist */
-#define SSH_FX_NO_SUCH_FILE 2
+# define SSH_FX_NO_SUCH_FILE 2
/** @brief Insufficient permission */
-#define SSH_FX_PERMISSION_DENIED 3
+# define SSH_FX_PERMISSION_DENIED 3
/** @brief Unknown error */
-#define SSH_FX_FAILURE 4
+# define SSH_FX_FAILURE 4
/** @brief Badly formatted packet */
-#define SSH_FX_BAD_MESSAGE 5
+# define SSH_FX_BAD_MESSAGE 5
/** @brief No connection to server */
-#define SSH_FX_NO_CONNECTION 6
+# define SSH_FX_NO_CONNECTION 6
/** @brief Connection to server lost */
-#define SSH_FX_CONNECTION_LOST 7
+# define SSH_FX_CONNECTION_LOST 7
/** @brief Operation not supported by server */
-#define SSH_FX_OP_UNSUPPORTED 8
+# define SSH_FX_OP_UNSUPPORTED 8
/** @brief Invalid handle value */
-#define SSH_FX_INVALID_HANDLE 9 /* v4+ */
+# define SSH_FX_INVALID_HANDLE 9 /* v4+ */
/** @brief File path does not exist or is invalid */
-#define SSH_FX_NO_SUCH_PATH 10 /* 0x0A */
+# define SSH_FX_NO_SUCH_PATH 10 /* 0x0A */
/** @brief File already exists */
-#define SSH_FX_FILE_ALREADY_EXISTS 11 /* 0x0B */
+# define SSH_FX_FILE_ALREADY_EXISTS 11 /* 0x0B */
/** @brief File is on read-only or write-protected media */
-#define SSH_FX_WRITE_PROTECT 12 /* 0x0C */
+# define SSH_FX_WRITE_PROTECT 12 /* 0x0C */
/** @brief No medium in drive */
-#define SSH_FX_NO_MEDIA 13 /* 0x0D */
+# define SSH_FX_NO_MEDIA 13 /* 0x0D */
/** @brief Insufficient free space */
-#define SSH_FX_NO_SPACE_ON_FILESYSTEM 14 /* 0x0E v5+ */
+# define SSH_FX_NO_SPACE_ON_FILESYSTEM 14 /* 0x0E v5+ */
/** @brief User's storage quota would be exceeded */
-#define SSH_FX_QUOTA_EXCEEDED 15 /* 0x0F */
+# define SSH_FX_QUOTA_EXCEEDED 15 /* 0x0F */
/** @brief Unknown principal in ACL */
-#define SSH_FX_UNKNOWN_PRINCIPAL 16 /* 0x10 */
+# define SSH_FX_UNKNOWN_PRINCIPAL 16 /* 0x10 */
/** @brief File is locked by another process */
-#define SSH_FX_LOCK_CONFLICT 17 /* 0x11 */
+# define SSH_FX_LOCK_CONFLICT 17 /* 0x11 */
/** @brief Directory is not empty */
-#define SSH_FX_DIR_NOT_EMPTY 18 /* 0x12 v6+ */
+# define SSH_FX_DIR_NOT_EMPTY 18 /* 0x12 v6+ */
/** @brief File is not a director */
-#define SSH_FX_NOT_A_DIRECTORY 19 /* 0x13 */
+# define SSH_FX_NOT_A_DIRECTORY 19 /* 0x13 */
/** @brief Filename is invalid */
-#define SSH_FX_INVALID_FILENAME 20 /* 0x14 */
+# define SSH_FX_INVALID_FILENAME 20 /* 0x14 */
/** @brief Too many symbolic links or link found by @ref SSH_FXF_NOFOLLOW */
-#define SSH_FX_LINK_LOOP 21 /* 0x15 */
+# define SSH_FX_LINK_LOOP 21 /* 0x15 */
/** @brief File cannot be deleted */
-#define SSH_FX_CANNOT_DELETE 22 /* 0x16 */
+# define SSH_FX_CANNOT_DELETE 22 /* 0x16 */
/** @brief Parameter out of range or conflicting */
-#define SSH_FX_INVALID_PARAMETER 23 /* 0x17 */
+# define SSH_FX_INVALID_PARAMETER 23 /* 0x17 */
/** @brief File is a directory */
-#define SSH_FX_FILE_IS_A_DIRECTORY 24 /* 0x18 */
+# define SSH_FX_FILE_IS_A_DIRECTORY 24 /* 0x18 */
/** @brief Mandatory lock conflict when reading or writing */
-#define SSH_FX_BYTE_RANGE_LOCK_CONFLICT 25 /* 0x19 */
+# define SSH_FX_BYTE_RANGE_LOCK_CONFLICT 25 /* 0x19 */
/** @brief Lock request refused */
-#define SSH_FX_BYTE_RANGE_LOCK_REFUSED 26 /* 0x1A */
+# define SSH_FX_BYTE_RANGE_LOCK_REFUSED 26 /* 0x1A */
/** @brief Delete operation pending on faile */
-#define SSH_FX_DELETE_PENDING 27 /* 0x1B */
+# define SSH_FX_DELETE_PENDING 27 /* 0x1B */
/** @brief File is corrupt */
-#define SSH_FX_FILE_CORRUPT 28 /* 0x1C */
+# define SSH_FX_FILE_CORRUPT 28 /* 0x1C */
/** @brief Principal cannot become file owner */
-#define SSH_FX_OWNER_INVALID 29 /* 0x1D */
+# define SSH_FX_OWNER_INVALID 29 /* 0x1D */
/** @brief Principal cannot become file group */
-#define SSH_FX_GROUP_INVALID 30 /* 0x1E */
+# define SSH_FX_GROUP_INVALID 30 /* 0x1E */
/** @brief Specified lock range has not been granted */
-#define SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK 31 /* 0x1F */
+# define SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK 31 /* 0x1F */
/** @} */
@@ -619,10 +624,14 @@
* @section specs Specifications
*
* - http://www.ietf.org/rfc/rfc4251.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-02.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-04.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-13.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-02.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-04.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-13.txt
*
* @section links Links
*
diff --git a/sftpclient.c b/sftpclient.c
old mode 100755
new mode 100644
index 1092bd7..3d998e7
--- a/sftpclient.c
+++ b/sftpclient.c
@@ -56,8 +56,8 @@
#include <limits.h>
#include <termios.h>
#if HAVE_READLINE
-# include <readline/readline.h>
-# include <readline/history.h>
+# include <readline/readline.h>
+# include <readline/history.h>
#endif
struct command {
@@ -116,75 +116,76 @@ static int forceversion;
static char *sftp_realpath(const char *path);
static const struct option options[] = {
- { "help", no_argument, 0, 'h' },
- { "version", no_argument, 0, 'V' },
- { "dropbear", no_argument, 0, 'r' },
- { "buffer", required_argument, 0, 'B' },
- { "batch", required_argument, 0, 'b' },
- { "program", required_argument, 0, 'P' },
- { "requests", required_argument, 0, 'R' },
- { "subsystem", required_argument, 0, 's' },
- { "sftp-version", required_argument, 0, 'S' },
- { "quirk-reverse-symlink", no_argument, 0, 256 },
- { "stop-on-error", no_argument, 0, 257 },
- { "no-stop-on-error", no_argument, 0, 258 },
- { "progress", no_argument, 0, 259 },
- { "no-progress", no_argument, 0, 260 },
- { "echo", no_argument, 0, 261 },
- { "fix-sigpipe", no_argument, 0, 262 },
- { "force-version", required_argument, 0, 263 },
- { "debug", no_argument, 0, 'd' },
- { "debug-path", required_argument, 0, 'D' },
- { "program-debug-path", required_argument, 0, 264 },
- { "host", required_argument, 0, 'H' },
- { "port", required_argument, 0, 'p' },
- { "ipv4", no_argument, 0, '4' },
- { "ipv6", no_argument, 0, '6' },
- { "1", no_argument, 0, '1' },
- { "2", no_argument, 0, '2' },
- { "C", no_argument, 0, 'C' },
- { "F", required_argument, 0, 'F' },
- { "o", required_argument, 0, 'o' },
- { "v", no_argument, 0, 'v' },
- { 0, 0, 0, 0 }
-};
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"dropbear", no_argument, 0, 'r'},
+ {"buffer", required_argument, 0, 'B'},
+ {"batch", required_argument, 0, 'b'},
+ {"program", required_argument, 0, 'P'},
+ {"requests", required_argument, 0, 'R'},
+ {"subsystem", required_argument, 0, 's'},
+ {"sftp-version", required_argument, 0, 'S'},
+ {"quirk-reverse-symlink", no_argument, 0, 256},
+ {"stop-on-error", no_argument, 0, 257},
+ {"no-stop-on-error", no_argument, 0, 258},
+ {"progress", no_argument, 0, 259},
+ {"no-progress", no_argument, 0, 260},
+ {"echo", no_argument, 0, 261},
+ {"fix-sigpipe", no_argument, 0, 262},
+ {"force-version", required_argument, 0, 263},
+ {"debug", no_argument, 0, 'd'},
+ {"debug-path", required_argument, 0, 'D'},
+ {"program-debug-path", required_argument, 0, 264},
+ {"host", required_argument, 0, 'H'},
+ {"port", required_argument, 0, 'p'},
+ {"ipv4", no_argument, 0, '4'},
+ {"ipv6", no_argument, 0, '6'},
+ {"1", no_argument, 0, '1'},
+ {"2", no_argument, 0, '2'},
+ {"C", no_argument, 0, 'C'},
+ {"F", required_argument, 0, 'F'},
+ {"o", required_argument, 0, 'o'},
+ {"v", no_argument, 0, 'v'},
+ {0, 0, 0, 0}};
/* display usage message and terminate */
static void attribute((noreturn)) help(void) {
- xprintf("Usage:\n"
- " sftpclient [OPTIONS] [USER@]HOST\n"
- "\n"
- "Quick and dirty SFTP client\n"
- "\n");
- xprintf("Options:\n"
- " --help, -h Display usage message\n"
- " --version, -V Display version number\n"
- " -r, --dropbear Use dbclient instead of ssh\n"
- " -B, --buffer BYTES Select buffer size (default 8192)\n"
- " -b, --batch PATH Read batch file\n"
- " -P, --program PATH Execute program as SFTP server\n");
- xprintf(" -R, --requests COUNT Maximum outstanding requests (default 8)\n"
- " -s, --subsystem NAME Remote subsystem name\n"
- " -S, --sftp-version VER Protocol version to request (default 3)\n"
- " --quirk-openssh Server gets SSH_FXP_SYMLINK backwards\n");
- xprintf("Options passed to SSH:\n"
- " -1, -2 Select protocol version\n"
- " -C Enable compression\n"
- " -F PATH Use alternative config file\n"
- " -o OPTION Pass option to client\n"
- " -v Raise logging level\n");
+ sftp_xprintf("Usage:\n"
+ " sftpclient [OPTIONS] [USER@]HOST\n"
+ "\n"
+ "Quick and dirty SFTP client\n"
+ "\n");
+ sftp_xprintf(
+ "Options:\n"
+ " --help, -h Display usage message\n"
+ " --version, -V Display version number\n"
+ " -r, --dropbear Use dbclient instead of ssh\n"
+ " -B, --buffer BYTES Select buffer size (default 8192)\n"
+ " -b, --batch PATH Read batch file\n"
+ " -P, --program PATH Execute program as SFTP server\n"
+ " -R, --requests COUNT Maximum outstanding requests (default 8)\n"
+ " -s, --subsystem NAME Remote subsystem name\n"
+ " -S, --sftp-version VER Protocol version to request (default 3)\n"
+ " --echo Echo commands\n"
+ " --quirk-openssh Server gets SSH_FXP_SYMLINK backwards\n"
+ "Options passed to SSH:\n"
+ " -1, -2 Select protocol version\n"
+ " -C Enable compression\n"
+ " -F PATH Use alternative config file\n"
+ " -o OPTION Pass option to client\n"
+ " -v Raise logging level\n");
exit(0);
}
/* display version number and terminate */
static void attribute((noreturn)) version(void) {
- xprintf("sftp client version %s\n", VERSION);
+ sftp_xprintf("sftp client version %s\n", VERSION);
exit(0);
}
/* Utilities */
-static int attribute((format(printf,1,2))) error(const char *fmt, ...) {
+static int attribute((format(printf, 1, 2))) error(const char *fmt, ...) {
va_list ap;
if(inputpath)
@@ -192,7 +193,7 @@ static int attribute((format(printf,1,2))) error(const char *fmt, ...) {
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
- fputc('\n', stderr);
+ fputc('\n', stderr);
fflush(stderr);
return -1;
}
@@ -200,7 +201,7 @@ static int attribute((format(printf,1,2))) error(const char *fmt, ...) {
static int status(void) {
uint32_t status;
char *msg;
-
+
/* Cope with half-parsed responses */
fakejob.ptr = fakejob.data + 5;
fakejob.left = fakejob.len - 5;
@@ -219,13 +220,15 @@ static uint8_t getresponse(int expected, uint32_t expected_id,
uint32_t len;
uint8_t type;
- if(do_read(sftpin, &len, sizeof len))
- fatal("unexpected EOF from server while reading %s response length", what);
- free(fakejob.data); /* free last job */
+ if(sftp_xread(sftpin, &len, sizeof len))
+ sftp_fatal("unexpected EOF from server while reading %s response length",
+ what);
+ free(fakejob.data); /* free last job */
fakejob.len = ntohl(len);
- fakejob.data = xmalloc(fakejob.len);
- if(do_read(sftpin, fakejob.data, fakejob.len))
- fatal("unexpected EOF from server while reading %s response data", what);
+ fakejob.data = sftp_xmalloc(fakejob.len);
+ if(sftp_xread(sftpin, fakejob.data, fakejob.len))
+ sftp_fatal("unexpected EOF from server while reading %s response data",
+ what);
if(sftp_debugging) {
D(("%s response:", what));
sftp_debug_hexdump(fakejob.data, fakejob.len);
@@ -236,15 +239,15 @@ static uint8_t getresponse(int expected, uint32_t expected_id,
if(type != SSH_FXP_VERSION) {
cpcheck(sftp_parse_uint32(&fakejob, &fakejob.id));
if(expected_id && fakejob.id != expected_id)
- fatal("wrong ID in response to %s (want %"PRIu32
- " got %"PRIu32" type was %d)",
- what, expected_id, fakejob.id, type);
+ sftp_fatal("wrong ID in response to %s (want %" PRIu32 " got %" PRIu32
+ " type was %d)",
+ what, expected_id, fakejob.id, type);
}
if(expected > 0 && type != expected) {
if(type == SSH_FXP_STATUS)
status();
else
- fatal("expected %s response %d got %d", what, expected, type);
+ sftp_fatal("expected %s response %d got %d", what, expected, type);
}
return type;
}
@@ -262,22 +265,22 @@ static int split(char *line, char **av) {
if(*line == '"') {
arg = av[ac++] = line++;
while(*line && *line != '"') {
- if(*line == '\\' && line[1])
- ++line;
- *arg++ = *line++;
+ if(*line == '\\' && line[1])
+ ++line;
+ *arg++ = *line++;
}
if(!*line) {
- error("unterminated string");
- return -1;
+ error("unterminated string");
+ return -1;
}
*arg++ = 0;
line++;
} else {
av[ac++] = line;
while(*line && !isspace((unsigned char)*line))
- ++line;
+ ++line;
if(*line)
- *line++ = 0;
+ *line++ = 0;
}
}
av[ac] = 0;
@@ -298,7 +301,7 @@ static char *remote_cwd(void) {
if(!cwd) {
if(!(cwd = sftp_realpath(".")))
exit(1);
- cwd = xstrdup(cwd);
+ cwd = sftp_xstrdup(cwd);
}
return cwd;
}
@@ -306,14 +309,14 @@ static char *remote_cwd(void) {
static void progress(const char *path, uint64_t sofar, uint64_t total) {
if(progress_indicators) {
if(!total)
- xprintf("\r%*s\r", terminal_width, "");
+ sftp_xprintf("\r%*s\r", terminal_width, "");
else if(total == (uint64_t)-1)
- xprintf("\r%.60s: %12"PRIu64"b", path, sofar);
+ sftp_xprintf("\r%.60s: %12" PRIu64 "b", path, sofar);
else
- xprintf("\r%.60s: %12"PRIu64"b %3d%%",
- path, sofar, (int)(100 * sofar / total));
- if(fflush(stdout) < 0)
- fatal("error writing to stdout: %s", strerror(errno));
+ sftp_xprintf("\r%.60s: %12" PRIu64 "b %3d%%", path, sofar,
+ (int)(100 * sofar / total));
+ if(fflush(stdout) < 0)
+ sftp_fatal("error writing to stdout: %s", strerror(errno));
}
}
@@ -322,13 +325,13 @@ static void progress(const char *path, uint64_t sofar, uint64_t total) {
static int sftp_init(void) {
uint32_t version, u32;
uint16_t u16;
-
+
/* Send SSH_FXP_INIT */
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_INIT);
sftp_send_uint32(&fakeworker, sftpversion);
sftp_send_end(&fakeworker);
-
+
/* Parse the version reponse */
if(getresponse(SSH_FXP_VERSION, 0, "SSH_FXP_INIT") != SSH_FXP_VERSION)
return -1;
@@ -347,7 +350,7 @@ static int sftp_init(void) {
protocol = &sftp_v6;
break;
default:
- return error("server wanted protocol version %"PRIu32, version);
+ return error("server wanted protocol version %" PRIu32, version);
}
attrmask = protocol->attrmask;
/* Extension data */
@@ -361,14 +364,14 @@ static int sftp_init(void) {
/* TODO table-driven extension parsing */
if(!strcmp(xname, "newline")) {
free(newline);
- newline = xstrdup(xdata);
+ newline = sftp_xstrdup(xdata);
if(!*newline)
return error("cannot cope with empty newline sequence");
/* TODO check newline sequence doesn't contain repeats */
} else if(!strcmp(xname, "vendor-id")) {
struct sftpjob xjob;
- char *vn ,*sn, *sv;
-
+ char *vn, *sn, *sv;
+
xjob.a = &allocator;
xjob.ptr = (void *)xdata;
xjob.left = xdatalen;
@@ -377,17 +380,17 @@ static int sftp_init(void) {
cpcheck(sftp_parse_string(&xjob, &sv, 0));
cpcheck(sftp_parse_uint64(&xjob, &serverbuild));
free(vendorname);
- vendorname = xstrdup(vn);
+ vendorname = sftp_xstrdup(vn);
free(servername);
- servername = xstrdup(sn);
+ servername = sftp_xstrdup(sn);
free(serverversion);
- serverversion = xstrdup(sv);
+ serverversion = sftp_xstrdup(sv);
} else if(!strcmp(xname, "versions")) {
free(serverversions);
- serverversions = xstrdup(xdata);
+ serverversions = sftp_xstrdup(xdata);
} else if(!strcmp(xname, "symlink-order@rjk.greenend.org.uk")) {
/* See commentary in v3.c */
- if(!strcmp(xdata, "targetpath-linkpath"))
+ if(!strcmp(xdata, "targetpath-linkpath"))
quirk_reverse_symlink = 1;
else if(!strcmp(xdata, "linkpath-targetpath"))
quirk_reverse_symlink = 0;
@@ -395,7 +398,7 @@ static int sftp_init(void) {
error("unknown %s value '%s'", xname, xdata);
} else if(!strcmp(xname, "supported")) {
struct sftpjob xjob;
-
+
xjob.a = &allocator;
xjob.ptr = (void *)xdata;
xjob.left = xdatalen;
@@ -408,11 +411,12 @@ static int sftp_init(void) {
cpcheck(sftp_parse_string(&xjob, 0, 0)); /* extension-names */
} else if(!strcmp(xname, "supported2")) {
struct sftpjob xjob;
-
+
xjob.a = &allocator;
xjob.ptr = (void *)xdata;
xjob.left = xdatalen;
- cpcheck(sftp_parse_uint32(&xjob, &attrmask)); /* supported-attribute-mask */
+ cpcheck(
+ sftp_parse_uint32(&xjob, &attrmask)); /* supported-attribute-mask */
assert(!(attrmask & SSH_FILEXFER_ATTR_CTIME));
cpcheck(sftp_parse_uint32(&xjob, &u32)); /* supported-attribute-bits */
cpcheck(sftp_parse_uint32(&xjob, &u32)); /* supported-open-flags */
@@ -430,17 +434,14 @@ static int sftp_init(void) {
cpcheck(sftp_parse_string(&xjob, 0, 0)); /* extension-names */
--u32;
}
- } else if(!strcmp(xname, "posix-rename@openssh.com")
- && !strcmp(xdata, "1")) {
+ } else if(!strcmp(xname, "posix-rename@openssh.com") &&
+ !strcmp(xdata, "1")) {
rename_extension = "posix-rename@openssh.com";
- } else if(!strcmp(xname, "posix-rename@openssh.org")
- && !rename_extension) {
+ } else if(!strcmp(xname, "posix-rename@openssh.org") && !rename_extension) {
rename_extension = "posix-rename@openssh.com";
- } else if(!strcmp(xname, "hardlink@openssh.com")
- && !strcmp(xdata, "1")) {
+ } else if(!strcmp(xname, "hardlink@openssh.com") && !strcmp(xdata, "1")) {
hardlink_extension = "hardlink@openssh.com";
- } else if(!strcmp(xname, "statvfs@openssh.com")
- && !strcmp(xdata, "2")) {
+ } else if(!strcmp(xname, "statvfs@openssh.com") && !strcmp(xdata, "2")) {
statvfs_extension = "statvfs@openssh.com";
}
}
@@ -463,15 +464,13 @@ static char *sftp_realpath(const char *path) {
return 0;
cpcheck(sftp_parse_uint32(&fakejob, &u32));
if(u32 != 1)
- fatal("wrong count in SSH_FXP_REALPATH reply");
+ sftp_fatal("wrong count in SSH_FXP_REALPATH reply");
cpcheck(sftp_parse_path(&fakejob, &resolved));
return resolved;
}
-static char *sftp_realpath_v6(const char *path,
- int control_byte,
- char **compose,
- struct sftpattr *attrs) {
+static char *sftp_realpath_v6(const char *path, int control_byte,
+ char **compose, struct sftpattr *attrs) {
char *resolved;
uint32_t u32, id;
@@ -490,14 +489,13 @@ static char *sftp_realpath_v6(const char *path,
return 0;
cpcheck(sftp_parse_uint32(&fakejob, &u32));
if(u32 != 1)
- fatal("wrong count in SSH_FXP_REALPATH reply");
+ sftp_fatal("wrong count in SSH_FXP_REALPATH reply");
cpcheck(sftp_parse_path(&fakejob, &resolved));
cpcheck(protocol->parseattrs(&fakejob, attrs));
return resolved;
}
-static int sftp_stat(const char *path, struct sftpattr *attrs,
- uint8_t type) {
+static int sftp_stat(const char *path, struct sftpattr *attrs, uint8_t type) {
uint32_t id;
remote_cwd();
@@ -547,8 +545,7 @@ static int sftp_opendir(const char *path, struct client_handle *hp) {
}
static int sftp_readdir(const struct client_handle *hp,
- struct sftpattr **attrsp,
- size_t *nattrsp) {
+ struct sftpattr **attrsp, size_t *nattrsp) {
uint32_t id, n;
struct sftpattr *attrs;
char *name, *longname = 0;
@@ -562,7 +559,7 @@ static int sftp_readdir(const struct client_handle *hp,
case SSH_FXP_NAME:
cpcheck(sftp_parse_uint32(&fakejob, &n));
if(n > SIZE_MAX / sizeof(struct sftpattr))
- fatal("too many attributes in SSH_FXP_READDIR response");
+ sftp_fatal("too many attributes in SSH_FXP_READDIR response");
attrs = sftp_alloc(fakejob.a, n * sizeof(struct sftpattr));
if(nattrsp)
*nattrsp = n;
@@ -591,7 +588,7 @@ static int sftp_readdir(const struct client_handle *hp,
status();
return -1;
default:
- fatal("bogus response to SSH_FXP_READDIR");
+ sftp_fatal("bogus response to SSH_FXP_READDIR");
}
}
@@ -607,8 +604,7 @@ static int sftp_close(const struct client_handle *hp) {
return status();
}
-static int sftp_setstat(const char *path,
- const struct sftpattr *attrs) {
+static int sftp_setstat(const char *path, const struct sftpattr *attrs) {
uint32_t id;
remote_cwd();
@@ -662,15 +658,15 @@ static int sftp_remove(const char *path) {
return status();
}
-static int sftp_rename(const char *oldpath, const char *newpath,
+static int sftp_rename(const char *oldpath, const char *newpath,
unsigned flags) {
uint32_t id;
-
+
remote_cwd();
/* In v3/4 atomic is assumed, overwrite and native are not available */
- if(protocol->version <= 4 && (flags & ~SSH_FXF_RENAME_ATOMIC) != 0)
- return error("cannot emulate rename flags %#x in protocol %d",
- flags, protocol->version);
+ if(protocol->version <= 4 && (flags & (uint32_t)~SSH_FXF_RENAME_ATOMIC) != 0)
+ return error("cannot emulate rename flags %#x in protocol %d", flags,
+ protocol->version);
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_RENAME);
sftp_send_uint32(&fakeworker, id = newid());
@@ -685,7 +681,7 @@ static int sftp_rename(const char *oldpath, const char *newpath,
static int sftp_prename(const char *oldpath, const char *newpath) {
uint32_t id;
-
+
remote_cwd();
if(!rename_extension)
return error("no posix-rename extension found");
@@ -720,18 +716,17 @@ static int sftp_hardlink(const char *targetpath, const char *linkpath) {
static int sftp_link(const char *targetpath, const char *linkpath,
int sftp_send_symlink) {
uint32_t id;
-
+
if(protocol->version < 6 && !sftp_send_symlink) {
if(hardlink_extension)
return sftp_hardlink(targetpath, linkpath);
- return error("hard links not supported in protocol %"PRIu32,
+ return error("hard links not supported in protocol %" PRIu32,
protocol->version);
}
remote_cwd();
sftp_send_begin(&fakeworker);
- sftp_send_uint8(&fakeworker, (protocol->version >= 6
- ? SSH_FXP_LINK
- : SSH_FXP_SYMLINK));
+ sftp_send_uint8(&fakeworker,
+ (protocol->version >= 6 ? SSH_FXP_LINK : SSH_FXP_SYMLINK));
sftp_send_uint32(&fakeworker, id = newid());
if(quirk_reverse_symlink) {
/* OpenSSH server gets SSH_FXP_SYMLINK args back to front
@@ -749,10 +744,8 @@ static int sftp_link(const char *targetpath, const char *linkpath,
return status();
}
-static int sftp_open(const char *path,
- uint32_t desired_access, uint32_t flags,
- const struct sftpattr *attrs,
- struct client_handle *hp) {
+static int sftp_open(const char *path, uint32_t desired_access, uint32_t flags,
+ const struct sftpattr *attrs, struct client_handle *hp) {
uint32_t id, pflags = 0;
remote_cwd();
@@ -764,10 +757,10 @@ static int sftp_open(const char *path,
pflags |= SSH_FXF_WRITE;
switch(flags & SSH_FXF_ACCESS_DISPOSITION) {
case SSH_FXF_CREATE_NEW:
- pflags |= SSH_FXF_CREAT|SSH_FXF_EXCL;
+ pflags |= SSH_FXF_CREAT | SSH_FXF_EXCL;
break;
case SSH_FXF_CREATE_TRUNCATE:
- pflags |= SSH_FXF_CREAT|SSH_FXF_TRUNC;
+ pflags |= SSH_FXF_CREAT | SSH_FXF_TRUNC;
break;
case SSH_FXF_OPEN_OR_CREATE:
pflags |= SSH_FXF_CREAT;
@@ -778,10 +771,9 @@ static int sftp_open(const char *path,
pflags |= SSH_FXF_TRUNC;
break;
default:
- return error("unknown SSH_FXF_ACCESS_DISPOSITION %#"PRIx32,
- flags);
+ return error("unknown SSH_FXF_ACCESS_DISPOSITION %#" PRIx32, flags);
}
- if(flags & (SSH_FXF_APPEND_DATA|SSH_FXF_APPEND_DATA_ATOMIC))
+ if(flags & (SSH_FXF_APPEND_DATA | SSH_FXF_APPEND_DATA_ATOMIC))
pflags |= SSH_FXF_APPEND;
if(flags & SSH_FXF_TEXT_MODE) {
if(protocol->version < 4)
@@ -790,11 +782,10 @@ static int sftp_open(const char *path,
else
pflags |= SSH_FXF_TEXT;
}
- if(flags & ~(SSH_FXF_ACCESS_DISPOSITION
- |SSH_FXF_APPEND_DATA
- |SSH_FXF_APPEND_DATA_ATOMIC
- |SSH_FXF_TEXT_MODE))
- return error("future SSH_FXP_OPEN flags (%#"PRIx32") cannot be emulated in protocol %d",
+ if(flags & (uint32_t) ~(SSH_FXF_ACCESS_DISPOSITION | SSH_FXF_APPEND_DATA |
+ SSH_FXF_APPEND_DATA_ATOMIC | SSH_FXF_TEXT_MODE))
+ return error("future SSH_FXP_OPEN flags (%#" PRIx32
+ ") cannot be emulated in protocol %d",
flags, protocol->version);
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_OPEN);
@@ -827,8 +818,7 @@ struct space_available {
uint32_t bytes_per_allocation_unit;
};
-static int sftp_space_available(const char *path,
- struct space_available *as) {
+static int sftp_space_available(const char *path, struct space_available *as) {
uint32_t id;
remote_cwd();
@@ -838,8 +828,8 @@ static int sftp_space_available(const char *path,
sftp_send_string(&fakeworker, "space-available");
sftp_send_path(&fakejob, &fakeworker, path);
sftp_send_end(&fakeworker);
- if(getresponse(SSH_FXP_EXTENDED_REPLY,
- id, "space-available") != SSH_FXP_EXTENDED_REPLY)
+ if(getresponse(SSH_FXP_EXTENDED_REPLY, id, "space-available") !=
+ SSH_FXP_EXTENDED_REPLY)
return -1;
cpcheck(sftp_parse_uint64(&fakejob, &as->bytes_on_device));
cpcheck(sftp_parse_uint64(&fakejob, &as->unused_bytes_on_device));
@@ -885,7 +875,7 @@ static char *sftp_readlink(const char *path) {
return 0;
cpcheck(sftp_parse_uint32(&fakejob, &u32));
if(u32 != 1)
- fatal("wrong count in SSH_FXP_READLINK reply");
+ sftp_fatal("wrong count in SSH_FXP_READLINK reply");
cpcheck(sftp_parse_path(&fakejob, &resolved));
return resolved;
}
@@ -918,8 +908,7 @@ struct statvfs_reply {
uint64_t namemax;
};
-static int sftp_statvfs(const char *path,
- struct statvfs_reply *sr) {
+static int sftp_statvfs(const char *path, struct statvfs_reply *sr) {
uint32_t id;
remote_cwd();
@@ -932,6 +921,8 @@ static int sftp_statvfs(const char *path,
sftp_send_path(&fakejob, &fakeworker, path);
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_EXTENDED_REPLY, id, statvfs_extension);
+ sftp_memset(sr, 0,
+ sizeof *sr); // workaround overenthusiastic warning with LTO
cpcheck(sftp_parse_uint64(&fakejob, &sr->bsize));
cpcheck(sftp_parse_uint64(&fakejob, &sr->frsize));
cpcheck(sftp_parse_uint64(&fakejob, &sr->blocks));
@@ -948,14 +939,12 @@ static int sftp_statvfs(const char *path,
/* Command line operations */
-static int cmd_pwd(int attribute((unused)) ac,
- char attribute((unused)) **av) {
- xprintf("%s\n", remote_cwd());
+static int cmd_pwd(int attribute((unused)) ac, char attribute((unused)) * *av) {
+ sftp_xprintf("%s\n", remote_cwd());
return 0;
}
-static int cmd_cd(int attribute((unused)) ac,
- char **av) {
+static int cmd_cd(int attribute((unused)) ac, char **av) {
const char *newcwd;
struct sftpattr attrs;
@@ -984,32 +973,30 @@ static int cmd_cd(int attribute((unused)) ac,
return -1;
}
free(cwd);
- cwd = xstrdup(newcwd);
+ cwd = sftp_xstrdup(newcwd);
return 0;
}
static int cmd_quit(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
exit(0);
}
-static int cmd_help(int attribute((unused)) ac,
- char attribute((unused)) **av);
+static int cmd_help(int attribute((unused)) ac, char attribute((unused)) * *av);
static int cmd_lpwd(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
char *lpwd;
if(!(lpwd = sftp_getcwd(fakejob.a))) {
error("error calling getcwd: %s", strerror(errno));
return -1;
}
- xprintf("%s\n", lpwd);
+ sftp_xprintf("%s\n", lpwd);
return 0;
}
-static int cmd_lcd(int attribute((unused)) ac,
- char **av) {
+static int cmd_lcd(int attribute((unused)) ac, char **av) {
if(chdir(av[0]) < 0) {
error("error calling chdir: %s", strerror(errno));
return -1;
@@ -1056,24 +1043,23 @@ static int sort_by_mtime(const void *av, const void *bv) {
/* Reverse an array in place */
static void reverse(void *array, size_t count, size_t size) {
if(array) {
- void *tmp = xmalloc(size);
+ void *tmp = sftp_xmalloc(size);
char *const base = array;
size_t n;
- /* If size is even then size/2 is the first half of the array and that's fine.
- * If size is odd then size/2 goes up to but excludes the middle member
- * which is also fine. */
+ /* If size is even then size/2 is the first half of the array and that's
+ * fine. If size is odd then size/2 goes up to but excludes the middle
+ * member which is also fine. */
for(n = 0; n < size / 2; ++n) {
- memcpy(tmp, base + n * size, size);
- memcpy(base + n * size, base + (count - n - 1) * size, size);
- memcpy(base + (count - n - 1) * size, tmp, size);
+ sftp_memcpy(tmp, base + n * size, size);
+ sftp_memcpy(base + n * size, base + (count - n - 1) * size, size);
+ sftp_memcpy(base + (count - n - 1) * size, tmp, size);
}
free(tmp);
}
}
-static int cmd_ls(int ac,
- char **av) {
+static int cmd_ls(int ac, char **av) {
const char *options, *path;
struct sftpattr *attrs, *allattrs = 0, fileattrs;
size_t nattrs, nallattrs = 0, n, m, i, maxnamewidth = 0;
@@ -1091,8 +1077,7 @@ static int cmd_ls(int ac,
/* See what type the file is */
if(sftp_stat(path, &fileattrs, SSH_FXP_LSTAT))
return -1;
- if(fileattrs.type != SSH_FILEXFER_TYPE_DIRECTORY
- || strchr(options, 'd')) {
+ if(fileattrs.type != SSH_FILEXFER_TYPE_DIRECTORY || strchr(options, 'd')) {
/* The file is not a directory, or we used -d */
allattrs = &fileattrs;
nallattrs = 1;
@@ -1111,8 +1096,8 @@ static int cmd_ls(int ac,
return -1;
}
if(!nattrs)
- break; /* eof */
- allattrs = xrecalloc(allattrs, nattrs + nallattrs, sizeof *attrs);
+ break; /* eof */
+ allattrs = sftp_xrecalloc(allattrs, nattrs + nallattrs, sizeof *attrs);
for(n = 0; n < nattrs; ++n) {
if(include_dotfiles || attrs[n].name[0] != '.') {
wchar_t *wname = sftp_mbs2wcs(attrs[n].name);
@@ -1144,42 +1129,41 @@ static int cmd_ls(int ac,
/* long listing */
time_t now;
struct tm nowtime;
- const unsigned long flags = (strchr(options, 'n')
- ? FORMAT_PREFER_NUMERIC_UID
- : 0)|FORMAT_PREFER_LOCALTIME|FORMAT_ATTRS;
-
+ const unsigned long flags =
+ (strchr(options, 'n') ? FORMAT_PREFER_NUMERIC_UID : 0) |
+ FORMAT_PREFER_LOCALTIME | FORMAT_ATTRS;
+
/* We'd like to know what year we're in for dates in longname */
time(&now);
gmtime_r(&now, &nowtime);
for(n = 0; n < nallattrs; ++n) {
struct sftpattr *const attrs = &allattrs[n];
- if(attrs->type == SSH_FILEXFER_TYPE_SYMLINK
- && !attrs->target) {
+ if(attrs->type == SSH_FILEXFER_TYPE_SYMLINK && !attrs->target) {
if(singlefile)
attrs->target = sftp_readlink(attrs->name);
else {
- char *const fullname = sftp_alloc(fakejob.a,
- strlen(path) + strlen(attrs->name)
- + 2);
+ char *const fullname =
+ sftp_alloc(fakejob.a, strlen(path) + strlen(attrs->name) + 2);
strcpy(fullname, path);
strcat(fullname, "/");
strcat(fullname, attrs->name);
- D(("%s -> %s", attrs->name, fullname));
+ D(("%s -> %s", attrs->name, fullname));
attrs->target = sftp_readlink(fullname);
}
}
- xprintf("%s\n", sftp_format_attr(fakejob.a, attrs, nowtime.tm_year, flags));
+ sftp_xprintf("%s\n",
+ sftp_format_attr(fakejob.a, attrs, nowtime.tm_year, flags));
}
} else if(strchr(options, '1')) {
/* single-column listing */
for(n = 0; n < nallattrs; ++n)
- xprintf("%s\n", allattrs[n].name);
+ sftp_xprintf("%s\n", allattrs[n].name);
} else {
/* multi-column listing. First figure out the terminal width. */
/* We have C columns of width M, with C-1 single-character blank columns
* between them. So the total width is C * M + (C - 1). The lot had
* better fit into W columns in total.
- *
+ *
* We want to find the maximum C such that:
* C * M + C - 1 <= W
* <=> C * (M + 1) <= W + 1
@@ -1216,12 +1200,13 @@ static int cmd_ls(int ac,
wchar_t *wname = sftp_mbs2wcs(allattrs[i].name);
const size_t w = wcswidth(wname, SIZE_MAX);
free(wname);
- xprintf("%s%*s",
- allattrs[i].name,
- (m + 1 < cols && i + rows < nallattrs
- ? (int)(maxnamewidth - w + 1) : 0), "");
+ sftp_xprintf("%s%*s", allattrs[i].name,
+ (m + 1 < cols && i + rows < nallattrs
+ ? (int)(maxnamewidth - w + 1)
+ : 0),
+ "");
}
- xprintf("\n");
+ sftp_xprintf("\n");
}
}
if(allattrs != &fileattrs)
@@ -1229,9 +1214,8 @@ static int cmd_ls(int ac,
return 0;
}
-static int cmd_lls(int ac,
- char **av) {
- const char **args = sftp_alloc(fakejob.a, (ac + 2) * sizeof (char *));
+static int cmd_lls(int ac, char **av) {
+ const char **args = sftp_alloc(fakejob.a, (ac + 2) * sizeof(char *));
int n = 0;
pid_t pid;
@@ -1239,12 +1223,12 @@ static int cmd_lls(int ac,
while(ac--)
args[n++] = *av++;
args[n] = 0;
- if(!(pid = xfork())) {
+ if(!(pid = sftp_xfork())) {
execvp(args[0], (void *)args);
- fatal("executing ls: %s", strerror(errno));
+ sftp_fatal("executing ls: %s", strerror(errno));
}
if(waitpid(pid, &n, 0) < 0) {
- fatal("error calling waitpid: %s", strerror(errno));
+ sftp_fatal("error calling waitpid: %s", strerror(errno));
if(n) {
error("ls returned status %#x", n);
return -1;
@@ -1253,8 +1237,7 @@ static int cmd_lls(int ac,
return 0;
}
-static int cmd_lumask(int ac,
- char **av) {
+static int cmd_lumask(int ac, char **av) {
mode_t n;
if(ac) {
@@ -1272,13 +1255,12 @@ static int cmd_lumask(int ac,
} else {
n = umask(0);
umask(n);
- xprintf("%03o\n", (unsigned)n);
+ sftp_xprintf("%03o\n", (unsigned)n);
}
return 0;
}
-static int cmd_lmkdir(int attribute((unused)) ac,
- char **av) {
+static int cmd_lmkdir(int attribute((unused)) ac, char **av) {
if(mkdir(av[0], 0777) < 0) {
error("creating directory %s: %s", av[0], strerror(errno));
return -1;
@@ -1286,10 +1268,9 @@ static int cmd_lmkdir(int attribute((unused)) ac,
return 0;
}
-static int cmd_chown(int attribute((unused)) ac,
- char **av) {
+static int cmd_chown(int attribute((unused)) ac, char **av) {
struct sftpattr attrs;
-
+
if(sftp_stat(av[1], &attrs, SSH_FXP_STAT))
return -1;
if(protocol->version >= 4) {
@@ -1304,10 +1285,9 @@ static int cmd_chown(int attribute((unused)) ac,
return sftp_setstat(av[1], &attrs);
}
-static int cmd_chgrp(int attribute((unused)) ac,
- char **av) {
+static int cmd_chgrp(int attribute((unused)) ac, char **av) {
struct sftpattr attrs;
-
+
if(sftp_stat(av[1], &attrs, SSH_FXP_STAT))
return -1;
if(protocol->version >= 4) {
@@ -1322,10 +1302,9 @@ static int cmd_chgrp(int attribute((unused)) ac,
return sftp_setstat(av[1], &attrs);
}
-static int cmd_chmod(int attribute((unused)) ac,
- char **av) {
+static int cmd_chmod(int attribute((unused)) ac, char **av) {
struct sftpattr attrs;
-
+
attrs.valid = SSH_FILEXFER_ATTR_PERMISSIONS;
attrs.type = SSH_FILEXFER_TYPE_UNKNOWN;
errno = 0;
@@ -1335,18 +1314,15 @@ static int cmd_chmod(int attribute((unused)) ac,
return sftp_setstat(av[1], &attrs);
}
-static int cmd_rm(int attribute((unused)) ac,
- char **av) {
+static int cmd_rm(int attribute((unused)) ac, char **av) {
return sftp_remove(av[0]);
}
-static int cmd_rmdir(int attribute((unused)) ac,
- char **av) {
+static int cmd_rmdir(int attribute((unused)) ac, char **av) {
return sftp_rmdir(av[0]);
}
-static int cmd_mv(int attribute((unused)) ac,
- char **av) {
+static int cmd_mv(int attribute((unused)) ac, char **av) {
if(ac == 3) {
const char *ptr = av[0];
int c;
@@ -1357,11 +1333,20 @@ static int cmd_mv(int attribute((unused)) ac,
return error("invalid options '%s'", av[0]);
while((c = *ptr++)) {
switch(c) {
- case 'n': flags |= SSH_FXF_RENAME_NATIVE; break;
- case 'a': flags |= SSH_FXF_RENAME_ATOMIC; break;
- case 'o': flags |= SSH_FXF_RENAME_OVERWRITE; break;
- case 'p': posixrename = 1; break;
- default: return error("invalid options '%s'", av[0]);
+ case 'n':
+ flags |= SSH_FXF_RENAME_NATIVE;
+ break;
+ case 'a':
+ flags |= SSH_FXF_RENAME_ATOMIC;
+ break;
+ case 'o':
+ flags |= SSH_FXF_RENAME_OVERWRITE;
+ break;
+ case 'p':
+ posixrename = 1;
+ break;
+ default:
+ return error("invalid options '%s'", av[0]);
}
}
if(posixrename)
@@ -1372,44 +1357,42 @@ static int cmd_mv(int attribute((unused)) ac,
return sftp_rename(av[0], av[1], 0);
}
-static int cmd_symlink(int attribute((unused)) ac,
- char **av) {
+static int cmd_symlink(int attribute((unused)) ac, char **av) {
return sftp_link(av[0], av[1], 1);
}
-static int cmd_link(int attribute((unused)) ac,
- char **av) {
+static int cmd_link(int attribute((unused)) ac, char **av) {
return sftp_link(av[0], av[1], 0);
}
/* cmd_get uses a background thread to send requests */
struct outstanding_read {
- uint32_t id; /* 0 or a request ID */
- off_t offset; /* offset in source file */
+ uint32_t id; /* 0 or a request ID */
+ off_t offset; /* offset in source file */
};
struct reader_data {
- pthread_mutex_t m; /* protects everything here */
- pthread_cond_t c1; /* signaled when a response received */
- pthread_cond_t c2; /* signaled when a request sent */
- struct client_handle h; /* target handle */
- struct outstanding_read *reqs; /* in-flight requests */
- uint64_t next_offset; /* next offset */
+ pthread_mutex_t m; /* protects everything here */
+ pthread_cond_t c1; /* signaled when a response received */
+ pthread_cond_t c2; /* signaled when a request sent */
+ struct client_handle h; /* target handle */
+ struct outstanding_read *reqs; /* in-flight requests */
+ uint64_t next_offset; /* next offset */
int outstanding, eof, failed;
- uint64_t size; /* file size */
- uint64_t written; /* byte written so far */
- int fd; /* file to write to */
- char *local, *tmp; /* output filename */
+ uint64_t size; /* file size */
+ uint64_t written; /* byte written so far */
+ int fd; /* file to write to */
+ char *local, *tmp; /* output filename */
/* For text translation: */
- FILE *translated_fp; /* file to write to (in stdio-speak) */
- size_t translated_state; /* how far thru newline we've seen */
+ FILE *translated_fp; /* file to write to (in stdio-speak) */
+ size_t translated_state; /* how far thru newline we've seen */
};
static void *reader_thread(void *arg) {
struct reader_data *const r = arg;
int n;
uint32_t id, len;
-
+
ferrcheck(pthread_mutex_lock(&r->m));
while(!r->eof && !r->failed) {
/* Wait for a job to be reaped */
@@ -1460,8 +1443,8 @@ static int write_translated_init(struct reader_data *r) {
return 0;
}
-static int write_translated(struct reader_data *r,
- const void *vptr, size_t bytes) {
+static int write_translated(struct reader_data *r, const void *vptr,
+ size_t bytes) {
const char *ptr = vptr;
while(bytes > 0) {
const int c = (unsigned char)*ptr++;
@@ -1481,8 +1464,8 @@ static int write_translated(struct reader_data *r,
} else {
if(r->translated_state) {
/* We're part way thru something that turned out not to be a newline. */
- if(fwrite(newline, 1, r->translated_state, r->translated_fp)
- != r->translated_state)
+ if(fwrite(newline, 1, r->translated_state, r->translated_fp) !=
+ r->translated_state)
return -1;
r->translated_state = 0;
/* Try again from the current point. */
@@ -1507,7 +1490,8 @@ static int write_translated_done(struct reader_data *r) {
if(r->translated_state) {
/* The file ends part way thru something that starts out like a newline
* sequence but turns out not to be one. */
- if(fwrite(newline, 1, r->translated_state, r->translated_fp) != r->translated_state)
+ if(fwrite(newline, 1, r->translated_state, r->translated_fp) !=
+ r->translated_state)
rc = -1;
r->translated_state = 0;
}
@@ -1556,7 +1540,7 @@ static void reap_write_response(struct reader_data *r) {
* the right place in the file according to what we asked for. There's
* not much point releasing the lock while doing the write - the
* background thread will have done all it wants while we were awaiting
- * the response.
+ * the response.
*
* In text mode we can rely on the responses arriving in the correct
* order.
@@ -1575,12 +1559,11 @@ static void reap_write_response(struct reader_data *r) {
progress(r->local, r->written, r->size);
break;
default:
- fatal("unexpected response %d to SSH_FXP_READ", rtype);
+ sftp_fatal("unexpected response %d to SSH_FXP_READ", rtype);
}
}
-static int cmd_get(int ac,
- char **av) {
+static int cmd_get(int ac, char **av) {
int preserve = 0;
const char *e;
char *remote;
@@ -1593,8 +1576,8 @@ static int cmd_get(int ac,
int seek = 0;
uint64_t line = 0;
- memset(&attrs, 0, sizeof attrs);
- memset(&r, 0, sizeof r);
+ sftp_memset(&attrs, 0, sizeof attrs);
+ sftp_memset(&r, 0, sizeof r);
r.fd = -1;
if(av[0][0] == '-') {
const char *s = *av++;
@@ -1605,7 +1588,7 @@ static int cmd_get(int ac,
preserve = 1;
break;
case 'f':
- flags |= SSH_FXF_NOFOLLOW;
+ flags |= SSH_FXF_NOFOLLOW;
break;
case 'L':
seek = 1;
@@ -1628,7 +1611,7 @@ static int cmd_get(int ac,
/* we'll write to a temporary file */
r.tmp = sftp_alloc(fakejob.a, strlen(r.local) + 5);
sprintf(r.tmp, "%s.new", r.local);
- if((r.fd = open(r.tmp, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
+ if((r.fd = open(r.tmp, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) {
error("error opening %s: %s", r.tmp, strerror(errno));
goto error;
}
@@ -1639,9 +1622,8 @@ static int cmd_get(int ac,
r.fd = -1;
}
/* open the remote file */
- if(sftp_open(remote, ACE4_READ_DATA|ACE4_READ_ATTRIBUTES,
- SSH_FXF_OPEN_EXISTING|flags,
- &attrs, &r.h))
+ if(sftp_open(remote, ACE4_READ_DATA | ACE4_READ_ATTRIBUTES,
+ SSH_FXF_OPEN_EXISTING | flags, &attrs, &r.h))
goto error;
/* stat the file */
if(sftp_fstat(&r.h, &attrs))
@@ -1649,8 +1631,8 @@ static int cmd_get(int ac,
if(!textmode && (attrs.valid & SSH_FILEXFER_ATTR_SIZE)) {
/* We know how big the file is. Check we can fit it! */
if((uint64_t)(off_t)attrs.size != attrs.size) {
- error("remote file %s is too large (%"PRIu64" bytes)",
- remote, attrs.size);
+ error("remote file %s is too large (%" PRIu64 " bytes)", remote,
+ attrs.size);
goto error;
}
r.size = attrs.size;
@@ -1663,7 +1645,7 @@ static int cmd_get(int ac,
if(sftp_text_seek(&r.h, line))
goto error;
}
- gettimeofday(&started, 0);
+ gettimeofday(&started, 0);
ferrcheck(pthread_mutex_init(&r.m, 0));
ferrcheck(pthread_cond_init(&r.c1, 0));
ferrcheck(pthread_cond_init(&r.c2, 0));
@@ -1680,7 +1662,7 @@ static int cmd_get(int ac,
while(!r.outstanding)
ferrcheck(pthread_cond_wait(&r.c2, &r.m));
reap_write_response(&r);
- /* Notify the background thread that something changed. */
+ /* Notify the background thread that something changed. */
ferrcheck(pthread_cond_signal(&r.c1));
}
ferrcheck(pthread_mutex_unlock(&r.m));
@@ -1696,23 +1678,23 @@ static int cmd_get(int ac,
ferrcheck(pthread_cond_destroy(&r.c1));
ferrcheck(pthread_cond_destroy(&r.c2));
progress(0, 0, 0);
- if(r.failed)
+ if(r.failed)
goto error;
gettimeofday(&finished, 0);
if(progress_indicators) {
- elapsed = ((finished.tv_sec - started.tv_sec)
- + (finished.tv_usec - started.tv_usec) / 1000000.0);
- xprintf("%"PRIu64" bytes in %.1f seconds", r.written, elapsed);
+ elapsed = ((finished.tv_sec - started.tv_sec) +
+ (finished.tv_usec - started.tv_usec) / 1000000.0);
+ sftp_xprintf("%" PRIu64 " bytes in %.1f seconds", r.written, elapsed);
if(elapsed > 0.1)
- xprintf(" %.0f bytes/sec", r.written / elapsed);
- xprintf("\n");
+ sftp_xprintf(" %.0f bytes/sec", r.written / elapsed);
+ sftp_xprintf("\n");
}
/* Close the handle */
sftp_close(&r.h);
r.h.len = 0;
if(preserve) {
/* Set permissions etc */
- attrs.valid &= ~SSH_FILEXFER_ATTR_SIZE; /* don't truncate */
+ attrs.valid &= ~SSH_FILEXFER_ATTR_SIZE; /* don't truncate */
attrs.valid &= ~SSH_FILEXFER_ATTR_UIDGID; /* different mapping! */
if(sftp_set_fstatus(fakejob.a, r.fd, &attrs, &e) != SSH_FX_OK) {
error("cannot %s %s: %s", e, r.tmp, strerror(errno));
@@ -1735,7 +1717,7 @@ static int cmd_get(int ac,
}
return 0;
error:
- write_translated_done(&r); /* ok to call if not initialized */
+ write_translated_done(&r); /* ok to call if not initialized */
if(r.fd >= 0)
close(r.fd);
if(r.tmp)
@@ -1747,20 +1729,20 @@ error:
/* put uses a thread to gather responses */
struct outstanding_write {
- uint32_t id; /* or 0 for empty slot */
- ssize_t n; /* size of this request */
+ uint32_t id; /* or 0 for empty slot */
+ ssize_t n; /* size of this request */
};
struct writer_data {
- pthread_mutex_t m; /* protects everything here */
- pthread_cond_t c1; /* signal when writer modifies */
- pthread_cond_t c2; /* signal when reader modifies */
- int failed; /* set on failure */
- int outstanding; /* number of outstanding requests */
- int finished; /* set when writer finished */
- struct outstanding_write *reqs; /* outstanding requests */
- const char *remote; /* remote path */
- uint64_t written, total; /* total size */
+ pthread_mutex_t m; /* protects everything here */
+ pthread_cond_t c1; /* signal when writer modifies */
+ pthread_cond_t c2; /* signal when reader modifies */
+ int failed; /* set on failure */
+ int outstanding; /* number of outstanding requests */
+ int finished; /* set when writer finished */
+ struct outstanding_write *reqs; /* outstanding requests */
+ const char *remote; /* remote path */
+ uint64_t written, total; /* total size */
};
static void *writer_thread(void *arg) {
@@ -1778,7 +1760,7 @@ static void *writer_thread(void *arg) {
continue;
}
/* Await the incoming response */
- getresponse(SSH_FXP_STATUS, 0/*don't care about id*/, "SSH_FXP_WRITE");
+ getresponse(SSH_FXP_STATUS, 0 /*don't care about id*/, "SSH_FXP_WRITE");
ferrcheck(pthread_cond_signal(&w->c2));
/* Find the request ID */
for(i = 0; i < nrequests && w->reqs[i].id != fakejob.id; ++i)
@@ -1796,13 +1778,12 @@ static void *writer_thread(void *arg) {
w->failed = 1;
}
}
- progress(0, 0, 0); /* clear progress indicator */
+ progress(0, 0, 0); /* clear progress indicator */
ferrcheck(pthread_mutex_unlock(&w->m));
return 0;
}
-static int cmd_put(int ac,
- char **av) {
+static int cmd_put(int ac, char **av) {
char *local;
const char *remote;
struct sftpattr attrs;
@@ -1821,9 +1802,9 @@ static int cmd_put(int ac,
int setmode = 0;
mode_t mode = 0;
- memset(&h, 0, sizeof h);
- memset(&attrs, 0, sizeof attrs);
- memset(&w, 0, sizeof w);
+ sftp_memset(&h, 0, sizeof h);
+ sftp_memset(&attrs, 0, sizeof attrs);
+ sftp_memset(&w, 0, sizeof w);
if(av[0][0] == '-') {
const char *s = *av++;
++s;
@@ -1832,16 +1813,16 @@ static int cmd_put(int ac,
case 'P':
preserve = 1;
break;
- case 'a':
+ case 'a':
disp = SSH_FXF_OPEN_OR_CREATE;
- flags |= SSH_FXF_APPEND_DATA;
+ flags |= SSH_FXF_APPEND_DATA;
break;
- case 'A':
+ case 'A':
disp = SSH_FXF_OPEN_EXISTING;
- flags |= SSH_FXF_APPEND_DATA;
+ flags |= SSH_FXF_APPEND_DATA;
break;
case 'f':
- flags |= SSH_FXF_NOFOLLOW;
+ flags |= SSH_FXF_NOFOLLOW;
break;
case 't':
disp = SSH_FXF_CREATE_NEW;
@@ -1870,7 +1851,7 @@ static int cmd_put(int ac,
--ac;
} else
remote = basename(local);
- if((fd = open(local, O_RDONLY)) < 0) {
+ if((fd = open(local, O_RDONLY)) < 0) {
error("cannot open %s: %s", local, strerror(errno));
goto error;
}
@@ -1895,13 +1876,13 @@ static int cmd_put(int ac,
/* Mask out things that don't make sense: we set the size by dint of
* uploading data, we don't want to try to set a numeric UID or GID, and we
* cannot set the allocation size or link count. */
- attrs.valid &= ~(SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_LINK_COUNT
- |SSH_FILEXFER_ATTR_UIDGID);
+ attrs.valid &=
+ (uint32_t) ~(SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_LINK_COUNT |
+ SSH_FILEXFER_ATTR_UIDGID);
/* Mask off attributes that don't work in this protocol version */
attrs.valid &= attrmask;
assert(!(attrs.valid & SSH_FILEXFER_ATTR_CTIME));
- attrs.attrib_bits &= ~SSH_FILEXFER_ATTR_FLAGS_HIDDEN;
+ attrs.attrib_bits &= (uint32_t)~SSH_FILEXFER_ATTR_FLAGS_HIDDEN;
}
if(setmode) {
attrs.valid |= SSH_FILEXFER_ATTR_PERMISSIONS;
@@ -1909,8 +1890,7 @@ static int cmd_put(int ac,
}
if(textmode)
flags |= SSH_FXF_TEXT_MODE;
- if(sftp_open(remote, ACE4_WRITE_DATA|ACE4_WRITE_ATTRIBUTES,
- disp | flags,
+ if(sftp_open(remote, ACE4_WRITE_DATA | ACE4_WRITE_ATTRIBUTES, disp | flags,
&attrs, &h))
goto error;
if(textmode) {
@@ -1922,7 +1902,7 @@ static int cmd_put(int ac,
}
w.reqs = sftp_alloc(fakejob.a, nrequests * sizeof *w.reqs);
w.remote = remote;
- gettimeofday(&started, 0);
+ gettimeofday(&started, 0);
ferrcheck(pthread_mutex_init(&w.m, 0));
ferrcheck(pthread_cond_init(&w.c1, 0));
ferrcheck(pthread_cond_init(&w.c2, 0));
@@ -1945,15 +1925,15 @@ static int cmd_put(int ac,
sftp_send_uint64(&fakeworker, offset);
sftp_send_need(fakejob.worker, buffersize + 4);
if(textmode) {
- char *const start = ((char *)fakejob.worker->buffer
- + fakejob.worker->bufused + 4);
+ char *const start =
+ ((char *)fakejob.worker->buffer + fakejob.worker->bufused + 4);
char *ptr = start;
size_t left = buffersize;
const size_t newline_len = strlen(newline);
int c;
/* We will need to perform a translation step. We read from stdio into
* our buffer expanding newlines as necessary. */
-
+
while(left > 0 && (c = getc(fp)) != EOF) {
if(c == '\n') {
/* We found a newline. Let us translated it to the desired wire
@@ -1966,7 +1946,7 @@ static int cmd_put(int ac,
} else {
/* Whoops, we cannot fit a translated newline in. */
if(ungetc(c, fp) < 0)
- fatal("ungetc: %s", strerror(errno));
+ sftp_fatal("ungetc: %s", strerror(errno));
}
} else {
/* This character is not a newline. */
@@ -2025,15 +2005,15 @@ static int cmd_put(int ac,
goto error;
gettimeofday(&finished, 0);
if(progress_indicators) {
- elapsed = ((finished.tv_sec - started.tv_sec)
- + (finished.tv_usec - started.tv_usec) / 1000000.0);
- xprintf("%"PRIu64" bytes in %.1f seconds", w.written, elapsed);
+ elapsed = ((finished.tv_sec - started.tv_sec) +
+ (finished.tv_usec - started.tv_usec) / 1000000.0);
+ sftp_xprintf("%" PRIu64 " bytes in %.1f seconds", w.written, elapsed);
if(elapsed > 0.1)
- xprintf(" %.0f bytes/sec", w.written / elapsed);
- xprintf("\n");
+ sftp_xprintf(" %.0f bytes/sec", w.written / elapsed);
+ sftp_xprintf("\n");
}
if(fd >= 0) {
- close(fd);
+ close(fd);
fd = -1;
}
if(fp) {
@@ -2054,7 +2034,7 @@ error:
close(fd);
if(h.len) {
sftp_close(&h);
- sftp_remove(remote); /* tidy up our mess */
+ sftp_remove(remote); /* tidy up our mess */
}
return -1;
}
@@ -2073,7 +2053,7 @@ static int cmd_progress(int ac, char **av) {
}
static int cmd_text(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
if(protocol->version < 4)
return error("text mode not supported in protocol version %d",
protocol->version);
@@ -2082,13 +2062,12 @@ static int cmd_text(int attribute((unused)) ac,
}
static int cmd_binary(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
textmode = 0;
return 0;
}
-static int cmd_version(int ac,
- char attribute((unused)) **av) {
+static int cmd_version(int ac, char attribute((unused)) * *av) {
if(ac == 1) {
const uint32_t id = newid();
@@ -2099,29 +2078,35 @@ static int cmd_version(int ac,
sftp_send_path(&fakejob, &fakeworker, av[0]);
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, id, "version-select");
- if(status()) return -1;
- if(!strcmp(av[0], "3")) protocol = &sftp_v3;
- else if(!strcmp(av[0], "4")) protocol = &sftp_v4;
- else if(!strcmp(av[0], "5")) protocol = &sftp_v5;
- else if(!strcmp(av[0], "6")) protocol = &sftp_v6;
- else fatal("unknown protocol %s", av[0]);
+ if(status())
+ return -1;
+ if(!strcmp(av[0], "3"))
+ protocol = &sftp_v3;
+ else if(!strcmp(av[0], "4"))
+ protocol = &sftp_v4;
+ else if(!strcmp(av[0], "5"))
+ protocol = &sftp_v5;
+ else if(!strcmp(av[0], "6"))
+ protocol = &sftp_v6;
+ else
+ sftp_fatal("unknown protocol %s", av[0]);
return 0;
} else {
- xprintf("Protocol version: %d\n", protocol->version);
+ sftp_xprintf("Protocol version: %d\n", protocol->version);
if(servername)
- xprintf("Server vendor: %s\n"
- "Server name: %s\n"
- "Server version: %s\n"
- "Server build: %"PRIu64"\n",
- vendorname, servername, serverversion, serverbuild);
+ sftp_xprintf("Server vendor: %s\n"
+ "Server name: %s\n"
+ "Server version: %s\n"
+ "Server build: %" PRIu64 "\n",
+ vendorname, servername, serverversion, serverbuild);
if(serverversions)
- xprintf("Server supports: %s\n", serverversions);
+ sftp_xprintf("Server supports: %s\n", serverversions);
return 0;
}
}
static int cmd_debug(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
sftp_debugging = !sftp_debugging;
D(("sftp_debugging enabled"));
return 0;
@@ -2134,34 +2119,32 @@ static void report_bytes(int width, const char *what, uint64_t howmuch) {
if(!howmuch)
return;
- xprintf("%s:%*s ", what, width - (int)strlen(what), "");
+ sftp_xprintf("%s:%*s ", what, width - (int)strlen(what), "");
if(howmuch >= 8 * gbyte)
- xprintf("%"PRIu64" Gbytes\n", howmuch / gbyte);
+ sftp_xprintf("%" PRIu64 " Gbytes\n", howmuch / gbyte);
else if(howmuch >= 8 * mbyte)
- xprintf("%"PRIu64" Mbytes\n", howmuch / mbyte);
+ sftp_xprintf("%" PRIu64 " Mbytes\n", howmuch / mbyte);
else if(howmuch >= 8 * kbyte)
- xprintf("%"PRIu64" Kbytes\n", howmuch / kbyte);
- else
- xprintf("%"PRIu64" bytes\n", howmuch);
+ sftp_xprintf("%" PRIu64 " Kbytes\n", howmuch / kbyte);
+ else
+ sftp_xprintf("%" PRIu64 " bytes\n", howmuch);
}
-static int cmd_df(int ac,
- char **av) {
+static int cmd_df(int ac, char **av) {
struct space_available as;
- if(sftp_space_available(ac ? av[0] : remote_cwd(), &as))
+ if(sftp_space_available(ac ? av[0] : remote_cwd(), &as))
return -1;
report_bytes(32, "Bytes on device", as.bytes_on_device);
report_bytes(32, "Unused bytes on device", as.unused_bytes_on_device);
report_bytes(32, "Available bytes on device", as.bytes_available_to_user);
- report_bytes(32, "Unused available bytes on device",
+ report_bytes(32, "Unused available bytes on device",
as.unused_bytes_available_to_user);
report_bytes(32, "Bytes per allocation unit", as.bytes_per_allocation_unit);
return 0;
}
-static int cmd_mkdir(int ac,
- char **av) {
+static int cmd_mkdir(int ac, char **av) {
const char *path;
mode_t mode;
@@ -2169,22 +2152,22 @@ static int cmd_mkdir(int ac,
mode = strtoul(av[0], 0, 8);
path = av[1];
} else {
- mode = -1;
+ mode = (mode_t)-1;
path = av[0];
}
return sftp_mkdir(path, mode);
}
static int cmd_init(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
return sftp_init();
}
static int cmd_unsupported(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
sftp_send_begin(&fakeworker);
- sftp_send_uint8(&fakeworker, 0xFFFFFFFF);
- sftp_send_uint32(&fakeworker, 0); /* id */
+ sftp_send_uint8(&fakeworker, 0xFF);
+ sftp_send_uint32(&fakeworker, 0); /* id */
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, 0, "_unsupported");
status();
@@ -2192,10 +2175,10 @@ static int cmd_unsupported(int attribute((unused)) ac,
}
static int cmd_ext_unsupported(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_EXTENDED);
- sftp_send_uint32(&fakeworker, 0); /* id */
+ sftp_send_uint32(&fakeworker, 0); /* id */
sftp_send_string(&fakeworker, "no-such-sftp-extension@rjk.greenend.org.uk");
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, 0, "_unsupported");
@@ -2203,30 +2186,27 @@ static int cmd_ext_unsupported(int attribute((unused)) ac,
return 0;
}
-static int cmd_readlink(int attribute((unused)) ac,
- char **av) {
+static int cmd_readlink(int attribute((unused)) ac, char **av) {
char *r = sftp_readlink(av[0]);
if(r) {
- xprintf("%s\n", r);
+ sftp_xprintf("%s\n", r);
return 0;
} else
return -1;
}
-static int cmd_realpath(int attribute((unused)) ac,
- char **av) {
+static int cmd_realpath(int attribute((unused)) ac, char **av) {
char *r = sftp_realpath(av[0]);
if(r) {
- xprintf("%s\n", r);
+ sftp_xprintf("%s\n", r);
return 0;
} else
return -1;
}
-static int cmd_realpath6(int attribute((unused)) ac,
- char **av) {
+static int cmd_realpath6(int attribute((unused)) ac, char **av) {
int control_byte;
char *resolved;
struct sftpattr attrs;
@@ -2248,14 +2228,14 @@ static int cmd_realpath6(int attribute((unused)) ac,
attrs.name = resolved;
time(&now);
gmtime_r(&now, &nowtime);
- xprintf("%s\n", sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
+ sftp_xprintf("%s\n",
+ sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
} else
- xprintf("%s\n", resolved);
+ sftp_xprintf("%s\n", resolved);
return 0;
}
-static int cmd_lrealpath(int attribute((unused)) ac,
- char **av) {
+static int cmd_lrealpath(int attribute((unused)) ac, char **av) {
char *r;
unsigned flags;
@@ -2264,12 +2244,12 @@ static int cmd_lrealpath(int attribute((unused)) ac,
else if(!strcmp(av[0], "stat-if"))
flags = RP_READLINK;
else if(!strcmp(av[0], "stat-always"))
- flags = RP_READLINK|RP_MUST_EXIST;
+ flags = RP_READLINK | RP_MUST_EXIST;
else
return error("unknown control string '%s'", av[0]);
r = sftp_find_realpath(fakejob.a, av[1], flags);
if(r) {
- xprintf("%s\n", r);
+ sftp_xprintf("%s\n", r);
return 0;
} else {
perror(0);
@@ -2278,7 +2258,7 @@ static int cmd_lrealpath(int attribute((unused)) ac,
}
static int cmd_bad_handle(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
struct client_handle h;
h.len = 8;
@@ -2298,7 +2278,7 @@ static int cmd_bad_handle(int attribute((unused)) ac,
}
static int cmd_bad_packet(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_READ);
/* completely missing ID */
@@ -2307,21 +2287,21 @@ static int cmd_bad_packet(int attribute((unused)) ac,
status();
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_READ);
- sftp_send_uint8(&fakeworker, 0); /* broken ID */
+ sftp_send_uint8(&fakeworker, 0); /* broken ID */
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
status();
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_READ);
sftp_send_uint32(&fakeworker, 0);
- sftp_send_uint8(&fakeworker, 0); /* truncated handle length */
+ sftp_send_uint8(&fakeworker, 0); /* truncated handle length */
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
status();
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_READ);
sftp_send_uint32(&fakeworker, 0);
- sftp_send_uint32(&fakeworker, 64); /* truncated handle */
+ sftp_send_uint32(&fakeworker, 64); /* truncated handle */
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
status();
@@ -2336,7 +2316,7 @@ static int cmd_bad_packet(int attribute((unused)) ac,
sftp_send_uint8(&fakeworker, SSH_FXP_READ);
sftp_send_uint32(&fakeworker, 0);
sftp_send_string(&fakeworker, "12345678");
- sftp_send_uint32(&fakeworker, 0); /* truncated uint64 */
+ sftp_send_uint32(&fakeworker, 0); /* truncated uint64 */
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
status();
@@ -2350,14 +2330,14 @@ static int cmd_bad_packet(int attribute((unused)) ac,
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_READLINK);
sftp_send_uint32(&fakeworker, 0);
- sftp_send_uint32(&fakeworker, 32); /* truncated string */
+ sftp_send_uint32(&fakeworker, 32); /* truncated string */
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
status();
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_READLINK);
sftp_send_uint32(&fakeworker, 0);
- sftp_send_uint8(&fakeworker, 0); /* truncated string length */
+ sftp_send_uint8(&fakeworker, 0); /* truncated string length */
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
status();
@@ -2365,12 +2345,12 @@ static int cmd_bad_packet(int attribute((unused)) ac,
}
static int cmd_bad_packet456(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_SETSTAT);
sftp_send_uint32(&fakeworker, 0);
sftp_send_string(&fakeworker, "path");
- sftp_send_uint32(&fakeworker, 0); /* valid attributes */
+ sftp_send_uint32(&fakeworker, 0); /* valid attributes */
/* missing type field */
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
@@ -2379,12 +2359,12 @@ static int cmd_bad_packet456(int attribute((unused)) ac,
}
static int cmd_bad_path(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_OPENDIR);
sftp_send_uint32(&fakeworker, 0);
- sftp_send_string(&fakeworker, "\xC0"); /* can't be the start of a UTF-8
- * sequence */
+ sftp_send_string(&fakeworker, "\xC0"); /* can't be the start of a UTF-8
+ * sequence */
/* missing type field */
sftp_send_end(&fakeworker);
getresponse(SSH_FXP_STATUS, 0, "_bad_path");
@@ -2392,75 +2372,77 @@ static int cmd_bad_path(int attribute((unused)) ac,
return 0;
}
-static int cmd_stat(int attribute((unused)) ac,
- char **av) {
+static int cmd_stat(int attribute((unused)) ac, char **av) {
struct sftpattr attrs;
time_t now;
struct tm nowtime;
- if(sftp_stat(av[0], &attrs, SSH_FXP_STAT)) return -1;
+ if(sftp_stat(av[0], &attrs, SSH_FXP_STAT))
+ return -1;
time(&now);
gmtime_r(&now, &nowtime);
- xprintf("%s\n", sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
+ sftp_xprintf("%s\n", sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
return 0;
}
-static int cmd_lstat(int attribute((unused)) ac,
- char **av) {
+static int cmd_lstat(int attribute((unused)) ac, char **av) {
struct sftpattr attrs;
time_t now;
struct tm nowtime;
- if(sftp_stat(av[0], &attrs, SSH_FXP_LSTAT)) return -1;
+ if(sftp_stat(av[0], &attrs, SSH_FXP_LSTAT))
+ return -1;
time(&now);
gmtime_r(&now, &nowtime);
- xprintf("%s\n", sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
+ sftp_xprintf("%s\n", sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
return 0;
}
-static int cmd_statfs(int attribute((unused)) ac,
- char **av) {
+static int cmd_statfs(int attribute((unused)) ac, char **av) {
struct statvfs_reply sr;
- if(sftp_statvfs(av[0], &sr)) return -1;
- xprintf("bsize %"PRIu64" frsize %"PRIu64
- " id %"PRIx64" flags %"PRIx64" namemax %"PRIu64"\n"
- " blocks %9"PRIu64"/%-9"PRIu64" (%"PRIu64")\n"
- " files %9"PRIu64"/%-9"PRIu64" (%"PRIu64")\n",
- sr.bsize, sr.frsize,
- sr.fsid, sr.flags, sr.namemax,
- sr.bfree, sr.blocks, sr.bavail,
- sr.ffree, sr.files, sr.favail);
+ if(sftp_statvfs(av[0], &sr))
+ return -1;
+ sftp_xprintf("bsize %" PRIu64 " frsize %" PRIu64 " id %" PRIx64
+ " flags %" PRIx64 " namemax %" PRIu64 "\n"
+ " blocks %9" PRIu64 "/%-9" PRIu64 " (%" PRIu64 ")\n"
+ " files %9" PRIu64 "/%-9" PRIu64 " (%" PRIu64 ")\n",
+ sr.bsize, sr.frsize, sr.fsid, sr.flags, sr.namemax, sr.bfree,
+ sr.blocks, sr.bavail, sr.ffree, sr.files, sr.favail);
return 0;
}
-static int cmd_truncate(int attribute((unused)) ac,
- char **av) {
+static int cmd_truncate(int attribute((unused)) ac, char **av) {
struct sftpattr attrs;
- memset(&attrs, 0, sizeof attrs);
+ sftp_memset(&attrs, 0, sizeof attrs);
attrs.valid = SSH_FILEXFER_ATTR_SIZE;
attrs.size = strtoull(av[0], 0, 0);
return sftp_setstat(av[1], &attrs);
}
static int cmd_overlap(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
struct sftpattr attrs;
- static const char a[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
- static const char b[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
- static const char c[] = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";
- static const char d[] = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
- static const char expect[] = "aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
+ static const char a[] =
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ static const char b[] =
+ "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
+ static const char c[] =
+ "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";
+ static const char d[] =
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
+ static const char expect[] =
+ "aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccdddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddddddddddd";
char buffer[128];
int n, r, rc = -1;
uint32_t ida, idb, idc, idd;
int fd = -1;
struct client_handle h;
- memset(&attrs, 0, sizeof attrs);
- if(sftp_open("dest", ACE4_WRITE_DATA,
- SSH_FXF_CREATE_TRUNCATE, &attrs, &h))
+ sftp_memset(&attrs, 0, sizeof attrs);
+ if(sftp_open("dest", ACE4_WRITE_DATA, SSH_FXF_CREATE_TRUNCATE, &attrs, &h))
goto error;
if((fd = open("dest", O_RDWR)) < 0) {
perror("open dest");
@@ -2474,7 +2456,7 @@ static int cmd_overlap(int attribute((unused)) ac,
sftp_send_uint64(&fakeworker, 0);
sftp_send_bytes(&fakeworker, a, 64);
sftp_send_end(&fakeworker);
-
+
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_WRITE);
sftp_send_uint32(&fakeworker, idb = newid());
@@ -2482,7 +2464,7 @@ static int cmd_overlap(int attribute((unused)) ac,
sftp_send_uint64(&fakeworker, 16);
sftp_send_bytes(&fakeworker, b, 64);
sftp_send_end(&fakeworker);
-
+
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_WRITE);
sftp_send_uint32(&fakeworker, idc = newid());
@@ -2490,7 +2472,7 @@ static int cmd_overlap(int attribute((unused)) ac,
sftp_send_uint64(&fakeworker, 32);
sftp_send_bytes(&fakeworker, c, 64);
sftp_send_end(&fakeworker);
-
+
sftp_send_begin(&fakeworker);
sftp_send_uint8(&fakeworker, SSH_FXP_WRITE);
sftp_send_uint32(&fakeworker, idd = newid());
@@ -2510,13 +2492,14 @@ static int cmd_overlap(int attribute((unused)) ac,
goto error;
}
r = read(fd, buffer, sizeof buffer);
- if(r != 48+64) {
- fprintf(stderr, "expected %d bytes got %d\n", 48+64, r);
+ if(r != 48 + 64) {
+ fprintf(stderr, "expected %d bytes got %d\n", 48 + 64, r);
goto error;
}
- buffer[r] = 0; /* ensure buffer terminated */
- if(memcmp(buffer, expect, 48+64)) {
- fprintf(stderr, "buffer contents mismatch\n"
+ buffer[r] = 0; /* ensure buffer terminated */
+ if(memcmp(buffer, expect, 48 + 64)) {
+ fprintf(stderr,
+ "buffer contents mismatch\n"
"expect: %s\n"
" got: %s\n",
expect, buffer);
@@ -2534,243 +2517,66 @@ error:
return rc;
}
-
/* Table of command line operations */
static const struct command commands[] = {
- {
- "_bad_handle", 0, 0, cmd_bad_handle,
- 0,
- "operate on a bogus handle"
- },
- {
- "_bad_packet", 0, 0, cmd_bad_packet,
- 0,
- "send bad packets"
- },
- {
- "_bad_packet456", 0, 0, cmd_bad_packet456,
- 0,
- "send bad packets (protos >= 4 only)"
- },
- {
- "_bad_path", 0, 0, cmd_bad_path,
- 0,
- "send bad paths"
- },
- {
- "_ext_unsupported", 0, 0, cmd_ext_unsupported,
- 0,
- "send an unsupported extension"
- },
- {
- "_init", 0, 0, cmd_init,
- 0,
- "resend SSH_FXP_INIT"
- },
- {
- "_lrealpath", 2, 2, cmd_lrealpath,
- "CONTROL PATH",
- "expand a local path name"
- },
- {
- "_overlap", 0, 0, cmd_overlap,
- "",
- "test overlapping writes"
- },
- {
- "_unsupported", 0, 0, cmd_unsupported,
- 0,
- "send an unsupported command"
- },
- {
- "binary", 0, 0, cmd_binary,
- 0,
- "binary mode"
- },
- {
- "bye", 0, 0, cmd_quit,
- 0,
- "quit"
- },
- {
- "cd", 1, 1, cmd_cd,
- "DIR",
- "change remote directory"
- },
- {
- "chgrp", 2, 2, cmd_chgrp,
- "GID PATH",
- "change remote file group"
- },
- {
- "chmod", 2, 2, cmd_chmod,
- "OCTAL PATH",
- "change remote file permissions"
- },
- {
- "chown", 2, 2, cmd_chown,
- "UID PATH",
- "change remote file ownership"
- },
- {
- "debug", 0, 0, cmd_debug,
- 0,
- "toggle sftp_debugging"
- },
- {
- "df", 0, 1, cmd_df,
- "[PATH]",
- "query available space"
- },
- {
- "exit", 0, 0, cmd_quit,
- 0,
- "quit"
- },
- {
- "get", 1, 3, cmd_get,
- "[-PfL<line>] REMOTE-PATH [LOCAL-PATH]",
- "retrieve a remote file"
- },
- {
- "help", 0, 0, cmd_help,
- 0,
- "display help"
- },
- {
- "lcd", 1, 1, cmd_lcd,
- "DIR",
- "change local directory"
- },
- {
- "link", 2, 2, cmd_link,
- "OLDPATH NEWPATH",
- "create a remote hard link"
- },
- {
- "lpwd", 0, 0, cmd_lpwd,
- "DIR",
- "display current local directory"
- },
- {
- "lls", 0, INT_MAX, cmd_lls,
- "[OPTIONS] [LOCAL-PATH]",
- "list local directory"
- },
- {
- "lmkdir", 1, 1, cmd_lmkdir,
- "LOCAL-PATH",
- "create local directory"
- },
- {
- "ls", 0, 2, cmd_ls,
- "[OPTIONS] [PATH]",
- "list remote directory"
- },
- {
- "lstat", 1, 1, cmd_lstat,
- "PATH",
- "lstat a file"
- },
- {
- "lumask", 0, 1, cmd_lumask,
- "OCTAL",
- "get or set local umask"
- },
- {
- "mkdir", 1, 2, cmd_mkdir,
- "[MODE] DIRECTORY",
- "create a remote directory"
- },
- {
- "mv", 2, 3, cmd_mv,
- "[-naop] OLDPATH NEWPATH",
- "rename a remote file"
- },
- {
- "progress", 0, 1, cmd_progress,
- "[on|off]",
- "set or toggle progress indicators"
- },
- {
- "put", 1, 3, cmd_put, "[-PaftemMODE] LOCAL-PATH [REMOTE-PATH]",
- "upload a file"
- },
- {
- "pwd", 0, 0, cmd_pwd,
- 0,
- "display current remote directory"
- },
- {
- "quit", 0, 0, cmd_quit,
- 0,
- "quit"
- },
- {
- "readlink", 1, 1, cmd_readlink,
- "PATH",
- "inspect a symlink"
- },
- {
- "realpath", 1, 1, cmd_realpath,
- "PATH",
- "expand a path name"
- },
- {
- "realpath6", 2, INT_MAX, cmd_realpath6,
- "CONTROL PATH [COMPOSE...]",
- "expand a path name"
- },
- {
- "rename", 2, 2, cmd_mv,
- "OLDPATH NEWPATH",
- "rename a remote file"
- },
- {
- "rm", 1, 1, cmd_rm,
- "PATH",
- "remove remote file"
- },
- {
- "rmdir", 1, 1, cmd_rmdir,
- "PATH",
- "remove remote directory"
- },
- {
- "symlink", 2, 2, cmd_symlink,
- "TARGET NEWPATH",
- "create a remote symlink"
- },
- {
- "stat", 1, 1, cmd_stat,
- "PATH",
- "stat a file"
- },
- {
- "statfs", 1, 1, cmd_statfs,
- "PATH",
- "stat a filesystem"
- },
- {
- "text", 0, 0, cmd_text,
- 0,
- "text mode"
- },
- {
- "truncate", 2, 2, cmd_truncate,
- "LENGTH FILE",
- "truncate a file"
- },
- {
- "version", 0, 1, cmd_version,
- 0,
- "set or display protocol version"
- },
- { 0, 0, 0, 0, 0, 0 }
-};
+ {"_bad_handle", 0, 0, cmd_bad_handle, 0, "operate on a bogus handle"},
+ {"_bad_packet", 0, 0, cmd_bad_packet, 0, "send bad packets"},
+ {"_bad_packet456", 0, 0, cmd_bad_packet456, 0,
+ "send bad packets (protos >= 4 only)"},
+ {"_bad_path", 0, 0, cmd_bad_path, 0, "send bad paths"},
+ {"_ext_unsupported", 0, 0, cmd_ext_unsupported, 0,
+ "send an unsupported extension"},
+ {"_init", 0, 0, cmd_init, 0, "resend SSH_FXP_INIT"},
+ {"_lrealpath", 2, 2, cmd_lrealpath, "CONTROL PATH",
+ "expand a local path name"},
+ {"_overlap", 0, 0, cmd_overlap, "", "test overlapping writes"},
+ {"_unsupported", 0, 0, cmd_unsupported, 0, "send an unsupported command"},
+ {"binary", 0, 0, cmd_binary, 0, "binary mode"},
+ {"bye", 0, 0, cmd_quit, 0, "quit"},
+ {"cd", 1, 1, cmd_cd, "DIR", "change remote directory"},
+ {"chgrp", 2, 2, cmd_chgrp, "GID PATH", "change remote file group"},
+ {"chmod", 2, 2, cmd_chmod, "OCTAL PATH", "change remote file permissions"},
+ {"chown", 2, 2, cmd_chown, "UID PATH", "change remote file ownership"},
+ {"debug", 0, 0, cmd_debug, 0, "toggle sftp_debugging"},
+ {"df", 0, 1, cmd_df, "[PATH]", "query available space"},
+ {"exit", 0, 0, cmd_quit, 0, "quit"},
+ {"get", 1, 3, cmd_get, "[-PfL<line>] REMOTE-PATH [LOCAL-PATH]",
+ "retrieve a remote file"},
+ {"help", 0, 0, cmd_help, 0, "display help"},
+ {"lcd", 1, 1, cmd_lcd, "DIR", "change local directory"},
+ {"link", 2, 2, cmd_link, "OLDPATH NEWPATH", "create a remote hard link"},
+ {"lpwd", 0, 0, cmd_lpwd, "DIR", "display current local directory"},
+ {"lls", 0, INT_MAX, cmd_lls, "[OPTIONS] [LOCAL-PATH]",
+ "list local directory"},
+ {"lmkdir", 1, 1, cmd_lmkdir, "LOCAL-PATH", "create local directory"},
+ {"ls", 0, 2, cmd_ls, "[OPTIONS] [PATH]", "list remote directory"},
+ {"lstat", 1, 1, cmd_lstat, "PATH", "lstat a file"},
+ {"lumask", 0, 1, cmd_lumask, "OCTAL", "get or set local umask"},
+ {"mkdir", 1, 2, cmd_mkdir, "[MODE] DIRECTORY", "create a remote directory"},
+ {"mv", 2, 3, cmd_mv, "[-naop] OLDPATH NEWPATH", "rename a remote file"},
+ {"progress", 0, 1, cmd_progress, "[on|off]",
+ "set or toggle progress indicators"},
+ {"put", 1, 3, cmd_put, "[-PaftemMODE] LOCAL-PATH [REMOTE-PATH]",
+ "upload a file"},
+ {"pwd", 0, 0, cmd_pwd, 0, "display current remote directory"},
+ {"quit", 0, 0, cmd_quit, 0, "quit"},
+ {"readlink", 1, 1, cmd_readlink, "PATH", "inspect a symlink"},
+ {"realpath", 1, 1, cmd_realpath, "PATH", "expand a path name"},
+ {"realpath6", 2, INT_MAX, cmd_realpath6, "CONTROL PATH [COMPOSE...]",
+ "expand a path name"},
+ {"rename", 2, 2, cmd_mv, "OLDPATH NEWPATH", "rename a remote file"},
+ {"rm", 1, 1, cmd_rm, "PATH", "remove remote file"},
+ {"rmdir", 1, 1, cmd_rmdir, "PATH", "remove remote directory"},
+ {"symlink", 2, 2, cmd_symlink, "TARGET NEWPATH", "create a remote symlink"},
+ {"stat", 1, 1, cmd_stat, "PATH", "stat a file"},
+ {"statfs", 1, 1, cmd_statfs, "PATH", "stat a filesystem"},
+ {"text", 0, 0, cmd_text, 0, "text mode"},
+ {"truncate", 2, 2, cmd_truncate, "LENGTH FILE", "truncate a file"},
+ {"version", 0, 1, cmd_version, 0, "set or display protocol version"},
+ {0, 0, 0, 0, 0, 0}};
static int cmd_help(int attribute((unused)) ac,
- char attribute((unused)) **av) {
+ char attribute((unused)) * *av) {
int n;
size_t max = 0, len = 0;
@@ -2780,19 +2586,19 @@ static int cmd_help(int attribute((unused)) ac,
len = strlen(commands[n].name);
if(commands[n].args)
len += strlen(commands[n].args) + 1;
- if(len > max)
+ if(len > max)
max = len;
}
for(n = 0; commands[n].name; ++n) {
if(commands[n].name[0] == '_')
continue;
len = strlen(commands[n].name);
- xprintf("%s", commands[n].name);
+ sftp_xprintf("%s", commands[n].name);
if(commands[n].args) {
len += strlen(commands[n].args) + 1;
- xprintf(" %s", commands[n].args);
+ sftp_xprintf(" %s", commands[n].args);
}
- xprintf("%*s %s\n", (int)(max - len), "", commands[n].help);
+ sftp_xprintf("%*s %s\n", (int)(max - len), "", commands[n].help);
}
return 0;
}
@@ -2814,14 +2620,14 @@ static char *input(const char *prompt, FILE *fp) {
}
return s;
#else
- xprintf("%s", prompt);
+ sftp_xprintf("%s", prompt);
if(fflush(stdout) < 0)
- fatal("error calling fflush: %s", strerror(errno));
+ sftp_fatal("error calling fflush: %s", strerror(errno));
#endif
}
if(!fgets(buffer, sizeof buffer, fp))
return 0;
- return xstrdup(buffer);
+ return sftp_xstrdup(buffer);
}
/* Input processing loop */
@@ -2829,15 +2635,15 @@ static void process(const char *prompt, FILE *fp) {
char *line;
int ac, n, rc;
char *avbuf[256], **av;
-
+
while((line = input(prompt, fp))) {
++inputline;
if(line[0] == '#')
goto next;
if(echo) {
- xprintf("%s", line);
+ sftp_xprintf("%s", line);
if(fflush(stdout) < 0)
- fatal("error calling fflush: %s", strerror(errno));
+ sftp_fatal("error calling fflush: %s", strerror(errno));
}
if(line[0] == '!') {
if(line[1] != '\n')
@@ -2850,7 +2656,7 @@ static void process(const char *prompt, FILE *fp) {
}
if((ac = split(line, av = avbuf)) < 0) {
if(stoponerror)
- fatal("stopping on error");
+ sftp_fatal("stopping on error");
goto next;
}
if(!ac)
@@ -2860,30 +2666,30 @@ static void process(const char *prompt, FILE *fp) {
if(!commands[n].name) {
error("unknown command: '%s'", av[0]);
if(stoponerror)
- fatal("stopping on error");
+ sftp_fatal("stopping on error");
goto next;
}
++av;
--ac;
if(ac < commands[n].minargs || ac > commands[n].maxargs) {
- error("wrong number of arguments (got %d, want %d-%d)",
- ac, commands[n].minargs, commands[n].maxargs);
+ error("wrong number of arguments (got %d, want %d-%d)", ac,
+ commands[n].minargs, commands[n].maxargs);
if(stoponerror)
- fatal("stopping on error");
+ sftp_fatal("stopping on error");
goto next;
}
if(commands[n].handler(ac, av) && stoponerror)
- fatal("stopping on error");
-next:
+ sftp_fatal("stopping on error");
+ next:
if(fflush(stdout) < 0)
- fatal("error calling fflush: %s", strerror(errno));
+ sftp_fatal("error calling fflush: %s", strerror(errno));
sftp_alloc_destroy(fakejob.a);
free(line);
}
if(ferror(fp))
- fatal("error reading %s: %s", inputpath, strerror(errno));
+ sftp_fatal("error reading %s: %s", inputpath, strerror(errno));
if(prompt)
- xprintf("\n");
+ sftp_xprintf("\n");
}
int main(int argc, char **argv) {
@@ -2895,14 +2701,14 @@ int main(int argc, char **argv) {
int dropbear = 0;
#if HAVE_GETADDRINFO
- memset(&hints, 0, sizeof hints);
+ sftp_memset(&hints, 0, sizeof hints);
hints.ai_flags = 0;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
#endif
setlocale(LC_ALL, "");
- newline = xstrdup("\r\n");
+ newline = sftp_xstrdup("\r\n");
/* Figure out terminal width */
{
@@ -2918,41 +2724,104 @@ int main(int argc, char **argv) {
}
while((n = getopt_long(argc, argv, "hVrB:b:P:R:s:S:12CF:o:vdH:p:46D:",
- options, 0)) >= 0) {
+ options, 0)) >= 0) {
switch(n) {
- case 'h': help();
- case 'V': version();
- case 'r': dropbear++; break;
- case 'B': buffersize = atoi(optarg); break;
- case 'b': batchfile = optarg; stoponerror = 1; progress_indicators = 0; break;
- case 'P': program = optarg; break;
- case 'R': nrequests = atoi(optarg); break;
- case 's': subsystem = optarg; break;
- case 'S': sftpversion = atoi(optarg); break;
- case '1': sshversion = 1; break;
- case '2': sshversion = 2; break;
- case 'C': compress = 1; break;
- case 'F': sshconf = optarg; break;
- case 'o': sshoptions[nsshoptions++] = optarg; break;
- case 'v': sshverbose++; break;
- case 'd': sftp_debugging = 1; break;
- case 'D': sftp_debugging = 1; sftp_debugpath = optarg; break;
- case 256: quirk_reverse_symlink = 1; break;
- case 257: stoponerror = 1; break;
- case 258: stoponerror = 0; break;
- case 259: progress_indicators = 1; break;
- case 260: progress_indicators = 0; break;
- case 261: echo = 1; break;
- case 262: signal(SIGPIPE, SIG_DFL); break; /* stupid python */
- case 263: sftpversion = atoi(optarg); forceversion = 1; break;
- case 264: program_debugpath = optarg; break;
- case 'H': host = optarg; break;
- case 'p': port = optarg; break;
+ case 'h':
+ help();
+ case 'V':
+ version();
+ case 'r':
+ dropbear++;
+ break;
+ case 'B':
+ buffersize = atoi(optarg);
+ break;
+ case 'b':
+ batchfile = optarg;
+ stoponerror = 1;
+ progress_indicators = 0;
+ break;
+ case 'P':
+ program = optarg;
+ break;
+ case 'R':
+ nrequests = atoi(optarg);
+ break;
+ case 's':
+ subsystem = optarg;
+ break;
+ case 'S':
+ sftpversion = atoi(optarg);
+ break;
+ case '1':
+ sshversion = 1;
+ break;
+ case '2':
+ sshversion = 2;
+ break;
+ case 'C':
+ compress = 1;
+ break;
+ case 'F':
+ sshconf = optarg;
+ break;
+ case 'o':
+ sshoptions[nsshoptions++] = optarg;
+ break;
+ case 'v':
+ sshverbose++;
+ break;
+ case 'd':
+ sftp_debugging = 1;
+ break;
+ case 'D':
+ sftp_debugging = 1;
+ sftp_debugpath = optarg;
+ break;
+ case 256:
+ quirk_reverse_symlink = 1;
+ break;
+ case 257:
+ stoponerror = 1;
+ break;
+ case 258:
+ stoponerror = 0;
+ break;
+ case 259:
+ progress_indicators = 1;
+ break;
+ case 260:
+ progress_indicators = 0;
+ break;
+ case 261:
+ echo = 1;
+ break;
+ case 262:
+ signal(SIGPIPE, SIG_DFL);
+ break; /* stupid python */
+ case 263:
+ sftpversion = atoi(optarg);
+ forceversion = 1;
+ break;
+ case 264:
+ program_debugpath = optarg;
+ break;
+ case 'H':
+ host = optarg;
+ break;
+ case 'p':
+ port = optarg;
+ break;
#if HAVE_GETADDRINFO
- case '4': hints.ai_family = PF_INET; break;
- case '6': hints.ai_family = PF_INET6; break;
+ case '4':
+ hints.ai_family = PF_INET;
+ break;
+ case '6':
+ hints.ai_family = PF_INET6;
+ break;
#endif
- default: exit(1);
+ default:
+ exit(1);
}
}
@@ -2967,28 +2836,27 @@ int main(int argc, char **argv) {
buffersize = 1048576;
if((sftpversion < 3 || sftpversion > 6) && !forceversion)
- fatal("unknown SFTP version %d", sftpversion);
-
+ sftp_fatal("unknown SFTP version %d", sftpversion);
+
if(host || port) {
#if HAVE_GETADDRINFO
struct addrinfo *res;
int rc, fd;
if(!(host && port) || program || subsystem)
- fatal("inconsistent options");
+ sftp_fatal("inconsistent options");
if((rc = getaddrinfo(host, port, &hints, &res)))
- fatal("error resolving host %s port %s: %s",
- host, port, gai_strerror(rc));
- if((fd = socket(res->ai_family, res->ai_socktype,
- res->ai_protocol)) < 0)
- fatal("error calling socket: %s", strerror(errno));
+ sftp_fatal("error resolving host %s port %s: %s", host, port,
+ gai_strerror(rc));
+ if((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
+ sftp_fatal("error calling socket: %s", strerror(errno));
if(connect(fd, res->ai_addr, res->ai_addrlen) < 0)
- fatal("error connecting to host %s port %s: %s",
- host, port, strerror(errno));
+ sftp_fatal("error connecting to host %s port %s: %s", host, port,
+ strerror(errno));
sftpin = sftpout = fd;
#else
/* It's hardly a core feature... */
- fatal("--host is not supported on this platform");
+ sftp_fatal("--host is not supported on this platform");
#endif
} else {
const char *cmdline[2048];
@@ -3004,7 +2872,7 @@ int main(int argc, char **argv) {
}
} else {
if(optind >= argc)
- fatal("missing USER@HOST argument");
+ sftp_fatal("missing USER@HOST argument");
if(dropbear) {
cmdline[ncmdline++] = "dbclient";
} else {
@@ -3031,40 +2899,39 @@ int main(int argc, char **argv) {
cmdline[ncmdline++] = subsystem ? subsystem : "sftp";
}
cmdline[ncmdline] = 0;
- xpipe(ip);
- xpipe(op);
- if(!(pid = xfork())) {
- xclose(ip[0]);
- xclose(op[1]);
- xdup2(ip[1], 1);
- xdup2(op[0], 0);
+ sftp_xpipe(ip);
+ sftp_xpipe(op);
+ if(!(pid = sftp_xfork())) {
+ sftp_xclose(ip[0]);
+ sftp_xclose(op[1]);
+ sftp_xdup2(ip[1], 1);
+ sftp_xdup2(op[0], 0);
execvp(cmdline[0], (void *)cmdline);
- fatal("executing %s: %s", cmdline[0], strerror(errno));
+ sftp_fatal("executing %s: %s", cmdline[0], strerror(errno));
}
- xclose(ip[1]);
- xclose(op[0]);
+ sftp_xclose(ip[1]);
+ sftp_xclose(op[0]);
sftpin = ip[0];
sftpout = op[1];
}
fakejob.a = sftp_alloc_init(&allocator);
fakejob.worker = &fakeworker;
- if((fakeworker.utf8_to_local = iconv_open(nl_langinfo(CODESET), "UTF-8"))
- == (iconv_t)-1)
- fatal("error calling iconv_open: %s", strerror(errno));
- if((fakeworker.local_to_utf8 = iconv_open("UTF-8", nl_langinfo(CODESET)))
- == (iconv_t)-1)
- fatal("error calling iconv_open: %s", strerror(errno));
+ if((fakeworker.utf8_to_local = iconv_open(nl_langinfo(CODESET), "UTF-8")) ==
+ (iconv_t)-1)
+ sftp_fatal("error calling iconv_open: %s", strerror(errno));
+ if((fakeworker.local_to_utf8 = iconv_open("UTF-8", nl_langinfo(CODESET))) ==
+ (iconv_t)-1)
+ sftp_fatal("error calling iconv_open: %s", strerror(errno));
if(sftp_init())
return 1;
-
if(batchfile) {
FILE *fp;
inputpath = batchfile;
if(!(fp = fopen(batchfile, "r")))
- fatal("error opening %s: %s", batchfile, strerror(errno));
+ sftp_fatal("error opening %s: %s", batchfile, strerror(errno));
process(0, fp);
} else {
inputpath = "stdin";
diff --git a/sftpclient.h b/sftpclient.h
index dad4485..d3f2bdc 100644
--- a/sftpclient.h
+++ b/sftpclient.h
@@ -19,13 +19,13 @@
*/
#ifndef SFTPCLIENT_H
-#define SFTPCLIENT_H
+# define SFTPCLIENT_H
-#define CLIENT 1
+# define CLIENT 1
-#include "sftpcommon.h"
+# include "sftpcommon.h"
-#include <sys/types.h>
+# include <sys/types.h>
#endif /* SFTPCLIENT_H */
diff --git a/sftpcommon.h b/sftpcommon.h
index 45a3d25..5785254 100644
--- a/sftpcommon.h
+++ b/sftpcommon.h
@@ -19,58 +19,66 @@
*/
#ifndef SFTPCOMMON_H
-#define SFTPCOMMON_H
+# define SFTPCOMMON_H
/** @file sftpcommon.h @brief Common definitions */
-#include <config.h>
-#include <inttypes.h>
-#include <sys/types.h>
+# include <config.h>
+# include <inttypes.h>
+# include <sys/types.h>
-#if HAVE_ENDIAN_H
-# include <endian.h>
-#endif
+# if HAVE_ENDIAN_H
+# include <endian.h>
+# endif
-#ifndef ASM
-# define ASM 1
-#endif
+# ifndef ASM
+# define ASM 1
+# endif
-#if __GNUC__ && __amd64__ && ASM
+# if __GNUC__ && __amd64__ && ASM
/** @brief Byte-swap a 64-bit value */
-#define BSWAP64(N) \
- ({uint64_t __n = (N); __asm__("bswap %0" : "+q"(__n)); __n;})
-#endif
+# define BSWAP64(N) \
+ ({ \
+ uint64_t __n = (N); \
+ __asm__("bswap %0" : "+q"(__n)); \
+ __n; \
+ })
+# endif
-#if __GNUC__ && !defined BSWAP64
+# if __GNUC__ && !defined BSWAP64
/** @brief Byte-swap a 64-bit value */
-#define BSWAP64(N) \
- ({uint64_t __n = (N); __n = ntohl(__n >> 32) | ((uint64_t)ntohl(__n) << 32); __n;})
-#endif
+# define BSWAP64(N) \
+ ({ \
+ uint64_t __n = (N); \
+ __n = ntohl(__n >> 32) | ((uint64_t)ntohl(__n) << 32); \
+ __n; \
+ })
+# endif
-#if WORDS_BIGENDIAN
+# if WORDS_BIGENDIAN
/** @brief Convert a 64-bit value to network byte order */
-# define NTOHLL(n) (n)
+# define NTOHLL(n) (n)
/** @brief Convert a 64-bit value to host byte order */
-# define HTONLL(n) (n)
-#endif
+# define HTONLL(n) (n)
+# endif
-#if HAVE_DECL_BE64TOH && !defined NTOHLL
+# if HAVE_DECL_BE64TOH && !defined NTOHLL
/** @brief Convert a 64-bit value to network byte order */
-# define NTOHLL be64toh
-#endif
-#if HAVE_DECL_HTOBE64 && !defined HTONLL
+# define NTOHLL be64toh
+# endif
+# if HAVE_DECL_HTOBE64 && !defined HTONLL
/** @brief Convert a 64-bit value to host byte order */
-#define HTONLL htobe64
-#endif
+# define HTONLL htobe64
+# endif
-#if defined BSWAP64 && !defined NTOHLL
+# if defined BSWAP64 && !defined NTOHLL
/** @brief Convert a 64-bit value to network byte order */
-# define NTOHLL BSWAP64
-#endif
-#if defined BSWAP64 && !defined HTONLL
+# define NTOHLL BSWAP64
+# endif
+# if defined BSWAP64 && !defined HTONLL
/** @brief Convert a 64-bit value to host byte order */
-# define HTONLL BSWAP64
-#endif
+# define HTONLL BSWAP64
+# endif
struct queue;
struct allocator;
@@ -86,6 +94,22 @@ struct stat;
*/
const char *status_to_string(uint32_t status);
+/** @brief Possible SFTP service states */
+enum sftp_state {
+ sftp_state_run = 0,
+ sftp_state_stop = 1,
+};
+
+/** @brief Get the current SFTP service state
+ * @return State value
+ */
+enum sftp_state sftp_state_get(void);
+
+/** @brief Set the SFTP service state
+ * @param s New state value
+ */
+void sftp_state_set(enum sftp_state s);
+
#endif /* SFTPCOMMON_H */
/*
diff --git a/sftpserver.c b/sftpserver.c
index c23a8b9..e99aded 100644
--- a/sftpserver.c
+++ b/sftpserver.c
@@ -51,17 +51,17 @@
#include <syslog.h>
#include <netinet/in.h>
#if HAVE_SYS_PRCTL_H
-# include <sys/prctl.h>
+# include <sys/prctl.h>
#endif
/* Linux and BSD have daemon() but other UNIX platforms tend not to */
-#if ! HAVE_DAEMON
+#if !HAVE_DAEMON
int daemon(int, int);
#endif
/* LOG_FTP doesn't exist everywhere */
#ifndef LOG_FTP
-# define LOG_FTP LOG_DAEMON
+# define LOG_FTP LOG_DAEMON
#endif
/* Forward declarations */
@@ -77,10 +77,7 @@ static const char *local_encoding;
#if NTHREADS > 1
/** @brief Queue-specific callbacks for processing SFTP requests */
static const struct queuedetails workqueue_details = {
- worker_init,
- process_sftpjob,
- worker_cleanup
-};
+ worker_init, process_sftpjob, worker_cleanup};
#endif
const struct sftpprotocol *protocol = &sftp_preinit;
@@ -89,48 +86,47 @@ const char sendtype[] = "response";
/* Options */
static const struct option options[] = {
- { "help", no_argument, 0, 'h' },
- { "version", no_argument, 0, 'V' },
- { "debug", no_argument, 0, 'd' },
- { "debug-file", required_argument, 0, 'D' },
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"debug", no_argument, 0, 'd'},
+ {"debug-file", required_argument, 0, 'D'},
#if DAEMON
- { "chroot", required_argument, 0, 'r' },
- { "user", required_argument, 0, 'u' },
- { "listen", required_argument, 0, 'L' },
- { "host", required_argument, 0, 'H' },
- { "background", no_argument, 0, 'b' },
- { "ipv4", no_argument, 0, '4' },
- { "ipv6", no_argument, 0, '6' },
+ {"chroot", required_argument, 0, 'r'},
+ {"user", required_argument, 0, 'u'},
+ {"listen", required_argument, 0, 'L'},
+ {"host", required_argument, 0, 'H'},
+ {"background", no_argument, 0, 'b'},
+ {"ipv4", no_argument, 0, '4'},
+ {"ipv6", no_argument, 0, '6'},
#endif
- { "readonly", no_argument, 0, 'R' },
- { 0, 0, 0, 0 }
-};
+ {"readonly", no_argument, 0, 'R'},
+ {0, 0, 0, 0}};
/* display usage message and terminate */
static void attribute((noreturn)) help(void) {
- xprintf("Usage:\n"
- " gesftpserver [OPTIONS]\n"
- "\n"
- "Green End SFTP server. Not intended for interactive use!\n"
- "\n");
- xprintf("Options:\n"
- " --help, -h Display usage message\n"
- " --version, -V Display version number\n"
+ sftp_xprintf("Usage:\n"
+ " gesftpserver [OPTIONS]\n"
+ "\n"
+ "Green End SFTP server. Not intended for interactive use!\n"
+ "\n");
+ sftp_xprintf("Options:\n"
+ " --help, -h Display usage message\n"
+ " --version, -V Display version number\n"
#if DAEMON
- " --chroot, -r PATH Change root to PATH\n"
- " --user, -u USER Change to user USER\n"
- " --listen, -L PORT Listen on PORT\n"
- " --host, -H HOSTNAME Bind to HOSTNAME (default *)\n"
- " -4|-6 Force IPv4 or IPv6 for --listen\n"
- " --background, -b Daemonize\n"
+ " --chroot, -r PATH Change root to PATH\n"
+ " --user, -u USER Change to user USER\n"
+ " --listen, -L PORT Listen on PORT\n"
+ " --host, -H HOSTNAME Bind to HOSTNAME (default *)\n"
+ " -4|-6 Force IPv4 or IPv6 for --listen\n"
+ " --background, -b Daemonize\n"
#endif
- " --readonly, -R Read-only mode\n");
+ " --readonly, -R Read-only mode\n");
exit(0);
}
/* display version number and terminate */
static void attribute((noreturn)) version(void) {
- xprintf("Green End SFTP server version %s\n", VERSION);
+ sftp_xprintf("Green End SFTP server version %s\n", VERSION);
exit(0);
}
@@ -150,7 +146,9 @@ static uint32_t sftp_init(struct sftpjob *job) {
return SSH_FX_FAILURE;
pcheck(sftp_parse_uint32(job, &version));
switch(version) {
- case 0: case 1: case 2:
+ case 0:
+ case 1:
+ case 2:
return SSH_FX_OP_UNSUPPORTED;
case 3:
protocol = &sftp_v3;
@@ -188,17 +186,15 @@ static uint32_t sftp_init(struct sftpjob *job) {
/* draft-ietf-secsh-filexfer-05.txt 4.4 */
sftp_send_string(job->worker, "supported");
offset = sftp_send_sub_begin(job->worker);
- sftp_send_uint32(job->worker, (SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_PERMISSIONS
- |SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME
- |SSH_FILEXFER_ATTR_OWNERGROUP
- |SSH_FILEXFER_ATTR_SUBSECOND_TIMES));
- sftp_send_uint32(job->worker, 0); /* supported-attribute-bits */
- sftp_send_uint32(job->worker, (SSH_FXF_ACCESS_DISPOSITION
- |SSH_FXF_APPEND_DATA
- |SSH_FXF_APPEND_DATA_ATOMIC
- |SSH_FXF_TEXT_MODE));
+ sftp_send_uint32(
+ job->worker,
+ (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+ SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+ SSH_FILEXFER_ATTR_OWNERGROUP | SSH_FILEXFER_ATTR_SUBSECOND_TIMES));
+ sftp_send_uint32(job->worker, 0); /* supported-attribute-bits */
+ sftp_send_uint32(job->worker,
+ (SSH_FXF_ACCESS_DISPOSITION | SSH_FXF_APPEND_DATA |
+ SSH_FXF_APPEND_DATA_ATOMIC | SSH_FXF_TEXT_MODE));
sftp_send_uint32(job->worker, 0xFFFFFFFF);
/* If we send a non-0 max-read-size then we promise to return that many
* bytes if asked for it and to mean EOF or error if we return less.
@@ -218,29 +214,27 @@ static uint32_t sftp_init(struct sftpjob *job) {
/* draft-ietf-secsh-filexfer-13.txt 5.4 */
sftp_send_string(job->worker, "supported2");
offset = sftp_send_sub_begin(job->worker);
- sftp_send_uint32(job->worker, (SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_PERMISSIONS
- |SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME
- |SSH_FILEXFER_ATTR_OWNERGROUP
- |SSH_FILEXFER_ATTR_SUBSECOND_TIMES));
+ sftp_send_uint32(
+ job->worker,
+ (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+ SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+ SSH_FILEXFER_ATTR_OWNERGROUP | SSH_FILEXFER_ATTR_SUBSECOND_TIMES));
/* Note - the client is invited to only send these bits, rather than
* promised that we never send anything else. Therefore 'supported-' is a
* misnomer. In particular we will send SSH_FILEXFER_ATTR_CTIME but cannot
* set the ctime of files and so follow the SHOULD that tells us to reject
* attempts to do so. */
- sftp_send_uint32(job->worker, 0); /* supported-attribute-bits */
- sftp_send_uint32(job->worker, (SSH_FXF_ACCESS_DISPOSITION
- |SSH_FXF_APPEND_DATA
- |SSH_FXF_APPEND_DATA_ATOMIC
- |SSH_FXF_TEXT_MODE
- |SSH_FXF_NOFOLLOW
- |SSH_FXF_DELETE_ON_CLOSE)); /* supported-open-flags */
- sftp_send_uint32(job->worker, 0xFFFFFFFF); /* supported-access-mask */
- sftp_send_uint32(job->worker, 0); /* max-read-size - see above */
- sftp_send_uint16(job->worker, 1); /* supported-open-block-vector */
- sftp_send_uint16(job->worker, 1); /* supported-block-vector */
- sftp_send_uint32(job->worker, 0); /* attrib-extension-count */
+ sftp_send_uint32(job->worker, 0); /* supported-attribute-bits */
+ sftp_send_uint32(job->worker,
+ (SSH_FXF_ACCESS_DISPOSITION | SSH_FXF_APPEND_DATA |
+ SSH_FXF_APPEND_DATA_ATOMIC | SSH_FXF_TEXT_MODE |
+ SSH_FXF_NOFOLLOW |
+ SSH_FXF_DELETE_ON_CLOSE)); /* supported-open-flags */
+ sftp_send_uint32(job->worker, 0xFFFFFFFF); /* supported-access-mask */
+ sftp_send_uint32(job->worker, 0); /* max-read-size - see above */
+ sftp_send_uint16(job->worker, 1); /* supported-open-block-vector */
+ sftp_send_uint16(job->worker, 1); /* supported-block-vector */
+ sftp_send_uint32(job->worker, 0); /* attrib-extension-count */
/* attrib-extensions would go here */
sftp_send_uint32(job->worker, protocol->nextensions); /* extension-count */
for(n = 0; n < protocol->nextensions; ++n)
@@ -287,27 +281,24 @@ static uint32_t sftp_init(struct sftpjob *job) {
}
/** @brief Requests supported prior to initialization */
-static const struct sftpcmd sftppreinittab[] = {
- { SSH_FXP_INIT, sftp_init }
-};
+static const struct sftpcmd sftppreinittab[] = {{SSH_FXP_INIT, sftp_init}};
/** @brief Protocol supported prior to initialization
*
* Only @ref SSH_FXP_INIT is supported at first. */
-const struct sftpprotocol sftp_preinit = {
- sizeof sftppreinittab / sizeof (struct sftpcmd),
- sftppreinittab,
- 3,
- 0xFFFFFFFF, /* never used */
- SSH_FX_OP_UNSUPPORTED,
- 0,
- 0,
- 0,
- sftp_v3_encode,
- 0,
- 0,
- 0
-};
+const struct sftpprotocol sftp_preinit = {sizeof sftppreinittab /
+ sizeof(struct sftpcmd),
+ sftppreinittab,
+ 3,
+ 0xFFFFFFFF, /* never used */
+ SSH_FX_OP_UNSUPPORTED,
+ 0,
+ 0,
+ 0,
+ sftp_v3_encode,
+ 0,
+ 0,
+ 0};
/* Worker setup/teardown */
@@ -315,18 +306,16 @@ const struct sftpprotocol sftp_preinit = {
* @return Initialized worker state
*/
static void *worker_init(void) {
- struct worker *w = xmalloc(sizeof *w);
+ struct worker *w = sftp_xmalloc(sizeof *w);
- memset(w, 0, sizeof *w);
+ sftp_memset(w, 0, sizeof *w);
w->buffer = 0;
- if((w->utf8_to_local = iconv_open(local_encoding, "UTF-8"))
- == (iconv_t)-1)
- fatal("error calling iconv_open(%s,UTF-8): %s",
- local_encoding, strerror(errno));
- if((w->local_to_utf8 = iconv_open("UTF-8", local_encoding))
- == (iconv_t)-1)
- fatal("error calling iconv_open(UTF-8,%s): %s",
- local_encoding, strerror(errno));
+ if((w->utf8_to_local = iconv_open(local_encoding, "UTF-8")) == (iconv_t)-1)
+ sftp_fatal("error calling iconv_open(%s,UTF-8): %s", local_encoding,
+ strerror(errno));
+ if((w->local_to_utf8 = iconv_open("UTF-8", local_encoding)) == (iconv_t)-1)
+ sftp_fatal("error calling iconv_open(UTF-8,%s): %s", local_encoding,
+ strerror(errno));
return w;
}
@@ -355,7 +344,7 @@ static void process_sftpjob(void *jv, void *wdv, struct allocator *a) {
struct sftpjob *const job = jv;
int l, r, type = 0;
uint32_t status, rc;
-
+
job->a = a;
job->id = 0;
job->worker = wdv;
@@ -381,7 +370,7 @@ static void process_sftpjob(void *jv, void *wdv, struct allocator *a) {
while(l <= r) {
const int m = (l + r) / 2;
const int mtype = protocol->commands[m].type;
-
+
if(type < mtype)
r = m - 1;
else if(type > mtype)
@@ -393,8 +382,11 @@ static void process_sftpjob(void *jv, void *wdv, struct allocator *a) {
status = protocol->commands[m].handler(job);
/* Send a response if necessary */
switch(status) {
- case HANDLER_RESPONDED: break;
- default: sftp_send_status(job, status, 0); break;
+ case HANDLER_RESPONDED:
+ break;
+ default:
+ sftp_send_status(job, status, 0);
+ break;
}
goto done;
}
@@ -440,7 +432,7 @@ int main(int argc, char **argv) {
int daemonize = 0;
struct addrinfo hints;
- memset(&hints, 0, sizeof hints);
+ sftp_memset(&hints, 0, sizeof hints);
hints.ai_flags = AI_PASSIVE;
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
@@ -453,9 +445,9 @@ int main(int argc, char **argv) {
if(strstr(bn, "-debug")) {
const char *home = getenv("HOME");
- sftp_debugpath = xmalloc(strlen(home) + 40);
- sprintf((char *)sftp_debugpath, "%s/.gesftpserver.%ju",
- home, (uintmax_t)getpid());
+ sftp_debugpath = sftp_xmalloc(strlen(home) + 40);
+ sprintf((char *)sftp_debugpath, "%s/.gesftpserver.%ju", home,
+ (uintmax_t)getpid());
sftp_debugging = 1;
}
/* Run in readonly mode */
@@ -465,31 +457,54 @@ int main(int argc, char **argv) {
/* We need I18N support for filename encoding */
setlocale(LC_CTYPE, "");
local_encoding = nl_langinfo(CODESET);
-
- while((n = getopt_long(argc, argv, "hVdD:r:u:H:L:b46R",
- options, 0)) >= 0) {
+
+ while((n = getopt_long(argc, argv, "hVdD:r:u:H:L:b46R", options, 0)) >= 0) {
switch(n) {
- case 'h': help();
- case 'V': version();
- case 'd': sftp_debugging = 1; break;
- case 'D': sftp_debugging = 1; sftp_debugpath = optarg; break;
+ case 'h':
+ help();
+ case 'V':
+ version();
+ case 'd':
+ sftp_debugging = 1;
+ break;
+ case 'D':
+ sftp_debugging = 1;
+ sftp_debugpath = optarg;
+ break;
#if DAEMON
- case 'r': root = optarg; break;
- case 'u': user = optarg; break;
- case 'H': host = optarg; break;
- case 'L': port = optarg; break;
- case 'b': daemonize = 1; break;
- case '4': hints.ai_family = PF_INET; break;
- case '6': hints.ai_family = PF_INET6; break;
+ case 'r':
+ root = optarg;
+ break;
+ case 'u':
+ user = optarg;
+ break;
+ case 'H':
+ host = optarg;
+ break;
+ case 'L':
+ port = optarg;
+ break;
+ case 'b':
+ daemonize = 1;
+ break;
+ case '4':
+ hints.ai_family = PF_INET;
+ break;
+ case '6':
+ hints.ai_family = PF_INET6;
+ break;
#endif
- case 'R': readonly = 1; break;
- default: exit(1);
+ case 'R':
+ readonly = 1;
+ break;
+ default:
+ exit(1);
}
}
#if DAEMON
if(daemonize && !port)
- fatal("--background requires --port");
+ sftp_fatal("--background requires --port");
#endif
/* If writes to the client fail then we'll get EPIPE. Arguably it might
@@ -510,16 +525,16 @@ int main(int argc, char **argv) {
#if HAVE_PRCTL
if(prctl(PR_SET_DUMPABLE, 0L) < 0)
- fatal("error calling prctl: %s", strerror(errno));
+ sftp_fatal("error calling prctl: %s", strerror(errno));
#endif
#if DAEMON
if(user) {
/* Look up the user */
if(!(pw = getpwnam(user)))
- fatal("no such user as %s", user);
+ sftp_fatal("no such user as %s", user);
if(initgroups(user, pw->pw_gid))
- fatal("error calling initgroups: %s", strerror(errno));
+ sftp_fatal("error calling initgroups: %s", strerror(errno));
}
if(port) {
@@ -532,60 +547,59 @@ int main(int argc, char **argv) {
sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask);
if(sigaction(SIGCHLD, &sa, 0) < 0)
- fatal("error calling sigaction: %s", strerror(errno));
+ sftp_fatal("error calling sigaction: %s", strerror(errno));
if((rc = getaddrinfo(host, port, &hints, &res))) {
if(host)
- fatal("error resolving host %s port %s: %s",
- host, port, gai_strerror(rc));
+ sftp_fatal("error resolving host %s port %s: %s", host, port,
+ gai_strerror(rc));
else
- fatal("error resolving port %s: %s",
- port, gai_strerror(rc));
+ sftp_fatal("error resolving port %s: %s", port, gai_strerror(rc));
}
- if((listenfd = socket(res->ai_family, res->ai_socktype,
- res->ai_protocol)) < 0)
- fatal("error calling socket: %s", strerror(errno));
- if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0)
- fatal("error calling setsockopt: %s", strerror(errno));
+ if((listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) <
+ 0)
+ sftp_fatal("error calling socket: %s", strerror(errno));
+ if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0)
+ sftp_fatal("error calling setsockopt: %s", strerror(errno));
if(bind(listenfd, res->ai_addr, res->ai_addrlen) < 0)
- fatal("error calling socket: %s", strerror(errno));
+ sftp_fatal("error calling socket: %s", strerror(errno));
if(listen(listenfd, SOMAXCONN) < 0)
- fatal("error calling listen: %s", strerror(errno));
+ sftp_fatal("error calling listen: %s", strerror(errno));
} else if(host)
- fatal("--host makes no sense without --port");
+ sftp_fatal("--host makes no sense without --port");
if((cd = iconv_open(local_encoding, "UTF-8")) == (iconv_t)-1)
- fatal("error calling iconv_open(%s,UTF-8): %s",
- local_encoding, strerror(errno));
+ sftp_fatal("error calling iconv_open(%s,UTF-8): %s", local_encoding,
+ strerror(errno));
iconv_close(cd);
if((cd = iconv_open("UTF-8", local_encoding)) == (iconv_t)-1)
- fatal("error calling iconv_open(UTF-8, %s): %s",
- local_encoding, strerror(errno));
+ sftp_fatal("error calling iconv_open(UTF-8, %s): %s", local_encoding,
+ strerror(errno));
iconv_close(cd);
-
+
if(root) {
/* Enter our chroot */
if(chdir(root) < 0)
- fatal("error calling chdir %s: %s", root, strerror(errno));
+ sftp_fatal("error calling chdir %s: %s", root, strerror(errno));
if(chroot(".") < 0)
- fatal("error calling chroot: %s", strerror(errno));
+ sftp_fatal("error calling chroot: %s", strerror(errno));
}
if(user) {
/* Become the right user */
assert(pw != 0);
if(setgid(pw->pw_gid) < 0)
- fatal("error calling setgid: %s", strerror(errno));
+ sftp_fatal("error calling setgid: %s", strerror(errno));
if(setuid(pw->pw_uid) < 0)
- fatal("error calling setuid: %s", strerror(errno));
+ sftp_fatal("error calling setuid: %s", strerror(errno));
if(setuid(0) >= 0)
- fatal("setuid(0) unexpectedly succeeded");
+ sftp_fatal("setuid(0) unexpectedly succeeded");
}
-
+
if(daemonize) {
openlog(bn, LOG_PID, LOG_FTP);
- log_syslog = 1;
+ sftp_log_syslog = 1;
if(daemon(0, 0) < 0)
- fatal("error calling daemon: %s", strerror(errno));
+ sftp_fatal("error calling daemon: %s", strerror(errno));
}
if(!port) {
@@ -600,7 +614,7 @@ int main(int argc, char **argv) {
} addr;
socklen_t addrlen = sizeof addr;
int fd;
-
+
if((fd = accept(listenfd, &addr.sa, &addrlen)) >= 0) {
switch(fork()) {
case -1:
@@ -610,14 +624,12 @@ int main(int argc, char **argv) {
sleep(60);
break;
case 0:
- forked();
- signal(SIGCHLD, SIG_DFL); /* XXX */
- if(dup2(fd, 0) < 0
- || dup2(fd, 1) < 0)
- fatal("dup2: %s", strerror(errno));
- if(close(fd) < 0
- || close(listenfd) < 0)
- fatal("close: %s", strerror(errno));
+ sftp_forked();
+ signal(SIGCHLD, SIG_DFL); /* XXX */
+ if(dup2(fd, 0) < 0 || dup2(fd, 1) < 0)
+ sftp_fatal("dup2: %s", strerror(errno));
+ if(close(fd) < 0 || close(listenfd) < 0)
+ sftp_fatal("close: %s", strerror(errno));
sftp_service();
_exit(0);
default:
@@ -641,21 +653,22 @@ static void sftp_service(void) {
uint32_t len;
struct sftpjob *job;
struct allocator a;
- void *const wdv = worker_init();
+ void *const wdv = worker_init();
D(("gesftpserver %s starting up", VERSION));
/* draft -13 s7.6 "The server SHOULD NOT apply a 'umask' to the mode
* bits". */
umask(0);
- while(!do_read(0, &len, sizeof len)) {
- job = xmalloc(sizeof *job);
+ while(sftp_state_get() != sftp_state_stop &&
+ !sftp_xread(0, &len, sizeof len)) {
+ job = sftp_xmalloc(sizeof *job);
job->len = ntohl(len);
if(!job->len || job->len > MAXREQUEST)
- fatal("invalid request size");
- job->data = xmalloc(job->len);
- if(do_read(0, job->data, job->len))
+ sftp_fatal("invalid request size");
+ job->data = sftp_xmalloc(job->len);
+ if(sftp_xread(0, job->data, job->len))
/* Job data missing or truncated - the other end is not playing the game
* fair so we give up straight away */
- fatal("read error: unexpected eof");
+ sftp_fatal("read error: unexpected eof");
if(sftp_debugging) {
D(("request:"));
sftp_debug_hexdump(job->data, job->len);
diff --git a/sftpserver.h b/sftpserver.h
index b3d7657..2ad6eb3 100644
--- a/sftpserver.h
+++ b/sftpserver.h
@@ -21,50 +21,48 @@
/** @file sftpserver.h @brief SFTP server parameters and common declarations */
#ifndef SFTPSERVER_H
-#define SFTPSERVER_H
+# define SFTPSERVER_H
-#include "sftpcommon.h"
+# include "sftpcommon.h"
-#include <sys/types.h>
+# include <sys/types.h>
-#ifndef MAXNAMES
+# ifndef MAXNAMES
/** @brief Maximum size of an @ref SSH_FXP_READDIR response */
-# define MAXNAMES 32
-#endif
+# define MAXNAMES 32
+# endif
-#ifndef MAXHANDLES
+# ifndef MAXHANDLES
/** @brief Maximum number of concurrent handles */
-# define MAXHANDLES 128
-#endif
+# define MAXHANDLES 128
+# endif
-#ifndef MAXREAD
+# ifndef MAXREAD
/** @brief Maximum read size */
-# define MAXREAD 1048576
-#endif
+# define MAXREAD 1048576
+# endif
-#ifndef MAXREQUEST
+# ifndef MAXREQUEST
/** @brief Maximum request size */
-# define MAXREQUEST 1048576
-#endif
+# define MAXREQUEST 1048576
+# endif
-#ifndef DEFAULT_PERMISSIONS
+# ifndef DEFAULT_PERMISSIONS
/** @brief Default file permissions */
-# define DEFAULT_PERMISSIONS 0755
-#endif
+# define DEFAULT_PERMISSIONS 0755
+# endif
-#ifndef NTHREADS
+# ifndef NTHREADS
/** @brief Number of threads */
-# define NTHREADS 4
-#endif
+# define NTHREADS 4
+# endif
/** @brief Send an @ref SSH_FXP_STATUS message
* @param job Job
* @param status Status code
* @param msg Human-readable message
*/
-void sftp_send_status(struct sftpjob *job,
- uint32_t status,
- const char *msg);
+void sftp_send_status(struct sftpjob *job, uint32_t status, const char *msg);
/** @brief @ref SSH_FXP_INIT stub for use after initialization
* @param job Job
@@ -160,8 +158,8 @@ uint32_t sftp_vany_extended(struct sftpjob *job);
*
* This is for protocols 4 and above.
*/
-void sftp_v456_sendnames(struct sftpjob *job,
- int nnames, const struct sftpattr *names);
+void sftp_v456_sendnames(struct sftpjob *job, int nnames,
+ const struct sftpattr *names);
/** @brief Send file attributes
* @param job Job
@@ -170,8 +168,7 @@ void sftp_v456_sendnames(struct sftpjob *job,
*
* This is for protocols 4 and above.
*/
-void sftp_v456_sendattrs(struct sftpjob *job,
- const struct sftpattr *attrs);
+void sftp_v456_sendattrs(struct sftpjob *job, const struct sftpattr *attrs);
/** @brief Parse file attributes
* @param job Job
diff --git a/stat.c b/stat.c
index bb36430..def7853 100644
--- a/stat.c
+++ b/stat.c
@@ -35,40 +35,52 @@
#include <sys/time.h>
#include <unistd.h>
-#if ! HAVE_FUTIMES
+#if !HAVE_FUTIMES
int futimes(int fd, const struct timeval *times);
#endif
-void sftp_stat_to_attrs(struct allocator *a,
- const struct stat *sb, struct sftpattr *attrs,
- uint32_t flags, const char *path) {
- memset(attrs, 0, sizeof *attrs);
- attrs->valid = (SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_PERMISSIONS
- |SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME
- |SSH_FILEXFER_ATTR_UIDGID
- |SSH_FILEXFER_ATTR_ALLOCATION_SIZE
- |SSH_FILEXFER_ATTR_LINK_COUNT
- |SSH_FILEXFER_ATTR_CTIME
- |SSH_FILEXFER_ATTR_BITS);
+void sftp_stat_to_attrs(struct allocator *a, const struct stat *sb,
+ struct sftpattr *attrs, uint32_t flags,
+ const char *path) {
+ sftp_memset(attrs, 0, sizeof *attrs);
+ attrs->valid = (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+ SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+ SSH_FILEXFER_ATTR_UIDGID | SSH_FILEXFER_ATTR_ALLOCATION_SIZE |
+ SSH_FILEXFER_ATTR_LINK_COUNT | SSH_FILEXFER_ATTR_CTIME |
+ SSH_FILEXFER_ATTR_BITS);
switch(sb->st_mode & S_IFMT) {
- case S_IFIFO: attrs->type = SSH_FILEXFER_TYPE_FIFO; break;
- case S_IFCHR: attrs->type = SSH_FILEXFER_TYPE_CHAR_DEVICE; break;
- case S_IFDIR: attrs->type = SSH_FILEXFER_TYPE_DIRECTORY; break;
- case S_IFBLK: attrs->type = SSH_FILEXFER_TYPE_BLOCK_DEVICE; break;
- case S_IFREG: attrs->type = SSH_FILEXFER_TYPE_REGULAR; break;
- case S_IFLNK: attrs->type = SSH_FILEXFER_TYPE_SYMLINK; break;
- case S_IFSOCK: attrs->type = SSH_FILEXFER_TYPE_SOCKET; break;
- default: attrs->type = SSH_FILEXFER_TYPE_SPECIAL; break;
+ case S_IFIFO:
+ attrs->type = SSH_FILEXFER_TYPE_FIFO;
+ break;
+ case S_IFCHR:
+ attrs->type = SSH_FILEXFER_TYPE_CHAR_DEVICE;
+ break;
+ case S_IFDIR:
+ attrs->type = SSH_FILEXFER_TYPE_DIRECTORY;
+ break;
+ case S_IFBLK:
+ attrs->type = SSH_FILEXFER_TYPE_BLOCK_DEVICE;
+ break;
+ case S_IFREG:
+ attrs->type = SSH_FILEXFER_TYPE_REGULAR;
+ break;
+ case S_IFLNK:
+ attrs->type = SSH_FILEXFER_TYPE_SYMLINK;
+ break;
+ case S_IFSOCK:
+ attrs->type = SSH_FILEXFER_TYPE_SOCKET;
+ break;
+ default:
+ attrs->type = SSH_FILEXFER_TYPE_SPECIAL;
+ break;
}
attrs->size = sb->st_size;
/* The cast ensures we don't do the multiply in a small word and overflow */
attrs->allocation_size = (uint64_t)sb->st_blksize * sb->st_blocks;
/* Only look up owner/group info if wanted */
- if((flags & SSH_FILEXFER_ATTR_OWNERGROUP)
- && (attrs->owner = sftp_uid2name(a, sb->st_uid))
- && (attrs->group = sftp_gid2name(a, sb->st_gid)))
+ if((flags & SSH_FILEXFER_ATTR_OWNERGROUP) &&
+ (attrs->owner = sftp_uid2name(a, sb->st_uid)) &&
+ (attrs->group = sftp_gid2name(a, sb->st_gid)))
attrs->valid |= SSH_FILEXFER_ATTR_OWNERGROUP;
attrs->uid = sb->st_uid;
attrs->gid = sb->st_gid;
@@ -77,12 +89,9 @@ void sftp_stat_to_attrs(struct allocator *a,
attrs->mtime.seconds = sb->st_mtime;
attrs->ctime.seconds = sb->st_ctime;
#if HAVE_STAT_TIMESPEC
- if(sb->st_atimespec.tv_nsec >= 0
- && sb->st_atimespec.tv_nsec < 1000000000
- && sb->st_mtimespec.tv_nsec >= 0
- && sb->st_mtimespec.tv_nsec < 1000000000
- && sb->st_ctimespec.tv_nsec >= 0
- && sb->st_ctimespec.tv_nsec < 1000000000) {
+ if(sb->st_atimespec.tv_nsec >= 0 && sb->st_atimespec.tv_nsec < 1000000000 &&
+ sb->st_mtimespec.tv_nsec >= 0 && sb->st_mtimespec.tv_nsec < 1000000000 &&
+ sb->st_ctimespec.tv_nsec >= 0 && sb->st_ctimespec.tv_nsec < 1000000000) {
/* Only send subsecond times if they are in range */
attrs->atime.nanoseconds = sb->st_atimespec.tv_nsec;
attrs->mtime.nanoseconds = sb->st_mtimespec.tv_nsec;
@@ -114,24 +123,21 @@ void sftp_stat_to_attrs(struct allocator *a,
static const struct {
uint32_t bit;
const char *description;
-} attr_bits[] = {
- { SSH_FILEXFER_ATTR_FLAGS_READONLY, "ro" },
- { SSH_FILEXFER_ATTR_FLAGS_SYSTEM, "sys" },
- { SSH_FILEXFER_ATTR_FLAGS_HIDDEN, "hide" },
- { SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE, "ci"},
- { SSH_FILEXFER_ATTR_FLAGS_ARCHIVE, "arc" },
- { SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED, "enc" },
- { SSH_FILEXFER_ATTR_FLAGS_COMPRESSED, "comp" },
- { SSH_FILEXFER_ATTR_FLAGS_SPARSE, "sp" },
- { SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY, "app" },
- { SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE, "imm" },
- { SSH_FILEXFER_ATTR_FLAGS_SYNC, "sync" },
- { SSH_FILEXFER_ATTR_FLAGS_TRANSLATION_ERR, "trans" }
-};
-
-const char *sftp_format_attr(struct allocator *a,
- const struct sftpattr *attrs, int thisyear,
- unsigned long flags) {
+} attr_bits[] = {{SSH_FILEXFER_ATTR_FLAGS_READONLY, "ro"},
+ {SSH_FILEXFER_ATTR_FLAGS_SYSTEM, "sys"},
+ {SSH_FILEXFER_ATTR_FLAGS_HIDDEN, "hide"},
+ {SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE, "ci"},
+ {SSH_FILEXFER_ATTR_FLAGS_ARCHIVE, "arc"},
+ {SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED, "enc"},
+ {SSH_FILEXFER_ATTR_FLAGS_COMPRESSED, "comp"},
+ {SSH_FILEXFER_ATTR_FLAGS_SPARSE, "sp"},
+ {SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY, "app"},
+ {SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE, "imm"},
+ {SSH_FILEXFER_ATTR_FLAGS_SYNC, "sync"},
+ {SSH_FILEXFER_ATTR_FLAGS_TRANSLATION_ERR, "trans"}};
+
+const char *sftp_format_attr(struct allocator *a, const struct sftpattr *attrs,
+ int thisyear, unsigned long flags) {
char perms[64], linkcount[64], size[64], date[64], nowner[64], ngroup[64];
char *formatted, *p, *bits;
size_t nbits;
@@ -146,44 +152,68 @@ const char *sftp_format_attr(struct allocator *a,
*p++ = (attrs->permissions & 00400) ? 'r' : '-';
*p++ = (attrs->permissions & 00200) ? 'w' : '-';
switch(attrs->permissions & 04100) {
- case 00000: *p++ = '-'; break;
- case 00100: *p++ = 'x'; break;
- case 04000: *p++ = 'S'; break;
- case 04100: *p++ = 's'; break;
+ case 00000:
+ *p++ = '-';
+ break;
+ case 00100:
+ *p++ = 'x';
+ break;
+ case 04000:
+ *p++ = 'S';
+ break;
+ case 04100:
+ *p++ = 's';
+ break;
}
*p++ = (attrs->permissions & 00040) ? 'r' : '-';
*p++ = (attrs->permissions & 00020) ? 'w' : '-';
switch(attrs->permissions & 02010) {
- case 00000: *p++ = '-'; break;
- case 00010: *p++ = 'x'; break;
- case 02000: *p++ = 'S'; break;
- case 02010: *p++ = 's'; break;
+ case 00000:
+ *p++ = '-';
+ break;
+ case 00010:
+ *p++ = 'x';
+ break;
+ case 02000:
+ *p++ = 'S';
+ break;
+ case 02010:
+ *p++ = 's';
+ break;
}
*p++ = (attrs->permissions & 00004) ? 'r' : '-';
*p++ = (attrs->permissions & 00002) ? 'w' : '-';
switch(attrs->permissions & 01001) {
- case 00000: *p++ = '-'; break;
- case 00001: *p++ = 'x'; break;
- case 01000: *p++ = 'T'; break;
- case 01001: *p++ = 't'; break;
+ case 00000:
+ *p++ = '-';
+ break;
+ case 00001:
+ *p++ = 'x';
+ break;
+ case 01000:
+ *p++ = 'T';
+ break;
+ case 01001:
+ *p++ = 't';
+ break;
}
*p = 0;
} else
strcpy(p, "?????????");
/* link count */
if(attrs->valid & SSH_FILEXFER_ATTR_LINK_COUNT)
- sprintf(linkcount, "%"PRIu32, attrs->link_count);
+ sprintf(linkcount, "%" PRIu32, attrs->link_count);
else
strcpy(linkcount, "?");
/* size */
if(attrs->valid & SSH_FILEXFER_ATTR_SIZE)
- sprintf(size, "%"PRIu64, attrs->size);
+ sprintf(size, "%" PRIu64, attrs->size);
else
strcpy(size, "?");
/* ownership */
if(attrs->valid & SSH_FILEXFER_ATTR_UIDGID) {
- sprintf(nowner, "%"PRIu32, attrs->uid);
- sprintf(ngroup, "%"PRIu32, attrs->gid);
+ sprintf(nowner, "%" PRIu32, attrs->uid);
+ sprintf(ngroup, "%" PRIu32, attrs->gid);
}
owner = group = "?";
if(flags & FORMAT_PREFER_NUMERIC_UID) {
@@ -219,41 +249,38 @@ const char *sftp_format_attr(struct allocator *a,
/* attribute bits */
bits = NULL;
nbits = 0;
- if(flags & FORMAT_ATTRS
- && (attrs->valid & SSH_FILEXFER_ATTR_BITS)
- && attrs->attrib_bits) {
- bits = append(a, bits, &nbits, "[");
+ if(flags & FORMAT_ATTRS && (attrs->valid & SSH_FILEXFER_ATTR_BITS) &&
+ attrs->attrib_bits) {
+ bits = sftp_str_append(a, bits, &nbits, "[");
for(n = 0; n < sizeof attr_bits / sizeof *attr_bits; ++n) {
if(attrs->attrib_bits & attr_bits[n].bit) {
if(bits[1])
- bits = append(a, bits, &nbits, ",");
- bits = append(a, bits, &nbits, attr_bits[n].description);
+ bits = sftp_str_append(a, bits, &nbits, ",");
+ bits = sftp_str_append(a, bits, &nbits, attr_bits[n].description);
}
}
- bits = append(a, bits, &nbits, "]");
+ bits = sftp_str_append(a, bits, &nbits, "]");
}
/* Format the result */
formatted = sftp_alloc(a, 80 + strlen(attrs->name));
/* The draft is pretty specific about field widths */
sprintf(formatted, "%10.10s %3.3s %-8.8s %-8.8s %8.8s %12.12s %s%s%s%s%s",
- perms, linkcount, owner, group,
- size, date, attrs->name,
- attrs->target ? " -> " : "",
- attrs->target ? attrs->target : "",
- bits ? " " : "",
- bits ? bits : "");
+ perms, linkcount, owner, group, size, date, attrs->name,
+ attrs->target ? " -> " : "", attrs->target ? attrs->target : "",
+ bits ? " " : "", bits ? bits : "");
return formatted;
}
-uint32_t sftp_normalize_ownergroup(struct allocator *a, struct sftpattr *attrs) {
+uint32_t sftp_normalize_ownergroup(struct allocator *a,
+ struct sftpattr *attrs) {
uint32_t rc = SSH_FX_OK;
- switch(attrs->valid & (SSH_FILEXFER_ATTR_UIDGID
- |SSH_FILEXFER_ATTR_OWNERGROUP)) {
+ switch(attrs->valid &
+ (SSH_FILEXFER_ATTR_UIDGID | SSH_FILEXFER_ATTR_OWNERGROUP)) {
case SSH_FILEXFER_ATTR_UIDGID:
- if((attrs->owner = sftp_uid2name(a, attrs->uid))
- && (attrs->group = sftp_gid2name(a, attrs->gid)))
+ if((attrs->owner = sftp_uid2name(a, attrs->uid)) &&
+ (attrs->group = sftp_gid2name(a, attrs->gid)))
attrs->valid |= SSH_FILEXFER_ATTR_OWNERGROUP;
break;
case SSH_FILEXFER_ATTR_OWNERGROUP:
@@ -310,16 +337,19 @@ struct sftp_set_status_callbacks {
/* Horrendous ugliness for SETSTAT/FSETSTAT */
#if HAVE_STAT_TIMESPEC
/** @brief Helper macro to set fractional part of timestamps */
-#define SET_STATUS_NANOSEC do { \
- times[0].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_ACCESSTIME) \
- ? (long)attrs.atime.nanoseconds \
- : current.st_atimespec.tv_nsec) / 1000; \
- times[1].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_MODIFYTIME) \
- ? (long)attrs.mtime.nanoseconds \
- : current.st_mtimespec.tv_nsec) / 1000; \
-} while(0)
+# define SET_STATUS_NANOSEC \
+ do { \
+ times[0].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_ACCESSTIME) \
+ ? (long)attrs.atime.nanoseconds \
+ : current.st_atimespec.tv_nsec) / \
+ 1000; \
+ times[1].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_MODIFYTIME) \
+ ? (long)attrs.mtime.nanoseconds \
+ : current.st_mtimespec.tv_nsec) / \
+ 1000; \
+ } while(0)
#else
-#define SET_STATUS_NANOSEC ((void)0)
+# define SET_STATUS_NANOSEC ((void)0)
#endif
/** @brief Implementation of sftp_set_status() and sftp_set_fstatus()
@@ -330,11 +360,10 @@ struct sftp_set_status_callbacks {
* @param whyp Where to store error string, or a null pointer
* @return 0 on success or an error code on failure
*/
-static uint32_t do_sftp_set_status(struct allocator *a,
- const void *what,
- const struct sftpattr *attrsp,
- const struct sftp_set_status_callbacks *cb,
- const char **whyp) {
+static uint32_t do_sftp_set_status(struct allocator *a, const void *what,
+ const struct sftpattr *attrsp,
+ const struct sftp_set_status_callbacks *cb,
+ const char **whyp) {
struct timeval times[2];
struct stat current;
struct sftpattr attrs = *attrsp;
@@ -343,33 +372,31 @@ static uint32_t do_sftp_set_status(struct allocator *a,
if(!whyp)
whyp = &why;
*whyp = 0;
- if((attrs.valid & (SSH_FILEXFER_ATTR_SIZE|SSH_FILEXFER_ATTR_ALLOCATION_SIZE))
- == (SSH_FILEXFER_ATTR_SIZE|SSH_FILEXFER_ATTR_ALLOCATION_SIZE)
- && attrs.allocation_size < attrs.size) {
+ if((attrs.valid &
+ (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_ALLOCATION_SIZE)) ==
+ (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_ALLOCATION_SIZE) &&
+ attrs.allocation_size < attrs.size) {
/* This is a MUST, e.g. draft -13 s7.4. We honor it even though we don't
* honor allocation-size. */
*whyp = "size exceeds allocation-size";
return SSH_FX_INVALID_PARAMETER;
}
- if(attrs.valid & (SSH_FILEXFER_ATTR_LINK_COUNT
- |SSH_FILEXFER_ATTR_TEXT_HINT))
+ if(attrs.valid & (SSH_FILEXFER_ATTR_LINK_COUNT | SSH_FILEXFER_ATTR_TEXT_HINT))
/* Client has violated a MUST NOT */
return SSH_FX_INVALID_PARAMETER;
- if((attrs.valid & (SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_PERMISSIONS
- |SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME
- |SSH_FILEXFER_ATTR_UIDGID
- |SSH_FILEXFER_ATTR_OWNERGROUP
- |SSH_FILEXFER_ATTR_SUBSECOND_TIMES
- |SSH_FILEXFER_ATTR_ALLOCATION_SIZE)) != attrs.valid) {
+ if((attrs.valid &
+ (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+ SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+ SSH_FILEXFER_ATTR_UIDGID | SSH_FILEXFER_ATTR_OWNERGROUP |
+ SSH_FILEXFER_ATTR_SUBSECOND_TIMES |
+ SSH_FILEXFER_ATTR_ALLOCATION_SIZE)) != attrs.valid) {
/* SHOULD not change any attributes if we cannot perform as required. We
* have a SHOULD which allows us to ignore allocation-size. */
*whyp = "unsupported flags";
return SSH_FX_OP_UNSUPPORTED;
}
if(attrs.valid & SSH_FILEXFER_ATTR_SIZE) {
- D(("...truncate to %"PRIu64, attrs.size));
+ D(("...truncate to %" PRIu64, attrs.size));
if(cb->do_truncate(what, attrs.size) < 0) {
*whyp = "truncate";
return HANDLER_ERRNO;
@@ -377,7 +404,7 @@ static uint32_t do_sftp_set_status(struct allocator *a,
}
sftp_normalize_ownergroup(a, &attrs);
if(attrs.valid & SSH_FILEXFER_ATTR_UIDGID) {
- D(("...chown to %"PRId32"/%"PRId32, attrs.uid, attrs.gid));
+ D(("...chown to %" PRId32 "/%" PRId32, attrs.uid, attrs.gid));
if(cb->do_chown(what, attrs.uid, attrs.gid) < 0) {
*whyp = "chown";
return HANDLER_ERRNO;
@@ -391,35 +418,35 @@ static uint32_t do_sftp_set_status(struct allocator *a,
return HANDLER_ERRNO;
}
}
- if(attrs.valid & (SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME)) {
+ if(attrs.valid &
+ (SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME)) {
if(cb->do_stat(what, ¤t) < 0) {
D(("cannot stat"));
*whyp = "stat";
return HANDLER_ERRNO;
}
- memset(times, 0, sizeof times);
+ sftp_memset(times, 0, sizeof times);
times[0].tv_sec = ((attrs.valid & SSH_FILEXFER_ATTR_ACCESSTIME)
- ? (time_t)attrs.atime.seconds
- : current.st_atime);
+ ? (time_t)attrs.atime.seconds
+ : current.st_atime);
times[1].tv_sec = ((attrs.valid & SSH_FILEXFER_ATTR_MODIFYTIME)
- ? (time_t)attrs.mtime.seconds
- : current.st_mtime);
+ ? (time_t)attrs.mtime.seconds
+ : current.st_mtime);
#if HAVE_STAT_TIMESPEC
if(attrs.valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) {
times[0].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_ACCESSTIME)
- ? (long)attrs.atime.nanoseconds
- : current.st_atimespec.tv_nsec) / 1000;
+ ? (long)attrs.atime.nanoseconds
+ : current.st_atimespec.tv_nsec) /
+ 1000;
times[1].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_MODIFYTIME)
- ? (long)attrs.mtime.nanoseconds
- : current.st_mtimespec.tv_nsec) / 1000;
+ ? (long)attrs.mtime.nanoseconds
+ : current.st_mtimespec.tv_nsec) /
+ 1000;
}
#endif
D(("...utimes to atime %lu.%06lu mtime %lu.%06lu",
- (unsigned long)times[0].tv_sec,
- (unsigned long)times[0].tv_usec,
- (unsigned long)times[1].tv_sec,
- (unsigned long)times[1].tv_usec));
+ (unsigned long)times[0].tv_sec, (unsigned long)times[0].tv_usec,
+ (unsigned long)times[1].tv_sec, (unsigned long)times[1].tv_usec));
if(cb->do_utimes(what, times) < 0) {
*whyp = "utimes";
return HANDLER_ERRNO;
@@ -476,17 +503,10 @@ static int name_utimes(const void *what, struct timeval *tv) {
/** @brief Table of callbacks for sftp_set_status() */
static const struct sftp_set_status_callbacks name_callbacks = {
- name_truncate,
- name_chown,
- name_chmod,
- name_lstat,
- name_utimes
-};
+ name_truncate, name_chown, name_chmod, name_lstat, name_utimes};
-uint32_t sftp_set_status(struct allocator *a,
- const char *path,
- const struct sftpattr *attrsp,
- const char **whyp) {
+uint32_t sftp_set_status(struct allocator *a, const char *path,
+ const struct sftpattr *attrsp, const char **whyp) {
return do_sftp_set_status(a, path, attrsp, &name_callbacks, whyp);
}
@@ -538,17 +558,10 @@ static int fd_utimes(const void *what, struct timeval *tv) {
/** @brief Table of callbacks for sftp_set_fstatus() */
static const struct sftp_set_status_callbacks fd_callbacks = {
- fd_truncate,
- fd_chown,
- fd_chmod,
- fd_stat,
- fd_utimes
-};
+ fd_truncate, fd_chown, fd_chmod, fd_stat, fd_utimes};
-uint32_t sftp_set_fstatus(struct allocator *a,
- int fd,
- const struct sftpattr *attrsp,
- const char **whyp) {
+uint32_t sftp_set_fstatus(struct allocator *a, int fd,
+ const struct sftpattr *attrsp, const char **whyp) {
return do_sftp_set_status(a, &fd, attrsp, &fd_callbacks, whyp);
}
diff --git a/stat.h b/stat.h
index cb9e1ec..c89969e 100644
--- a/stat.h
+++ b/stat.h
@@ -21,7 +21,7 @@
/** @file stat.h @brief SFTP attribute support interface */
#ifndef STAT_H
-#define STAT_H
+# define STAT_H
/** @brief Produce a human-readable representation of file attributes
* @param a Allocator
@@ -35,37 +35,35 @@
* - @ref FORMAT_PREFER_LOCALTIME
* - @ref FORMAT_ATTRS
*/
-const char *sftp_format_attr(struct allocator *a,
- const struct sftpattr *attrs, int thisyear,
- unsigned long flags);
+const char *sftp_format_attr(struct allocator *a, const struct sftpattr *attrs,
+ int thisyear, unsigned long flags);
/** @brief User numeric instead of named user and group IDs
*
* See sftp_format_attr().
*/
-#define FORMAT_PREFER_NUMERIC_UID 0x00000001
+# define FORMAT_PREFER_NUMERIC_UID 0x00000001
/** @brief Use local time instead of UTC
*
* See sftp_format_attr().
*/
-#define FORMAT_PREFER_LOCALTIME 0x00000002
+# define FORMAT_PREFER_LOCALTIME 0x00000002
/** @brief Include attribute bits
*
* See sftp_format_attr().
*/
-#define FORMAT_ATTRS 0x00000004
+# define FORMAT_ATTRS 0x00000004
/** @brief Fill in missing owner/group attributes
* @param a Allocator
* @param attrs Attributes
- * @return 0 on success, status code on error
+ * @return 0 on success, status code on error
*
* If exactly one of @ref SSH_FILEXFER_ATTR_UIDGID and @ref
* SSH_FILEXFER_ATTR_OWNERGROUP is present then attempt to fill in the other.
*/
-uint32_t sftp_normalize_ownergroup(struct allocator *a,
- struct sftpattr *attrs);
+uint32_t sftp_normalize_ownergroup(struct allocator *a, struct sftpattr *attrs);
/** @brief Set the attributes on a path name
* @param a Allocator
@@ -74,10 +72,8 @@ uint32_t sftp_normalize_ownergroup(struct allocator *a,
* @param whyp Where to store error string, or a null pointer
* @return 0 on success or an error code on failure
*/
-uint32_t sftp_set_status(struct allocator *a,
- const char *path,
- const struct sftpattr *attrs,
- const char **whyp);
+uint32_t sftp_set_status(struct allocator *a, const char *path,
+ const struct sftpattr *attrs, const char **whyp);
/** @brief Set the attributes on an open file
* @param a Allocator
@@ -86,10 +82,8 @@ uint32_t sftp_set_status(struct allocator *a,
* @param whyp Where to store error string, or a null pointer
* @return 0 on success or an error code on failure
*/
-uint32_t sftp_set_fstatus(struct allocator *a,
- int fd,
- const struct sftpattr *attrs,
- const char **whyp);
+uint32_t sftp_set_fstatus(struct allocator *a, int fd,
+ const struct sftpattr *attrs, const char **whyp);
/** @brief Convert @c stat() output to SFTP attributes
* @param a Allocator
@@ -103,12 +97,12 @@ uint32_t sftp_set_fstatus(struct allocator *a,
* filled in.
*
* @todo @ref SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE is not implemented.
- *
+ *
* @todo @ref SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE is not implemented.
*/
-void sftp_stat_to_attrs(struct allocator *a,
- const struct stat *sb, struct sftpattr *attrs,
- uint32_t flags, const char *path);
+void sftp_stat_to_attrs(struct allocator *a, const struct stat *sb,
+ struct sftpattr *attrs, uint32_t flags,
+ const char *path);
#endif /* STAT_H */
diff --git a/status.c b/status.c
index b3e9d5c..0e2af32 100644
--- a/status.c
+++ b/status.c
@@ -31,45 +31,76 @@
const char *status_to_string(uint32_t status) {
switch(status) {
- case SSH_FX_OK: return "OK";
- case SSH_FX_EOF: return "end of file";
- case SSH_FX_NO_SUCH_FILE: return "file does not exist";
- case SSH_FX_PERMISSION_DENIED: return "permission denied";
- case SSH_FX_FAILURE: return "operation failed";
- case SSH_FX_BAD_MESSAGE: return "badly encoded SFTP packet";
- case SSH_FX_NO_CONNECTION: return "no connection";
- case SSH_FX_CONNECTION_LOST: return "connection lost";
- case SSH_FX_OP_UNSUPPORTED: return "operation not supported";
- case SSH_FX_INVALID_HANDLE: return "invalid handle";
- case SSH_FX_NO_SUCH_PATH: return "path does not exist or is invalid";
- case SSH_FX_FILE_ALREADY_EXISTS: return "file already exists";
- case SSH_FX_WRITE_PROTECT: return "file is on read-only medium";
- case SSH_FX_NO_MEDIA: return "no medium in drive";
- case SSH_FX_NO_SPACE_ON_FILESYSTEM: return "no space on filesystem";
- case SSH_FX_QUOTA_EXCEEDED: return "quota exceeded";
- case SSH_FX_UNKNOWN_PRINCIPAL: return "unknown principal";
- case SSH_FX_LOCK_CONFLICT: return "file is locked";
- case SSH_FX_DIR_NOT_EMPTY: return "directory is not empty";
- case SSH_FX_NOT_A_DIRECTORY: return "file is not a directory";
- case SSH_FX_INVALID_FILENAME: return "invalid filename";
- case SSH_FX_LINK_LOOP: return "too many symbolic links";
- case SSH_FX_CANNOT_DELETE: return "file cannot be deleted";
- case SSH_FX_INVALID_PARAMETER: return "invalid parameter";
- case SSH_FX_FILE_IS_A_DIRECTORY: return "file is a directory";
- case SSH_FX_BYTE_RANGE_LOCK_CONFLICT: return "byte range is locked";
- case SSH_FX_BYTE_RANGE_LOCK_REFUSED: return "cannot lock byte range";
- case SSH_FX_DELETE_PENDING: return "file deletion pending";
- case SSH_FX_FILE_CORRUPT: return "file is corrupt";
- case SSH_FX_OWNER_INVALID: return "invalid owner";
- case SSH_FX_GROUP_INVALID: return "invalid group";
- case SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK: return "no such lock";
- default: return "unknown status";
+ case SSH_FX_OK:
+ return "OK";
+ case SSH_FX_EOF:
+ return "end of file";
+ case SSH_FX_NO_SUCH_FILE:
+ return "file does not exist";
+ case SSH_FX_PERMISSION_DENIED:
+ return "permission denied";
+ case SSH_FX_FAILURE:
+ return "operation failed";
+ case SSH_FX_BAD_MESSAGE:
+ return "badly encoded SFTP packet";
+ case SSH_FX_NO_CONNECTION:
+ return "no connection";
+ case SSH_FX_CONNECTION_LOST:
+ return "connection lost";
+ case SSH_FX_OP_UNSUPPORTED:
+ return "operation not supported";
+ case SSH_FX_INVALID_HANDLE:
+ return "invalid handle";
+ case SSH_FX_NO_SUCH_PATH:
+ return "path does not exist or is invalid";
+ case SSH_FX_FILE_ALREADY_EXISTS:
+ return "file already exists";
+ case SSH_FX_WRITE_PROTECT:
+ return "file is on read-only medium";
+ case SSH_FX_NO_MEDIA:
+ return "no medium in drive";
+ case SSH_FX_NO_SPACE_ON_FILESYSTEM:
+ return "no space on filesystem";
+ case SSH_FX_QUOTA_EXCEEDED:
+ return "quota exceeded";
+ case SSH_FX_UNKNOWN_PRINCIPAL:
+ return "unknown principal";
+ case SSH_FX_LOCK_CONFLICT:
+ return "file is locked";
+ case SSH_FX_DIR_NOT_EMPTY:
+ return "directory is not empty";
+ case SSH_FX_NOT_A_DIRECTORY:
+ return "file is not a directory";
+ case SSH_FX_INVALID_FILENAME:
+ return "invalid filename";
+ case SSH_FX_LINK_LOOP:
+ return "too many symbolic links";
+ case SSH_FX_CANNOT_DELETE:
+ return "file cannot be deleted";
+ case SSH_FX_INVALID_PARAMETER:
+ return "invalid parameter";
+ case SSH_FX_FILE_IS_A_DIRECTORY:
+ return "file is a directory";
+ case SSH_FX_BYTE_RANGE_LOCK_CONFLICT:
+ return "byte range is locked";
+ case SSH_FX_BYTE_RANGE_LOCK_REFUSED:
+ return "cannot lock byte range";
+ case SSH_FX_DELETE_PENDING:
+ return "file deletion pending";
+ case SSH_FX_FILE_CORRUPT:
+ return "file is corrupt";
+ case SSH_FX_OWNER_INVALID:
+ return "invalid owner";
+ case SSH_FX_GROUP_INVALID:
+ return "invalid group";
+ case SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK:
+ return "no such lock";
+ default:
+ return "unknown status";
}
}
-void sftp_send_status(struct sftpjob *job,
- uint32_t status,
- const char *msg) {
+void sftp_send_status(struct sftpjob *job, uint32_t status, const char *msg) {
if(status == HANDLER_ERRNO) {
/* Bodge to allow us to treat -1 as a magical status meaning 'consult
* errno'. This goes back via the protocol-specific status callback, so
@@ -84,16 +115,22 @@ void sftp_send_status(struct sftpjob *job,
/* Limit to status values known to this version of the protocol */
if(status > protocol->maxstatus) {
switch(status) {
- case SSH_FX_INVALID_FILENAME: status = SSH_FX_BAD_MESSAGE; break;
- case SSH_FX_NO_SUCH_PATH: status = SSH_FX_NO_SUCH_FILE; break;
- default: status = SSH_FX_FAILURE; break;
+ case SSH_FX_INVALID_FILENAME:
+ status = SSH_FX_BAD_MESSAGE;
+ break;
+ case SSH_FX_NO_SUCH_PATH:
+ status = SSH_FX_NO_SUCH_FILE;
+ break;
+ default:
+ status = SSH_FX_FAILURE;
+ break;
}
}
sftp_send_begin(job->worker);
sftp_send_uint8(job->worker, SSH_FXP_STATUS);
sftp_send_uint32(job->worker, job->id);
sftp_send_uint32(job->worker, status);
- sftp_send_path(job, job->worker, msg); /* needs to be UTF-8 */
+ sftp_send_path(job, job->worker, msg); /* needs to be UTF-8 */
/* We are not I18N'd yet. Doing so will require the following:
* - determine an RFC1766 interpretation of the current LC_MESSAGES
* setting
@@ -111,28 +148,28 @@ static const struct {
int errno_value;
uint32_t status_value;
} errnotab[] = {
- { 0, SSH_FX_OK },
- { EPERM, SSH_FX_PERMISSION_DENIED },
- { EACCES, SSH_FX_PERMISSION_DENIED },
- { ENOENT, SSH_FX_NO_SUCH_FILE },
- { EIO, SSH_FX_FILE_CORRUPT },
- { ENOSPC, SSH_FX_NO_SPACE_ON_FILESYSTEM },
- { ENOTDIR, SSH_FX_NOT_A_DIRECTORY },
- { EISDIR, SSH_FX_FILE_IS_A_DIRECTORY },
- { EEXIST, SSH_FX_FILE_ALREADY_EXISTS },
- { EROFS, SSH_FX_WRITE_PROTECT },
- { ELOOP, SSH_FX_LINK_LOOP },
- { ENAMETOOLONG, SSH_FX_INVALID_FILENAME },
- { ENOTEMPTY, SSH_FX_DIR_NOT_EMPTY },
- { EDQUOT, SSH_FX_QUOTA_EXCEEDED },
- { -1, SSH_FX_FAILURE },
+ {0, SSH_FX_OK},
+ {EPERM, SSH_FX_PERMISSION_DENIED},
+ {EACCES, SSH_FX_PERMISSION_DENIED},
+ {ENOENT, SSH_FX_NO_SUCH_FILE},
+ {EIO, SSH_FX_FILE_CORRUPT},
+ {ENOSPC, SSH_FX_NO_SPACE_ON_FILESYSTEM},
+ {ENOTDIR, SSH_FX_NOT_A_DIRECTORY},
+ {EISDIR, SSH_FX_FILE_IS_A_DIRECTORY},
+ {EEXIST, SSH_FX_FILE_ALREADY_EXISTS},
+ {EROFS, SSH_FX_WRITE_PROTECT},
+ {ELOOP, SSH_FX_LINK_LOOP},
+ {ENAMETOOLONG, SSH_FX_INVALID_FILENAME},
+ {ENOTEMPTY, SSH_FX_DIR_NOT_EMPTY},
+ {EDQUOT, SSH_FX_QUOTA_EXCEEDED},
+ {-1, SSH_FX_FAILURE},
};
void sftp_send_errno_status(struct sftpjob *job) {
int n;
const int errno_value = errno;
- for(n = 0;
+ for(n = 0;
errnotab[n].errno_value != errno_value && errnotab[n].errno_value != -1;
++n)
;
diff --git a/thread.h b/thread.h
index 62d7563..0495c7d 100644
--- a/thread.h
+++ b/thread.h
@@ -21,24 +21,24 @@
/** @file thread.h @brief Thread utilities */
#ifndef THREAD_H
-#define THREAD_H
+# define THREAD_H
-#include <pthread.h>
-#include <stdio.h>
+# include <pthread.h>
+# include <stdio.h>
-#if NTHREADS > 1 || CLIENT
+# if NTHREADS > 1 || CLIENT
/** @brief Error-checking macro for @c pthread_... functions */
-#define ferrcheck(E) do { \
- const int frc = (E); \
- if(frc) { \
- fatal("%s:%d: %s: %s\n", __FILE__, __LINE__, \
- #E, strerror(frc)); \
- exit(1); \
- } \
-} while(0)
-#else
-#define ferrcheck(E) (void)0
-#endif
+# define ferrcheck(E) \
+ do { \
+ const int frc = (E); \
+ if(frc) { \
+ sftp_fatal("%s:%d: %s: %s\n", __FILE__, __LINE__, #E, strerror(frc)); \
+ exit(1); \
+ } \
+ } while(0)
+# else
+# define ferrcheck(E) (void)0
+# endif
#endif /* THREAD_H */
diff --git a/types.h b/types.h
index 3b8b96f..931f541 100644
--- a/types.h
+++ b/types.h
@@ -21,11 +21,11 @@
/** @file types.h @brief Data types */
#ifndef TYPES_H
-#define TYPES_H
+# define TYPES_H
-#include <sys/stat.h>
-#include <wchar.h>
-#include <iconv.h>
+# include <sys/stat.h>
+# include <wchar.h>
+# include <iconv.h>
/** @brief An SFTP timestamp */
struct sftptime {
@@ -243,7 +243,7 @@ struct sftpjob {
uint32_t id;
/** @brief Worker processing this job */
- struct worker *worker; /* worker processing this job */
+ struct worker *worker; /* worker processing this job */
};
/** @brief An SFTP request */
@@ -268,10 +268,10 @@ struct sftpextension {
};
/** @brief Internal error code meaning "already responded" */
-#define HANDLER_RESPONDED ((uint32_t)-1)
+# define HANDLER_RESPONDED ((uint32_t)-1)
/** @brief Internal error code meaning "consult errno" */
-#define HANDLER_ERRNO ((uint32_t)-2)
+# define HANDLER_ERRNO ((uint32_t)-2)
/** @brief Definition of an SFTP protocol version */
struct sftpprotocol {
@@ -298,8 +298,8 @@ struct sftpprotocol {
* @param names Filenames (and attributes) to send
* @return Error code
*/
- void (*sendnames)(struct sftpjob *job,
- int nnames, const struct sftpattr *names);
+ void (*sendnames)(struct sftpjob *job, int nnames,
+ const struct sftpattr *names);
/** @brief Send file attributes
* @param job Job
@@ -320,16 +320,14 @@ struct sftpprotocol {
* @param path Input/output filename
* @return 0 on success, -1 on error (as per sftp_iconv())
*/
- int (*encode)(struct sftpjob *job,
- char **path);
+ int (*encode)(struct sftpjob *job, char **path);
/** @brief Decode a filename
* @param job Job
* @param path Input/output filename
* @return Error code
*/
- uint32_t (*decode)(struct sftpjob *job,
- char **path);
+ uint32_t (*decode)(struct sftpjob *job, char **path);
/** @brief Number of extension types supported */
int nextensions;
diff --git a/users.h b/users.h
index 71e7fbe..3b28d84 100644
--- a/users.h
+++ b/users.h
@@ -19,9 +19,9 @@
*/
#ifndef USERS_H
-#define USERS_H
+# define USERS_H
-#include <sys/types.h>
+# include <sys/types.h>
struct allocator;
diff --git a/utils.c b/utils.c
index 78322ce..45dc9ec 100644
--- a/utils.c
+++ b/utils.c
@@ -32,9 +32,9 @@
#include <limits.h>
#include <assert.h>
-int log_syslog;
+int sftp_log_syslog;
-int do_read(int fd, void *buffer, size_t size) {
+int sftp_xread(int fd, void *buffer, size_t size) {
size_t sofar = 0;
ssize_t n;
char *ptr = buffer;
@@ -44,42 +44,42 @@ int do_read(int fd, void *buffer, size_t size) {
if(n > 0)
sofar += n;
else if(n == 0)
- return -1; /* eof */
+ return -1; /* eof */
else
- fatal("read error: %s", strerror(errno));
+ sftp_fatal("read error: %s", strerror(errno));
}
- return 0; /* ok */
+ return 0; /* ok */
}
-void *xmalloc(size_t n) {
+void *sftp_xmalloc(size_t n) {
void *ptr;
- if(n) {
- if(!(ptr = malloc(n)))
- fatal("xmalloc: out of memory (%zu)", n);
- return ptr;
- } else
- return 0;
+ if(!n)
+ n = 1;
+ if(!(ptr = malloc(n)))
+ sftp_fatal("sftp_xmalloc: out of memory (%zu)", n);
+ return ptr;
}
-void *xcalloc(size_t n, size_t size) {
+void *sftp_xcalloc(size_t n, size_t size) {
void *ptr;
- if(n && size) {
- if(!(ptr = calloc(n, size)))
- fatal("xcalloc: out of memory (%zu, %zu)", n, size);
- return ptr;
- } else
- return 0;
+ if(!n)
+ n = 1;
+ if(!size)
+ size = 1;
+ if(!(ptr = calloc(n, size)))
+ sftp_fatal("sftp_xcalloc: out of memory (%zu, %zu)", n, size);
+ return ptr;
}
-void *xrecalloc(void *ptr, size_t n, size_t size) {
+void *sftp_xrecalloc(void *ptr, size_t n, size_t size) {
if(n > SIZE_MAX / size)
- fatal("xrecalloc: out of memory (%zu, %zu)", n, size);
+ sftp_fatal("sftp_xrecalloc: out of memory (%zu, %zu)", n, size);
n *= size;
if(n) {
if(!(ptr = realloc(ptr, n)))
- fatal("xrecalloc: out of memory (%zu)", n);
+ sftp_fatal("sftp_xrecalloc: out of memory (%zu)", n);
return ptr;
} else {
free(ptr);
@@ -87,10 +87,10 @@ void *xrecalloc(void *ptr, size_t n, size_t size) {
}
}
-void *xrealloc(void *ptr, size_t n) {
+void *sftp_xrealloc(void *ptr, size_t n) {
if(n) {
if(!(ptr = realloc(ptr, n)))
- fatal("xrealloc: out of memory (%zu)", n);
+ sftp_fatal("sftp_xrealloc: out of memory (%zu)", n);
return ptr;
} else {
free(ptr);
@@ -98,17 +98,17 @@ void *xrealloc(void *ptr, size_t n) {
}
}
-char *xstrdup(const char *s) {
- return strcpy(xmalloc(strlen(s) + 1), s);
+char *sftp_xstrdup(const char *s) {
+ return strcpy(sftp_xmalloc(strlen(s) + 1), s);
}
static void (*exitfn)(int) attribute((noreturn)) = exit;
-void fatal(const char *msg, ...) {
+void sftp_fatal(const char *msg, ...) {
va_list ap;
va_start(ap, msg);
- if(log_syslog)
+ if(sftp_log_syslog)
vsyslog(LOG_ERR, msg, ap);
else {
fprintf(stderr, "FATAL: ");
@@ -119,31 +119,29 @@ void fatal(const char *msg, ...) {
exitfn(-1);
}
-void forked(void) {
- exitfn = _exit;
-}
+void sftp_forked(void) { exitfn = _exit; }
-pid_t xfork(void) {
+pid_t sftp_xfork(void) {
pid_t pid;
if((pid = fork()) < 0)
- fatal("fork: %s", strerror(errno));
+ sftp_fatal("fork: %s", strerror(errno));
if(!pid)
- forked();
+ sftp_forked();
return pid;
}
-char *appendn(struct allocator *a, char *s, size_t *ns,
- const char *t, size_t lt) {
+char *sftp_str_appendn(struct allocator *a, char *s, size_t *ns, const char *t,
+ size_t lt) {
const size_t ls = s ? strlen(s) : 0, need = lt + ls + 1;
-
+
if(need > *ns) {
size_t newsize = *ns ? *ns : 16;
while(need > newsize && newsize)
newsize *= 2;
if(!newsize)
- fatal("appendn: out of memory (%zu, %zu)", ls, need);
+ sftp_fatal("sftp_str_appendn: out of memory (%zu, %zu)", ls, need);
s = sftp_alloc_more(a, s, *ns, newsize);
*ns = newsize;
} else {
@@ -151,14 +149,13 @@ char *appendn(struct allocator *a, char *s, size_t *ns,
assert(s);
}
- memcpy(s + ls, t, lt);
+ sftp_memcpy(s + ls, t, lt);
s[ls + lt] = 0;
return s;
}
-char *append(struct allocator *a, char *s, size_t *ns,
- const char *t) {
- return appendn(a, s, ns, t, strlen(t));
+char *sftp_str_append(struct allocator *a, char *s, size_t *ns, const char *t) {
+ return sftp_str_appendn(a, s, ns, t, strlen(t));
}
/*
diff --git a/utils.h b/utils.h
index 5787e2f..4a13dcc 100644
--- a/utils.h
+++ b/utils.h
@@ -21,8 +21,10 @@
/** @file utils.h @brief Utility functions interface */
#ifndef UTILS_H
-#define UTILS_H
+# define UTILS_H
+# include <string.h>
+# include <assert.h>
/** @brief Read bytes from @p fd
* @param fd File descriptor to read from
@@ -30,44 +32,39 @@
* @param size Number of bytes to read
* @return 0 on success, non-0 if EOF before @p size bytes read
*
- * Loops if necessary to cope with short reads. Calls fatal() on error.
+ * Loops if necessary to cope with short reads. Calls sftp_fatal() on error.
*/
-int do_read(int fd, void *buffer, size_t size);
-
-/* libreadliine contains xmalloc/xrealloc! We use some #defines to work around
- * the problem. */
-#define xmalloc sftp__xmalloc
-#define xrealloc sftp__xrealloc
+int sftp_xread(int fd, void *buffer, size_t size);
/** @brief Allocate memory
* @param n Number of bytes to allocate
* @return Pointer to allocated memory
*
- * Equivalent to @c malloc() but calls fatal() on error.
+ * Equivalent to @c malloc() but calls sftp_fatal() on error.
*
* Does not zero-fill.
*/
-void *xmalloc(size_t n);
+void *sftp_xmalloc(size_t n);
/** @brief Allocate memory
* @param n Number of objects to allocate
* @param size Size of one object
* @return Pointer to allocated memory
*
- * Equivalent to @c calloc() but calls fatal() on error.
+ * Equivalent to @c calloc() but calls sftp_fatal() on error.
*/
-void *xcalloc(size_t n, size_t size);
+void *sftp_xcalloc(size_t n, size_t size);
/** @brief Reallocate memory
* @param ptr Existing allocation
* @param n Number of bytes to allocate
* @return Pointer to allocated memory
*
- * Equivalent to @c realloc() but calls fatal() on error.
+ * Equivalent to @c realloc() but calls sftp_fatal() on error.
*
* Does not zero-fill.
*/
-void *xrealloc(void *ptr, size_t n);
+void *sftp_xrealloc(void *ptr, size_t n);
/** @brief Reallocate memory
* @param ptr Existing allocation
@@ -75,19 +72,19 @@ void *xrealloc(void *ptr, size_t n);
* @param size Size of one object
* @return Pointer to allocated memory
*
- * Equivalent to @c realloc() but calls fatal() on error.
+ * Equivalent to @c realloc() but calls sftp_fatal() on error.
*
* Does not zero-fill.
*/
-void *xrecalloc(void *ptr, size_t n, size_t size);
+void *sftp_xrecalloc(void *ptr, size_t n, size_t size);
/** @brief Duplicate a string
* @param s String to duplicate
* @return Duplicated string
*
- * Equivalent to @c strdup() but calls fatal() on error.
+ * Equivalent to @c strdup() but calls sftp_fatal() on error.
*/
-char *xstrdup(const char *s);
+char *sftp_xstrdup(const char *s);
/** @brief Append to a string
* @param a Allocator
@@ -96,8 +93,7 @@ char *xstrdup(const char *s);
* @param t String to append
* @return New string
*/
-char *append(struct allocator *a, char *s, size_t *ns,
- const char *t);
+char *sftp_str_append(struct allocator *a, char *s, size_t *ns, const char *t);
/** @brief Append to a string
* @param a Allocator
@@ -107,8 +103,8 @@ char *append(struct allocator *a, char *s, size_t *ns,
* @param lt Length of @p t
* @return New string
*/
-char *appendn(struct allocator *a, char *s, size_t *ns,
- const char *t, size_t lt);
+char *sftp_str_appendn(struct allocator *a, char *s, size_t *ns, const char *t,
+ size_t lt);
/** @brief Convenient wrapper for readlink(2)
* @param a Allocator to store result
@@ -145,20 +141,19 @@ char *sftp_do_readlink(struct allocator *a, const char *path);
*
* Sets @c errno on erorr.
*/
-char *sftp_find_realpath(struct allocator *a, const char *path,
- unsigned flags);
+char *sftp_find_realpath(struct allocator *a, const char *path, unsigned flags);
/** @brief Follow symlinks
*
* See sftp_find_realpath().
*/
-#define RP_READLINK 0x0001
+# define RP_READLINK 0x0001
/** @brief Path must exist
*
* See sftp_find_realpath().
*/
-#define RP_MUST_EXIST 0x0002
+# define RP_MUST_EXIST 0x0002
/** @brief Compute the name of the current directory
* @param a Allocator to store result
@@ -178,35 +173,62 @@ const char *sftp_dirname(struct allocator *a, const char *path);
* @param ... Arguments
*
* The error is written either to standard error or syslog; see @ref
- * log_syslog.
+ * sftp_log_syslog.
*
* Terminates the process.
*/
-void fatal(const char *msg, ...)
- attribute((noreturn))
- attribute((format(printf,1,2)));
+void sftp_fatal(const char *msg, ...) attribute((noreturn))
+ attribute((format(printf, 1, 2)));
/** @brief Fork a subprocess
* @return 0 in the child, process ID in the parent
*
- * Calls fatal() on error.
+ * Calls sftp_fatal() on error.
*/
-pid_t xfork(void);
+pid_t sftp_xfork(void);
/** @brief Called after forking
*
- * Affects the way that fatal() terminates the process.
+ * Affects the way that sftp_fatal() terminates the process.
*
- * xfork() already calls it, any other calls to @c fork() should call it
+ * sftp_xfork() already calls it, any other calls to @c fork() should call it
* explicitly.
*/
-void forked(void);
+void sftp_forked(void);
+
+/** @brief memcpy wrapper
+ *
+ * Equivalent to @c memcpy except that the prohibition on null pointer
+ * arguments is removed when @p n is 0.
+ */
+static inline void *sftp_memcpy(void *restrict dest, const void *restrict src,
+ size_t n) {
+ if(n) {
+ assert(dest);
+ assert(src);
+ return memcpy(dest, src, n);
+ }
+ return dest;
+}
+
+/** @brief sftp_memset wrapper
+ *
+ * Equivalent to @c memset except that the prohibition on null pointer
+ * arguments is removed when @p n is 0.
+ */
+static inline void *sftp_memset(void *s, int ch, size_t n) {
+ if(n) {
+ assert(s);
+ return memset(s, ch, n);
+ }
+ return s;
+}
/** @brief Whether to log to syslog
*
- * Affects where fatal() writes to.
+ * Affects where sftp_fatal() writes to.
*/
-extern int log_syslog;
+extern int sftp_log_syslog;
#endif /* UTILS_H */
diff --git a/v3.c b/v3.c
index b761f6b..0a028f1 100644
--- a/v3.c
+++ b/v3.c
@@ -50,12 +50,12 @@ int reverse_symlink;
/* Encode/decode path names. v3 does not know what encoding filenames use. I
* assume that the client and the server use the same encoding and so don't
* perform any translation. */
-int sftp_v3_encode(struct sftpjob attribute((unused)) *job,
- char attribute((unused)) **path) {
+int sftp_v3_encode(struct sftpjob attribute((unused)) * job,
+ char attribute((unused)) * *path) {
return 0;
}
-static uint32_t v3_decode(struct sftpjob attribute((unused)) *job,
+static uint32_t v3_decode(struct sftpjob attribute((unused)) * job,
char **path) {
/* Empty path means default directory */
if(!**path)
@@ -65,8 +65,8 @@ static uint32_t v3_decode(struct sftpjob attribute((unused)) *job,
/* Send a filename list as found in an SSH_FXP_NAME response. The response
* header and so on must be generated by the caller. */
-static void v3_sendnames(struct sftpjob *job,
- int nnames, const struct sftpattr *names) {
+static void v3_sendnames(struct sftpjob *job, int nnames,
+ const struct sftpattr *names) {
time_t now;
struct tm nowtime;
@@ -76,31 +76,30 @@ static void v3_sendnames(struct sftpjob *job,
sftp_send_uint32(job->worker, nnames);
while(nnames > 0) {
sftp_send_path(job, job->worker, names->name);
- sftp_send_string(job->worker, sftp_format_attr(job->a, names, nowtime.tm_year, 0));
+ sftp_send_string(job->worker,
+ sftp_format_attr(job->a, names, nowtime.tm_year, 0));
protocol->sendattrs(job, names);
++names;
--nnames;
}
}
-static void v3_sendattrs(struct sftpjob *job,
- const struct sftpattr *attrs) {
+static void v3_sendattrs(struct sftpjob *job, const struct sftpattr *attrs) {
uint32_t v3bits, m, a;
/* The timestamp flags change between v3 and v4. In the structure we always
* use the v4+ bits, so we must translate. */
- if((attrs->valid & (SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME))
- == (SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME))
- v3bits = ((attrs->valid & (SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_UIDGID
- |SSH_FILEXFER_ATTR_PERMISSIONS))
- |SSH_FILEXFER_ACMODTIME);
+ if((attrs->valid &
+ (SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME)) ==
+ (SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME))
+ v3bits =
+ ((attrs->valid & (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID |
+ SSH_FILEXFER_ATTR_PERMISSIONS)) |
+ SSH_FILEXFER_ACMODTIME);
else
- v3bits = (attrs->valid & (SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_UIDGID
- |SSH_FILEXFER_ATTR_PERMISSIONS));
+ v3bits =
+ (attrs->valid & (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID |
+ SSH_FILEXFER_ATTR_PERMISSIONS));
sftp_send_uint32(job->worker, v3bits);
if(v3bits & SSH_FILEXFER_ATTR_SIZE)
sftp_send_uint64(job->worker, attrs->size);
@@ -119,11 +118,11 @@ static void v3_sendattrs(struct sftpjob *job,
* bogus timestamps or have some other workaround, then delete the
* checks. */
if(m != attrs->mtime.seconds)
- fatal("sending out-of-range mtime");
+ sftp_fatal("sending out-of-range mtime");
if(a != attrs->atime.seconds)
- fatal("sending out-of-range mtime");
- sftp_send_uint32(job->worker, m);
+ sftp_fatal("sending out-of-range mtime");
sftp_send_uint32(job->worker, a);
+ sftp_send_uint32(job->worker, m);
}
/* Note that we just discard unknown bits rather than reporting errors. */
}
@@ -131,19 +130,19 @@ static void v3_sendattrs(struct sftpjob *job,
static uint32_t v3_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
uint32_t n, rc;
- memset(attrs, 0, sizeof *attrs);
+ sftp_memset(attrs, 0, sizeof *attrs);
if((rc = sftp_parse_uint32(job, &attrs->valid)) != SSH_FX_OK)
return rc;
if((attrs->valid & protocol->attrmask) != attrs->valid) {
- D(("received attrs %#x but protocol %d only supports %#x",
- attrs->valid, protocol->version, protocol->attrmask));
+ D(("received attrs %#x but protocol %d only supports %#x", attrs->valid,
+ protocol->version, protocol->attrmask));
attrs->valid = 0;
return SSH_FX_BAD_MESSAGE;
}
/* Translate v3 bits t v4+ bits */
if(attrs->valid & SSH_FILEXFER_ACMODTIME)
- attrs->valid |= (SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME);
+ attrs->valid |=
+ (SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME);
/* Read the v3 fields */
if(attrs->valid & SSH_FILEXFER_ATTR_SIZE)
if((rc = sftp_parse_uint64(job, &attrs->size)) != SSH_FX_OK)
@@ -159,14 +158,30 @@ static uint32_t v3_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
return rc;
/* Fake up type field */
switch(attrs->permissions & S_IFMT) {
- case S_IFIFO: attrs->type = SSH_FILEXFER_TYPE_FIFO; break;
- case S_IFCHR: attrs->type = SSH_FILEXFER_TYPE_CHAR_DEVICE; break;
- case S_IFDIR: attrs->type = SSH_FILEXFER_TYPE_DIRECTORY; break;
- case S_IFBLK: attrs->type = SSH_FILEXFER_TYPE_BLOCK_DEVICE; break;
- case S_IFREG: attrs->type = SSH_FILEXFER_TYPE_REGULAR; break;
- case S_IFLNK: attrs->type = SSH_FILEXFER_TYPE_SYMLINK; break;
- case S_IFSOCK: attrs->type = SSH_FILEXFER_TYPE_SOCKET; break;
- default: attrs->type = SSH_FILEXFER_TYPE_UNKNOWN; break;
+ case S_IFIFO:
+ attrs->type = SSH_FILEXFER_TYPE_FIFO;
+ break;
+ case S_IFCHR:
+ attrs->type = SSH_FILEXFER_TYPE_CHAR_DEVICE;
+ break;
+ case S_IFDIR:
+ attrs->type = SSH_FILEXFER_TYPE_DIRECTORY;
+ break;
+ case S_IFBLK:
+ attrs->type = SSH_FILEXFER_TYPE_BLOCK_DEVICE;
+ break;
+ case S_IFREG:
+ attrs->type = SSH_FILEXFER_TYPE_REGULAR;
+ break;
+ case S_IFLNK:
+ attrs->type = SSH_FILEXFER_TYPE_SYMLINK;
+ break;
+ case S_IFSOCK:
+ attrs->type = SSH_FILEXFER_TYPE_SOCKET;
+ break;
+ default:
+ attrs->type = SSH_FILEXFER_TYPE_UNKNOWN;
+ break;
}
} else
attrs->type = SSH_FILEXFER_TYPE_UNKNOWN;
@@ -184,8 +199,8 @@ static uint32_t v3_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
if((rc = sftp_parse_uint32(job, &n)) != SSH_FX_OK)
return rc;
while(n-- > 0) {
- if((rc = sftp_parse_string(job, 0, 0)) != SSH_FX_OK
- || (rc = sftp_parse_string(job, 0, 0)) != SSH_FX_OK)
+ if((rc = sftp_parse_string(job, 0, 0)) != SSH_FX_OK ||
+ (rc = sftp_parse_string(job, 0, 0)) != SSH_FX_OK)
return rc;
}
}
@@ -194,7 +209,7 @@ static uint32_t v3_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
/* Command implementations */
-uint32_t sftp_vany_already_init(struct sftpjob attribute((unused)) *job) {
+uint32_t sftp_vany_already_init(struct sftpjob attribute((unused)) * job) {
/* Cannot initialize more than once */
return SSH_FX_FAILURE;
}
@@ -221,7 +236,7 @@ uint32_t sftp_vany_remove(struct sftpjob *job) {
uint32_t sftp_vany_rmdir(struct sftpjob *job) {
char *path;
-
+
if(readonly)
return SSH_FX_PERMISSION_DENIED;
pcheck(sftp_parse_path(job, &path));
@@ -275,11 +290,11 @@ uint32_t sftp_v34_rename(struct sftpjob *job) {
return SSH_FX_FILE_ALREADY_EXISTS;
}
#endif
- if(rename(oldpath, newpath) < 0)
+ if(rename(oldpath, newpath) < 0)
return HANDLER_ERRNO;
else
return SSH_FX_OK;
- } else
+ } else
return HANDLER_ERRNO;
} else if(unlink(oldpath) < 0) {
const int save_errno = errno;
@@ -372,7 +387,7 @@ uint32_t sftp_vany_readlink(struct sftpjob *job) {
}
return HANDLER_ERRNO;
}
- memset(&attr, 0, sizeof attr);
+ sftp_memset(&attr, 0, sizeof attr);
attr.name = result;
sftp_send_begin(job->worker);
sftp_send_uint8(job->worker, SSH_FXP_NAME);
@@ -392,7 +407,7 @@ uint32_t sftp_vany_opendir(struct sftpjob *job) {
if(!(dp = opendir(path)))
return HANDLER_ERRNO;
sftp_handle_new_dir(&id, dp, path);
- D(("...handle is %"PRIu32" %"PRIu32, id.id, id.tag));
+ D(("...handle is %" PRIu32 " %" PRIu32, id.id, id.tag));
sftp_send_begin(job->worker);
sftp_send_uint8(job->worker, SSH_FXP_HANDLE);
sftp_send_uint32(job->worker, job->id);
@@ -411,14 +426,14 @@ uint32_t sftp_vany_readdir(struct sftpjob *job) {
const char *path;
char *childpath, *fullpath;
struct stat sb;
-
+
pcheck(sftp_parse_handle(job, &id));
- D(("sftp_vany_readdir %"PRIu32" %"PRIu32, id.id, id.tag));
+ D(("sftp_vany_readdir %" PRIu32 " %" PRIu32, id.id, id.tag));
if((rc = sftp_handle_get_dir(&id, &dp, &path))) {
sftp_send_status(job, rc, "invalid directory handle");
return HANDLER_RESPONDED;
}
- memset(d, 0, sizeof d);
+ sftp_memset(d, 0, sizeof d);
for(n = 0; n < MAXNAMES;) {
/* readdir() has a slightly shonky interface - a null return can mean EOF
* or error, and there is no guarantee that errno is reset to 0 on EOF. */
@@ -439,10 +454,10 @@ uint32_t sftp_vany_readdir(struct sftpjob *job) {
sftp_stat_to_attrs(job->a, &sb, &d[n], 0xFFFFFFFF, childpath);
d[n].name = childpath;
++n;
- errno = 0; /* avoid error slippage from
- * e.g. getpwuid() failure */
+ errno = 0; /* avoid error slippage from
+ * e.g. getpwuid() failure */
}
-
+
if(errno)
return HANDLER_ERRNO;
if(n) {
@@ -458,9 +473,9 @@ uint32_t sftp_vany_readdir(struct sftpjob *job) {
uint32_t sftp_vany_close(struct sftpjob *job) {
struct handleid id;
-
+
pcheck(sftp_parse_handle(job, &id));
- D(("sftp_vany_close %"PRIu32" %"PRIu32, id.id, id.tag));
+ D(("sftp_vany_close %" PRIu32 " %" PRIu32, id.id, id.tag));
return sftp_handle_close(&id);
}
@@ -470,7 +485,7 @@ uint32_t sftp_v345_realpath(struct sftpjob *job) {
pcheck(sftp_parse_path(job, &path));
D(("sftp_v345_realpath %s", path));
- memset(&attr, 0, sizeof attr);
+ sftp_memset(&attr, 0, sizeof attr);
attr.name = sftp_find_realpath(job->a, path, RP_READLINK);
if(attr.name) {
D(("...real path is %s", attr.name));
@@ -486,7 +501,7 @@ uint32_t sftp_v345_realpath(struct sftpjob *job) {
/* Command code for the various _*STAT calls. rc is the return value
* from *stat() and SB is the buffer. */
-static uint32_t sftp_v3_stat_core(struct sftpjob *job, int rc,
+static uint32_t sftp_v3_stat_core(struct sftpjob *job, int rc,
const struct stat *sb) {
struct sftpattr attrs;
@@ -494,7 +509,7 @@ static uint32_t sftp_v3_stat_core(struct sftpjob *job, int rc,
/* We suppress owner/group name lookup since there is no way to communicate
* it in protocol version 3 */
sftp_stat_to_attrs(job->a, sb, &attrs,
- ~(uint32_t)SSH_FILEXFER_ATTR_OWNERGROUP, 0);
+ ~(uint32_t)SSH_FILEXFER_ATTR_OWNERGROUP, 0);
sftp_send_begin(job->worker);
sftp_send_uint8(job->worker, SSH_FXP_ATTRS);
sftp_send_uint32(job->worker, job->id);
@@ -530,7 +545,7 @@ static uint32_t sftp_v3_fstat(struct sftpjob *job) {
uint32_t rc;
pcheck(sftp_parse_handle(job, &id));
- D(("sftp_v3_fstat %"PRIu32" %"PRIu32, id.id, id.tag));
+ D(("sftp_v3_fstat %" PRIu32 " %" PRIu32, id.id, id.tag));
if((rc = sftp_handle_get_fd(&id, &fd, 0)))
return rc;
return sftp_v3_stat_core(job, fstat(fd, &sb), &sb);
@@ -562,11 +577,11 @@ uint32_t sftp_vany_fsetstat(struct sftpjob *job) {
return SSH_FX_PERMISSION_DENIED;
pcheck(sftp_parse_handle(job, &id));
pcheck(protocol->parseattrs(job, &attrs));
- D(("sftp_vany_fsetstat %"PRIu32" %"PRIu32, id.id, id.tag));
+ D(("sftp_vany_fsetstat %" PRIu32 " %" PRIu32, id.id, id.tag));
/* Check owner/group */
if((rc = sftp_normalize_ownergroup(job->a, &attrs)) != SSH_FX_OK)
return rc;
- if((rc = sftp_handle_get_fd(&id, &fd, 0)))
+ if((rc = sftp_handle_get_fd(&id, &fd, 0)))
return rc;
return sftp_set_fstatus(job->a, fd, &attrs, 0);
}
@@ -581,12 +596,12 @@ uint32_t sftp_vany_mkdir(struct sftpjob *job) {
pcheck(sftp_parse_path(job, &path));
pcheck(protocol->parseattrs(job, &attrs));
D(("sftp_vany_mkdir %s", path));
- attrs.valid &= ~SSH_FILEXFER_ATTR_SIZE; /* makes no sense */
+ attrs.valid &= (uint32_t)~SSH_FILEXFER_ATTR_SIZE; /* makes no sense */
if(attrs.valid & SSH_FILEXFER_ATTR_PERMISSIONS) {
- D(("initial permissions are %#o (%d decimal)",
- attrs.permissions, attrs.permissions));
+ D(("initial permissions are %#o (%d decimal)", attrs.permissions,
+ attrs.permissions));
/* If we're given initial permissions, use them */
- if(mkdir(path, attrs.permissions & 07777) < 0)
+ if(mkdir(path, attrs.permissions & 07777) < 0)
return HANDLER_ERRNO;
/* Don't modify permissions later unless necessary */
if(attrs.permissions == (attrs.permissions & 0777))
@@ -617,9 +632,9 @@ uint32_t sftp_v34_open(struct sftpjob *job) {
pcheck(sftp_parse_path(job, &path));
pcheck(sftp_parse_uint32(job, &pflags));
pcheck(protocol->parseattrs(job, &attrs));
- D(("sftp_v34_open %s %#"PRIx32, path, pflags));
+ D(("sftp_v34_open %s %#" PRIx32, path, pflags));
/* Translate to v5/6 bits */
- switch(pflags & (SSH_FXF_CREAT|SSH_FXF_TRUNC|SSH_FXF_EXCL)) {
+ switch(pflags & (SSH_FXF_CREAT | SSH_FXF_TRUNC | SSH_FXF_EXCL)) {
case 0:
flags = SSH_FXF_OPEN_EXISTING;
break;
@@ -632,11 +647,11 @@ uint32_t sftp_v34_open(struct sftpjob *job) {
case SSH_FXF_CREAT:
flags = SSH_FXF_OPEN_OR_CREATE;
break;
- case SSH_FXF_CREAT|SSH_FXF_TRUNC:
+ case SSH_FXF_CREAT | SSH_FXF_TRUNC:
flags = SSH_FXF_CREATE_TRUNCATE;
break;
- case SSH_FXF_CREAT|SSH_FXF_EXCL:
- case SSH_FXF_CREAT|SSH_FXF_TRUNC|SSH_FXF_EXCL: /* nonsensical */
+ case SSH_FXF_CREAT | SSH_FXF_EXCL:
+ case SSH_FXF_CREAT | SSH_FXF_TRUNC | SSH_FXF_EXCL: /* nonsensical */
flags = SSH_FXF_CREATE_NEW;
break;
default:
@@ -645,9 +660,9 @@ uint32_t sftp_v34_open(struct sftpjob *job) {
if(pflags & SSH_FXF_TEXT)
flags |= SSH_FXF_TEXT_MODE;
if(pflags & SSH_FXF_READ)
- desired_access |= ACE4_READ_DATA|ACE4_READ_ATTRIBUTES;
+ desired_access |= ACE4_READ_DATA | ACE4_READ_ATTRIBUTES;
if(pflags & SSH_FXF_WRITE)
- desired_access |= ACE4_WRITE_DATA|ACE4_WRITE_ATTRIBUTES;
+ desired_access |= ACE4_WRITE_DATA | ACE4_WRITE_ATTRIBUTES;
if(pflags & SSH_FXF_APPEND) {
flags |= SSH_FXF_APPEND_DATA;
desired_access |= ACE4_APPEND_DATA;
@@ -666,7 +681,8 @@ uint32_t sftp_vany_read(struct sftpjob *job) {
pcheck(sftp_parse_handle(job, &id));
pcheck(sftp_parse_uint64(job, &offset));
pcheck(sftp_parse_uint32(job, &len));
- D(("sftp_vany_read %"PRIx32" %"PRIu32" %"PRIu32": %"PRIu32" bytes at %"PRIu64,
+ D(("sftp_vany_read %" PRIx32 " %" PRIu32 " %" PRIu32 ": %" PRIu32
+ " bytes at %" PRIu64,
job->id, id.id, id.tag, len, offset));
if(len > MAXREAD)
len = MAXREAD;
@@ -677,7 +693,7 @@ uint32_t sftp_vany_read(struct sftpjob *job) {
sftp_send_uint8(job->worker, SSH_FXP_DATA);
sftp_send_uint32(job->worker, job->id);
sftp_send_need(job->worker, len + 4);
- if(flags & (HANDLE_TEXT|HANDLE_APPEND))
+ if(flags & (HANDLE_TEXT | HANDLE_APPEND))
n = read(fd, job->worker->buffer + job->worker->bufused + 4, len);
else
n = pread(fd, job->worker->buffer + job->worker->bufused + 4, len, offset);
@@ -712,13 +728,13 @@ uint32_t sftp_vany_write(struct sftpjob *job) {
pcheck(sftp_parse_uint32(job, &len));
if(len > job->left)
return SSH_FX_BAD_MESSAGE;
- D(("sftp_vany_write %"PRIu32" %"PRIu32": %"PRIu32" bytes at %"PRIu64,
+ D(("sftp_vany_write %" PRIu32 " %" PRIu32 ": %" PRIu32 " bytes at %" PRIu64,
id.id, id.tag, len, offset));
if((rc = sftp_handle_get_fd(&id, &fd, &flags)))
return rc;
while(len > 0) {
/* Short writes aren't allowed so we loop around writing more */
- if(flags & (HANDLE_TEXT|HANDLE_APPEND))
+ if(flags & (HANDLE_TEXT | HANDLE_APPEND))
n = write(fd, job->ptr, len);
else
n = pwrite(fd, job->ptr, len, offset);
@@ -740,7 +756,7 @@ uint32_t sftp_vany_posix_rename(struct sftpjob *job) {
pcheck(sftp_parse_path(job, &oldpath));
pcheck(sftp_parse_path(job, &newpath));
D(("sftp_vany_posix_rename %s %s", oldpath, newpath));
- if(rename(oldpath, newpath) < 0)
+ if(rename(oldpath, newpath) < 0)
return HANDLER_ERRNO;
else
return SSH_FX_OK;
@@ -770,8 +786,9 @@ uint32_t sftp_vany_statfs(struct sftpjob *job) {
return HANDLER_RESPONDED;
}
-static uint32_t sftp_vany_statvfs_send(struct sftpjob *job, int rc, struct statvfs *fs) {
- if (rc < 0)
+static uint32_t sftp_vany_statvfs_send(struct sftpjob *job, int rc,
+ struct statvfs *fs) {
+ if(rc < 0)
return HANDLER_ERRNO;
sftp_send_begin(job->worker);
sftp_send_uint8(job->worker, SSH_FXP_EXTENDED_REPLY);
@@ -785,7 +802,8 @@ static uint32_t sftp_vany_statvfs_send(struct sftpjob *job, int rc, struct statv
sftp_send_uint64(job->worker, fs->f_ffree);
sftp_send_uint64(job->worker, fs->f_favail);
sftp_send_uint64(job->worker, fs->f_fsid);
- sftp_send_uint64(job->worker, (fs->f_flag & ST_RDONLY ? 1 : 0) | (fs->f_flag & ST_NOSUID ? 2 : 0));
+ sftp_send_uint64(job->worker, (fs->f_flag & ST_RDONLY ? 1 : 0) |
+ (fs->f_flag & ST_NOSUID ? 2 : 0));
sftp_send_uint64(job->worker, fs->f_namemax);
sftp_send_end(job->worker);
return HANDLER_RESPONDED;
@@ -807,7 +825,7 @@ uint32_t sftp_vany_fstatvfs(struct sftpjob *job) {
uint32_t rc;
pcheck(sftp_parse_handle(job, &id));
- D(("sftp_vany_fstatvfs %"PRIu32" %"PRIu32, id.id, id.tag));
+ D(("sftp_vany_fstatvfs %" PRIu32 " %" PRIu32, id.id, id.tag));
if((rc = sftp_handle_get_fd(&id, &fd, 0)))
return rc;
return sftp_vany_statvfs_send(job, fstatvfs(fd, &fs), &fs);
@@ -819,10 +837,10 @@ uint32_t sftp_vany_fsync(struct sftpjob *job) {
uint32_t rc;
pcheck(sftp_parse_handle(job, &id));
- D(("sftp_v3_fstat %"PRIu32" %"PRIu32, id.id, id.tag));
+ D(("sftp_v3_fstat %" PRIu32 " %" PRIu32, id.id, id.tag));
if((rc = sftp_handle_get_fd(&id, &fd, 0)))
return rc;
- if (fsync(fd) < 0)
+ if(fsync(fd) < 0)
return HANDLER_ERRNO;
return SSH_FX_OK;
}
@@ -833,7 +851,7 @@ uint32_t sftp_vany_hardlink(struct sftpjob *job) {
/* See also comment in v3.c for SSH_FXP_SYMLINK */
if(readonly)
return SSH_FX_PERMISSION_DENIED;
- pcheck(sftp_parse_path(job, &oldpath)); /* aka existing-path/target-paths */
+ pcheck(sftp_parse_path(job, &oldpath)); /* aka existing-path/target-paths */
pcheck(sftp_parse_path(job, &newlinkpath));
D(("sftp_hardlink %s %s", oldpath, newlinkpath));
if(link(oldpath, newlinkpath) < 0)
@@ -842,56 +860,53 @@ uint32_t sftp_vany_hardlink(struct sftpjob *job) {
}
static const struct sftpcmd sftpv3tab[] = {
- { SSH_FXP_INIT, sftp_vany_already_init },
- { SSH_FXP_OPEN, sftp_v34_open },
- { SSH_FXP_CLOSE, sftp_vany_close },
- { SSH_FXP_READ, sftp_vany_read },
- { SSH_FXP_WRITE, sftp_vany_write },
- { SSH_FXP_LSTAT, sftp_v3_lstat },
- { SSH_FXP_FSTAT, sftp_v3_fstat },
- { SSH_FXP_SETSTAT, sftp_vany_setstat },
- { SSH_FXP_FSETSTAT, sftp_vany_fsetstat },
- { SSH_FXP_OPENDIR, sftp_vany_opendir },
- { SSH_FXP_READDIR, sftp_vany_readdir },
- { SSH_FXP_REMOVE, sftp_vany_remove },
- { SSH_FXP_MKDIR, sftp_vany_mkdir },
- { SSH_FXP_RMDIR, sftp_vany_rmdir },
- { SSH_FXP_REALPATH, sftp_v345_realpath },
- { SSH_FXP_STAT, sftp_v3_stat },
- { SSH_FXP_RENAME, sftp_v34_rename },
- { SSH_FXP_READLINK, sftp_vany_readlink },
- { SSH_FXP_SYMLINK, sftp_v345_symlink },
- { SSH_FXP_EXTENDED, sftp_vany_extended }
-};
+ {SSH_FXP_INIT, sftp_vany_already_init},
+ {SSH_FXP_OPEN, sftp_v34_open},
+ {SSH_FXP_CLOSE, sftp_vany_close},
+ {SSH_FXP_READ, sftp_vany_read},
+ {SSH_FXP_WRITE, sftp_vany_write},
+ {SSH_FXP_LSTAT, sftp_v3_lstat},
+ {SSH_FXP_FSTAT, sftp_v3_fstat},
+ {SSH_FXP_SETSTAT, sftp_vany_setstat},
+ {SSH_FXP_FSETSTAT, sftp_vany_fsetstat},
+ {SSH_FXP_OPENDIR, sftp_vany_opendir},
+ {SSH_FXP_READDIR, sftp_vany_readdir},
+ {SSH_FXP_REMOVE, sftp_vany_remove},
+ {SSH_FXP_MKDIR, sftp_vany_mkdir},
+ {SSH_FXP_RMDIR, sftp_vany_rmdir},
+ {SSH_FXP_REALPATH, sftp_v345_realpath},
+ {SSH_FXP_STAT, sftp_v3_stat},
+ {SSH_FXP_RENAME, sftp_v34_rename},
+ {SSH_FXP_READLINK, sftp_vany_readlink},
+ {SSH_FXP_SYMLINK, sftp_v345_symlink},
+ {SSH_FXP_EXTENDED, sftp_vany_extended}};
static const struct sftpextension v3_extensions[] = {
- { "fsync@openssh.com", "1", sftp_vany_fsync },
- { "hardlink@openssh.com", "1", sftp_vany_hardlink },
- { "posix-rename@openssh.com", "1", sftp_vany_posix_rename },
- { "posix-rename@openssh.org", "", sftp_vany_posix_rename },
- { "space-available", "", sftp_vany_space_available },
- { "statfs@openssh.org", "", sftp_vany_statfs },
- { "statvfs@openssh.com", "2", sftp_vany_statvfs },
- { "fstatvfs@openssh.com", "2", sftp_vany_fstatvfs },
+ {"fsync@openssh.com", "1", sftp_vany_fsync},
+ {"hardlink@openssh.com", "1", sftp_vany_hardlink},
+ {"posix-rename@openssh.com", "1", sftp_vany_posix_rename},
+ {"posix-rename@openssh.org", "", sftp_vany_posix_rename},
+ {"space-available", "", sftp_vany_space_available},
+ {"statfs@openssh.org", "", sftp_vany_statfs},
+ {"statvfs@openssh.com", "2", sftp_vany_statvfs},
+ {"fstatvfs@openssh.com", "2", sftp_vany_fstatvfs},
};
const struct sftpprotocol sftp_v3 = {
- sizeof sftpv3tab / sizeof (struct sftpcmd), /* ncommands */
- sftpv3tab, /* commands */
- 3, /* version */
- (SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_PERMISSIONS
- |SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME
- |SSH_FILEXFER_ATTR_UIDGID), /* attrmask */
- SSH_FX_OP_UNSUPPORTED, /* maxstatus */
- v3_sendnames,
- v3_sendattrs,
- v3_parseattrs,
- sftp_v3_encode,
- v3_decode,
- sizeof v3_extensions / sizeof (struct sftpextension),
- v3_extensions, /* extensions */
+ sizeof sftpv3tab / sizeof(struct sftpcmd), /* ncommands */
+ sftpv3tab, /* commands */
+ 3, /* version */
+ (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+ SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+ SSH_FILEXFER_ATTR_UIDGID), /* attrmask */
+ SSH_FX_OP_UNSUPPORTED, /* maxstatus */
+ v3_sendnames,
+ v3_sendattrs,
+ v3_parseattrs,
+ sftp_v3_encode,
+ v3_decode,
+ sizeof v3_extensions / sizeof(struct sftpextension),
+ v3_extensions, /* extensions */
};
/*
diff --git a/v4.c b/v4.c
index 4a2084b..5441571 100644
--- a/v4.c
+++ b/v4.c
@@ -29,16 +29,15 @@
#include "stat.h"
#include "handle.h"
#include "serialize.h"
+#include "utils.h"
#include <string.h>
-int sftp_v456_encode(struct sftpjob *job,
- char **path) {
+int sftp_v456_encode(struct sftpjob *job, char **path) {
/* Translate local to UTF-8 */
return sftp_iconv(job->a, job->worker->local_to_utf8, path);
}
-uint32_t sftp_v456_decode(struct sftpjob *job,
- char **path) {
+uint32_t sftp_v456_decode(struct sftpjob *job, char **path) {
/* Empty path means default directory */
if(!**path)
*path = (char *)".";
@@ -49,8 +48,7 @@ uint32_t sftp_v456_decode(struct sftpjob *job,
return SSH_FX_OK;
}
-void sftp_v456_sendattrs(struct sftpjob *job,
- const struct sftpattr *attrs) {
+void sftp_v456_sendattrs(struct sftpjob *job, const struct sftpattr *attrs) {
const uint32_t valid = attrs->valid & protocol->attrmask;
sftp_send_uint32(job->worker, valid);
@@ -110,12 +108,12 @@ void sftp_v456_sendattrs(struct sftpjob *job,
uint32_t sftp_v456_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
uint32_t n, rc;
- memset(attrs, 0, sizeof *attrs);
+ sftp_memset(attrs, 0, sizeof *attrs);
if((rc = sftp_parse_uint32(job, &attrs->valid)) != SSH_FX_OK)
return rc;
if((attrs->valid & protocol->attrmask) != attrs->valid) {
- D(("received attrs %#x but protocol %d only supports %#x",
- attrs->valid, protocol->version, protocol->attrmask));
+ D(("received attrs %#x but protocol %d only supports %#x", attrs->valid,
+ protocol->version, protocol->attrmask));
attrs->valid = 0;
return SSH_FX_BAD_MESSAGE;
}
@@ -135,28 +133,33 @@ uint32_t sftp_v456_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
return rc;
}
if(attrs->valid & SSH_FILEXFER_ATTR_ACCESSTIME) {
- if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->atime.seconds)) != SSH_FX_OK)
+ if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->atime.seconds)) !=
+ SSH_FX_OK)
return rc;
if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
if((rc = sftp_parse_uint32(job, &attrs->atime.nanoseconds)) != SSH_FX_OK)
return rc;
}
if(attrs->valid & SSH_FILEXFER_ATTR_CREATETIME) {
- if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->createtime.seconds)) != SSH_FX_OK)
+ if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->createtime.seconds)) !=
+ SSH_FX_OK)
return rc;
if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
- if((rc = sftp_parse_uint32(job, &attrs->createtime.nanoseconds)) != SSH_FX_OK)
+ if((rc = sftp_parse_uint32(job, &attrs->createtime.nanoseconds)) !=
+ SSH_FX_OK)
return rc;
}
if(attrs->valid & SSH_FILEXFER_ATTR_MODIFYTIME) {
- if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->mtime.seconds)) != SSH_FX_OK)
+ if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->mtime.seconds)) !=
+ SSH_FX_OK)
return rc;
if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
if((rc = sftp_parse_uint32(job, &attrs->mtime.nanoseconds)) != SSH_FX_OK)
return rc;
}
if(attrs->valid & SSH_FILEXFER_ATTR_CTIME) {
- if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->ctime.seconds)) != SSH_FX_OK)
+ if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->ctime.seconds)) !=
+ SSH_FX_OK)
return rc;
if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
if((rc = sftp_parse_uint32(job, &attrs->ctime.nanoseconds)) != SSH_FX_OK)
@@ -206,8 +209,8 @@ uint32_t sftp_v456_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
/* Send a filename list as found in an SSH_FXP_NAME response. The response
* header and so on must be generated by the caller. */
-void sftp_v456_sendnames(struct sftpjob *job,
- int nnames, const struct sftpattr *names) {
+void sftp_v456_sendnames(struct sftpjob *job, int nnames,
+ const struct sftpattr *names) {
/* We'd like to know what year we're in for dates in longname */
sftp_send_uint32(job->worker, nnames);
while(nnames > 0) {
@@ -220,7 +223,7 @@ void sftp_v456_sendnames(struct sftpjob *job,
/* Command code for the various _*STAT calls. rc is the return value
* from *stat() and SB is the buffer. */
-static uint32_t sftp_v456_stat_core(struct sftpjob *job, int rc,
+static uint32_t sftp_v456_stat_core(struct sftpjob *job, int rc,
const struct stat *sb, const char *path) {
struct sftpattr attrs;
uint32_t flags;
@@ -263,65 +266,61 @@ uint32_t sftp_v456_fstat(struct sftpjob *job) {
uint32_t rc;
pcheck(sftp_parse_handle(job, &id));
- D(("sftp_fstat %"PRIu32" %"PRIu32, id.id, id.tag));
+ D(("sftp_fstat %" PRIu32 " %" PRIu32, id.id, id.tag));
if((rc = sftp_handle_get_fd(&id, &fd, 0)))
return rc;
return sftp_v456_stat_core(job, fstat(fd, &sb), &sb, 0);
}
static const struct sftpcmd sftpv4tab[] = {
- { SSH_FXP_INIT, sftp_vany_already_init },
- { SSH_FXP_OPEN, sftp_v34_open },
- { SSH_FXP_CLOSE, sftp_vany_close },
- { SSH_FXP_READ, sftp_vany_read },
- { SSH_FXP_WRITE, sftp_vany_write },
- { SSH_FXP_LSTAT, sftp_v456_lstat },
- { SSH_FXP_FSTAT, sftp_v456_fstat },
- { SSH_FXP_SETSTAT, sftp_vany_setstat },
- { SSH_FXP_FSETSTAT, sftp_vany_fsetstat },
- { SSH_FXP_OPENDIR, sftp_vany_opendir },
- { SSH_FXP_READDIR, sftp_vany_readdir },
- { SSH_FXP_REMOVE, sftp_vany_remove },
- { SSH_FXP_MKDIR, sftp_vany_mkdir },
- { SSH_FXP_RMDIR, sftp_vany_rmdir },
- { SSH_FXP_REALPATH, sftp_v345_realpath },
- { SSH_FXP_STAT, sftp_v456_stat },
- { SSH_FXP_RENAME, sftp_v34_rename },
- { SSH_FXP_READLINK, sftp_vany_readlink },
- { SSH_FXP_SYMLINK, sftp_v345_symlink },
- { SSH_FXP_EXTENDED, sftp_vany_extended }
-};
+ {SSH_FXP_INIT, sftp_vany_already_init},
+ {SSH_FXP_OPEN, sftp_v34_open},
+ {SSH_FXP_CLOSE, sftp_vany_close},
+ {SSH_FXP_READ, sftp_vany_read},
+ {SSH_FXP_WRITE, sftp_vany_write},
+ {SSH_FXP_LSTAT, sftp_v456_lstat},
+ {SSH_FXP_FSTAT, sftp_v456_fstat},
+ {SSH_FXP_SETSTAT, sftp_vany_setstat},
+ {SSH_FXP_FSETSTAT, sftp_vany_fsetstat},
+ {SSH_FXP_OPENDIR, sftp_vany_opendir},
+ {SSH_FXP_READDIR, sftp_vany_readdir},
+ {SSH_FXP_REMOVE, sftp_vany_remove},
+ {SSH_FXP_MKDIR, sftp_vany_mkdir},
+ {SSH_FXP_RMDIR, sftp_vany_rmdir},
+ {SSH_FXP_REALPATH, sftp_v345_realpath},
+ {SSH_FXP_STAT, sftp_v456_stat},
+ {SSH_FXP_RENAME, sftp_v34_rename},
+ {SSH_FXP_READLINK, sftp_vany_readlink},
+ {SSH_FXP_SYMLINK, sftp_v345_symlink},
+ {SSH_FXP_EXTENDED, sftp_vany_extended}};
static const struct sftpextension v4_extensions[] = {
- { "fsync@openssh.com", "1", sftp_vany_fsync },
- { "hardlink@openssh.com", "1", sftp_vany_hardlink },
- { "posix-rename@openssh.com", "1", sftp_vany_posix_rename },
- { "posix-rename@openssh.org", "", sftp_vany_posix_rename },
- { "space-available", "", sftp_vany_space_available },
- { "statfs@openssh.org", "", sftp_vany_statfs },
- { "text-seek", "", sftp_vany_text_seek },
- { "statvfs@openssh.com", "2", sftp_vany_statvfs },
- { "fstatvfs@openssh.com", "2", sftp_vany_fstatvfs },
+ {"fsync@openssh.com", "1", sftp_vany_fsync},
+ {"hardlink@openssh.com", "1", sftp_vany_hardlink},
+ {"posix-rename@openssh.com", "1", sftp_vany_posix_rename},
+ {"posix-rename@openssh.org", "", sftp_vany_posix_rename},
+ {"space-available", "", sftp_vany_space_available},
+ {"statfs@openssh.org", "", sftp_vany_statfs},
+ {"text-seek", "", sftp_vany_text_seek},
+ {"statvfs@openssh.com", "2", sftp_vany_statvfs},
+ {"fstatvfs@openssh.com", "2", sftp_vany_fstatvfs},
};
const struct sftpprotocol sftp_v4 = {
- sizeof sftpv4tab / sizeof (struct sftpcmd),
- sftpv4tab,
- 4,
- (SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_PERMISSIONS
- |SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME
- |SSH_FILEXFER_ATTR_OWNERGROUP
- |SSH_FILEXFER_ATTR_SUBSECOND_TIMES),
- SSH_FX_NO_MEDIA,
- sftp_v456_sendnames,
- sftp_v456_sendattrs,
- sftp_v456_parseattrs,
- sftp_v456_encode,
- sftp_v456_decode,
- sizeof v4_extensions / sizeof (struct sftpextension),
- v4_extensions, /* extensions */
+ sizeof sftpv4tab / sizeof(struct sftpcmd),
+ sftpv4tab,
+ 4,
+ (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+ SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+ SSH_FILEXFER_ATTR_OWNERGROUP | SSH_FILEXFER_ATTR_SUBSECOND_TIMES),
+ SSH_FX_NO_MEDIA,
+ sftp_v456_sendnames,
+ sftp_v456_sendattrs,
+ sftp_v456_parseattrs,
+ sftp_v456_encode,
+ sftp_v456_decode,
+ sizeof v4_extensions / sizeof(struct sftpextension),
+ v4_extensions, /* extensions */
};
/*
diff --git a/v5.c b/v5.c
index 23d690f..8790ca1 100644
--- a/v5.c
+++ b/v5.c
@@ -45,13 +45,13 @@ uint32_t sftp_v56_open(struct sftpjob *job) {
pcheck(sftp_parse_uint32(job, &desired_access));
pcheck(sftp_parse_uint32(job, &flags));
pcheck(protocol->parseattrs(job, &attrs));
- D(("sftp_v56_open %s %#"PRIx32" %#"PRIx32, path, desired_access, flags));
+ D(("sftp_v56_open %s %#" PRIx32 " %#" PRIx32, path, desired_access, flags));
return sftp_generic_open(job, path, desired_access, flags, &attrs);
}
uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
- uint32_t desired_access, uint32_t flags,
- struct sftpattr *attrs) {
+ uint32_t desired_access, uint32_t flags,
+ struct sftpattr *attrs) {
mode_t initial_permissions;
int created, open_flags, fd;
struct stat sb;
@@ -59,7 +59,8 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
unsigned sftp_handle_flags = 0;
uint32_t rc;
- D(("sftp_generic_open %s %#"PRIx32" %#"PRIx32, path, desired_access, flags));
+ D(("sftp_generic_open %s %#" PRIx32 " %#" PRIx32, path, desired_access,
+ flags));
/* Check owner/group */
if((rc = sftp_normalize_ownergroup(job->a, attrs)) != SSH_FX_OK)
return rc;
@@ -75,15 +76,13 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
* the specification taken literally prohibits UNIX implementations, I assume
* that it is in error.
*/
- switch(desired_access & (ACE4_READ_DATA|ACE4_WRITE_DATA)) {
- case 0: /* probably a broken client */
+ switch(desired_access & (ACE4_READ_DATA | ACE4_WRITE_DATA)) {
+ case 0: /* probably a broken client */
case ACE4_READ_DATA:
D(("O_RDONLY"));
open_flags = O_RDONLY;
- if(desired_access & (ACE4_WRITE_NAMED_ATTRS
- |ACE4_WRITE_ATTRIBUTES
- |ACE4_WRITE_ACL
- |ACE4_WRITE_OWNER))
+ if(desired_access & (ACE4_WRITE_NAMED_ATTRS | ACE4_WRITE_ATTRIBUTES |
+ ACE4_WRITE_ACL | ACE4_WRITE_OWNER))
return SSH_FX_PERMISSION_DENIED;
break;
case ACE4_WRITE_DATA:
@@ -91,38 +90,37 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
return SSH_FX_PERMISSION_DENIED;
D(("O_WRONLY"));
open_flags = O_WRONLY;
- if(desired_access & (ACE4_READ_NAMED_ATTRS
- |ACE4_READ_ATTRIBUTES
- |ACE4_READ_ACL))
+ if(desired_access &
+ (ACE4_READ_NAMED_ATTRS | ACE4_READ_ATTRIBUTES | ACE4_READ_ACL))
return SSH_FX_PERMISSION_DENIED;
break;
- case ACE4_READ_DATA|ACE4_WRITE_DATA:
+ case ACE4_READ_DATA | ACE4_WRITE_DATA:
if(readonly)
return SSH_FX_PERMISSION_DENIED;
D(("O_RDWR"));
open_flags = O_RDWR;
break;
default:
- fatal("bitwise operators have broken");
+ sftp_fatal("bitwise operators have broken");
}
/* UNIX systems generally do not allow the owner to be changed by
* non-superusers. */
if((desired_access & ACE4_WRITE_OWNER) && getuid())
return SSH_FX_PERMISSION_DENIED;
- /* LIST_DIRECTORY, ADD_FILE, ADD_SUBDIRECTORY and DELETE_CHILD don't make
- * sense for regular files. We ignore them, regarding a grant of permission
- * as not implying that the operation can possibly work.
- *
- * Similary SYNCHRONIZE and EXECUTE we're happy to grant permission for even
- * if there's no way to take advantage of that permission.
- *
- * DELETE is always possible and nothing to do with opening the file.
- */
+ /* LIST_DIRECTORY, ADD_FILE, ADD_SUBDIRECTORY and DELETE_CHILD don't make
+ * sense for regular files. We ignore them, regarding a grant of permission
+ * as not implying that the operation can possibly work.
+ *
+ * Similary SYNCHRONIZE and EXECUTE we're happy to grant permission for even
+ * if there's no way to take advantage of that permission.
+ *
+ * DELETE is always possible and nothing to do with opening the file.
+ */
#ifdef O_NOCTTY
/* We don't want to accidentally acquire a controlling terminal. */
open_flags |= O_NOCTTY;
#endif
- if(flags & (SSH_FXF_APPEND_DATA|SSH_FXF_APPEND_DATA_ATOMIC)) {
+ if(flags & (SSH_FXF_APPEND_DATA | SSH_FXF_APPEND_DATA_ATOMIC)) {
/* We always use O_APPEND for appending so we always give atomic append. */
D(("O_APPEND"));
open_flags |= O_APPEND;
@@ -130,7 +128,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
}
if(flags & SSH_FXF_TEXT_MODE)
sftp_handle_flags |= HANDLE_TEXT;
- if(flags & (SSH_FXF_BLOCK_READ|SSH_FXF_BLOCK_WRITE|SSH_FXF_BLOCK_DELETE))
+ if(flags & (SSH_FXF_BLOCK_READ | SSH_FXF_BLOCK_WRITE | SSH_FXF_BLOCK_DELETE))
return SSH_FX_OP_UNSUPPORTED;
if(flags & SSH_FXF_NOFOLLOW) {
#ifdef O_NOFOLLOW
@@ -154,9 +152,9 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
} else
/* Otherwise be conservative */
initial_permissions = DEFAULT_PERMISSIONS & 0666;
- if(readonly
- && ((flags & SSH_FXF_ACCESS_DISPOSITION) != SSH_FXF_OPEN_EXISTING
- || (flags & SSH_FXF_DELETE_ON_CLOSE))) {
+ if(readonly &&
+ ((flags & SSH_FXF_ACCESS_DISPOSITION) != SSH_FXF_OPEN_EXISTING ||
+ (flags & SSH_FXF_DELETE_ON_CLOSE))) {
return SSH_FX_PERMISSION_DENIED;
}
switch(flags & SSH_FXF_ACCESS_DISPOSITION) {
@@ -165,16 +163,16 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
if(flags & SSH_FXF_NOFOLLOW) {
/* O_EXCL is just right if we don't want to follow links. */
D(("SSH_FXF_CREATE_NEW|SSH_FXF_NOFOLLOW -> O_CREAT|O_EXCL"));
- fd = open(path, open_flags|O_CREAT|O_EXCL, initial_permissions);
+ fd = open(path, open_flags | O_CREAT | O_EXCL, initial_permissions);
created = 1;
} else {
/* O_EXCL will refuse to follow links so that's no good here. We do a
- * racy test and open since that's the best available. */
+ * racy test and open since that's the best available. */
D(("SSH_FXF_CREATE_NEW -> test for existence"));
- if(stat(path, &sb) == 0)
+ if(stat(path, &sb) == 0)
return SSH_FX_FILE_ALREADY_EXISTS;
D(("SSH_FXF_CREATE_NEW -> O_CREAT"));
- fd = open(path, open_flags|O_CREAT, initial_permissions);
+ fd = open(path, open_flags | O_CREAT, initial_permissions);
created = 1;
}
break;
@@ -188,7 +186,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
D(("SSH_FXF_OPEN_OR_TRUNCATE -> not O_TRUNC"));
if(flags & SSH_FXF_NOFOLLOW) {
D(("SSH_FXF_*|SSH_FXF_NOFOLLOW -> O_CREAT|O_EXCL"));
- fd = open(path, open_flags|O_CREAT|O_EXCL, initial_permissions);
+ fd = open(path, open_flags | O_CREAT | O_EXCL, initial_permissions);
if(fd >= 0)
/* The file did not exist before */
created = 1;
@@ -204,7 +202,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
fd = open(path, open_flags, initial_permissions);
created = 0;
} else
- created = 0; /* quieten compiler */
+ created = 0; /* quieten compiler */
} else {
/* As above we cannot use O_EXCL in this case as it'll refuse to follow
* symlinks. */
@@ -220,7 +218,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
* you get that file (perhaps truncated)! We can't use O_EXCL here
* because as observed so there is really no way round this. */
D(("SSH_FXF_* -> O_CREAT"));
- fd = open(path, open_flags|O_CREAT, initial_permissions);
+ fd = open(path, open_flags | O_CREAT, initial_permissions);
created = 0;
}
}
@@ -250,7 +248,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
}
#endif
D(("SSH_FXF_TRUNCATE_EXISTING -> O_TRUNC"));
- fd = open(path, open_flags|O_TRUNC, initial_permissions);
+ fd = open(path, open_flags | O_TRUNC, initial_permissions);
created = 0;
break;
default:
@@ -262,9 +260,9 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
return SSH_FX_FILE_IS_A_DIRECTORY;
}
if(fd < 0) {
- if(((flags & SSH_FXF_ACCESS_DISPOSITION) == SSH_FXF_OPEN_EXISTING
- || (flags & SSH_FXF_ACCESS_DISPOSITION) == SSH_FXF_TRUNCATE_EXISTING)
- && errno == ENOENT) {
+ if(((flags & SSH_FXF_ACCESS_DISPOSITION) == SSH_FXF_OPEN_EXISTING ||
+ (flags & SSH_FXF_ACCESS_DISPOSITION) == SSH_FXF_TRUNCATE_EXISTING) &&
+ errno == ENOENT) {
/* The client could do the extra check but at the cost of a round trip,
* so it makes some sense to do it and return the alternative status.
* This is of rather limited use as the client has no way to know that we
@@ -272,14 +270,13 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
* alternative error message might clue in users occasionally. */
if(lstat(sftp_dirname(job->a, path), &sb) < 0)
return SSH_FX_NO_SUCH_PATH;
- errno = ENOENT; /* restore errno just in case */
+ errno = ENOENT; /* restore errno just in case */
}
#ifdef O_NOFOLLOW
/* If we couldn't open the file because we declined to follow a symlink
* then we need an unusual error code. (But if we had to emulate
* O_NOFOLLOW then the test already happened long ago.) */
- if((flags & SSH_FXF_NOFOLLOW)
- && (errno == ENOENT || errno == EEXIST)) {
+ if((flags & SSH_FXF_NOFOLLOW) && (errno == ENOENT || errno == EEXIST)) {
if(lstat(path, &sb) < 0)
return HANDLER_ERRNO;
if(S_ISLNK(sb.st_mode))
@@ -289,7 +286,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
return HANDLER_ERRNO;
}
/* Set initial attributrs if we created the file */
- if(created && attrs->valid && (rc = sftp_set_fstatus(job->a, fd, attrs, 0))) {
+ if(created && attrs->valid && (rc = sftp_set_fstatus(job->a, fd, attrs, 0))) {
const int save_errno = errno;
close(fd);
unlink(path);
@@ -304,7 +301,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
unlink(path);
}
sftp_handle_new_file(&id, fd, path, sftp_handle_flags);
- D(("...handle is %"PRIu32" %"PRIu32, id.id, id.tag));
+ D(("...handle is %" PRIu32 " %" PRIu32, id.id, id.tag));
sftp_send_begin(job->worker);
sftp_send_uint8(job->worker, SSH_FXP_HANDLE);
sftp_send_uint32(job->worker, job->id);
@@ -322,9 +319,9 @@ uint32_t sftp_v56_rename(struct sftpjob *job) {
pcheck(sftp_parse_path(job, &oldpath));
pcheck(sftp_parse_path(job, &newpath));
pcheck(sftp_parse_uint32(job, &flags));
- D(("sftp_v56_rename %s %s %#"PRIx32, oldpath, newpath, flags));
+ D(("sftp_v56_rename %s %s %#" PRIx32, oldpath, newpath, flags));
- if(flags & (SSH_FXF_RENAME_NATIVE|SSH_FXF_RENAME_OVERWRITE)) {
+ if(flags & (SSH_FXF_RENAME_NATIVE | SSH_FXF_RENAME_OVERWRITE)) {
/* We asked for an overwriting rename (or a native one, in which case we're
* allowed to do any old thing). We are guaranteed that rename() is atomic
* in the required sense on UNIX systems ("In this case, a link named new
@@ -343,17 +340,17 @@ uint32_t sftp_v56_rename(struct sftpjob *job) {
#ifndef __linux__
{
struct stat sb;
-
+
if(lstat(newpath, &sb) == 0)
return SSH_FX_FILE_ALREADY_EXISTS;
}
#endif
- if(rename(oldpath, newpath) < 0)
- return HANDLER_ERRNO;
- else
- return SSH_FX_OK;
+ if(rename(oldpath, newpath) < 0)
+ return HANDLER_ERRNO;
+ else
+ return SSH_FX_OK;
} else
- return SSH_FX_FILE_ALREADY_EXISTS;
+ return SSH_FX_FILE_ALREADY_EXISTS;
} else if(unlink(oldpath) < 0) {
const int save_errno = errno;
@@ -388,17 +385,17 @@ uint32_t sftp_vany_text_seek(struct sftpjob *job) {
}
/* Look for the right line */
i = 0;
- n = 0; /* quieten compiler */
- D(("on entry: line=%"PRIu64, line));
+ n = 0; /* quieten compiler */
+ D(("on entry: line=%" PRIu64, line));
while(line > 0 && (n = read(fd, buffer, sizeof buffer)) > 0) {
- D(("outer: line=%"PRIu64" n=%zd", line, n));
+ D(("outer: line=%" PRIu64 " n=%zd", line, n));
i = 0;
while(line > 0 && i < n) {
if(buffer[i++] == '\n')
- --line;
+ --line;
}
}
- D(("exited:: line=%"PRIu64" n=%zd i=%zd", line, n, i));
+ D(("exited:: line=%" PRIu64 " n=%zd i=%zd", line, n, i));
if(n < 0)
return HANDLER_ERRNO;
else if(n == 0)
@@ -444,8 +441,9 @@ uint32_t sftp_vany_extended(struct sftpjob *job) {
D(("extension %s", name));
/* TODO when we have nontrivially many extensions we should use a binary
* search here. */
- for(n = 0; (n < protocol->nextensions
- && strcmp(name, protocol->extensions[n].name)); ++n)
+ for(n = 0;
+ (n < protocol->nextensions && strcmp(name, protocol->extensions[n].name));
+ ++n)
;
if(n >= protocol->nextensions)
return SSH_FX_OP_UNSUPPORTED;
@@ -454,59 +452,55 @@ uint32_t sftp_vany_extended(struct sftpjob *job) {
}
static const struct sftpcmd sftpv5tab[] = {
- { SSH_FXP_INIT, sftp_vany_already_init },
- { SSH_FXP_OPEN, sftp_v56_open },
- { SSH_FXP_CLOSE, sftp_vany_close },
- { SSH_FXP_READ, sftp_vany_read },
- { SSH_FXP_WRITE, sftp_vany_write },
- { SSH_FXP_LSTAT, sftp_v456_lstat },
- { SSH_FXP_FSTAT, sftp_v456_fstat },
- { SSH_FXP_SETSTAT, sftp_vany_setstat },
- { SSH_FXP_FSETSTAT, sftp_vany_fsetstat },
- { SSH_FXP_OPENDIR, sftp_vany_opendir },
- { SSH_FXP_READDIR, sftp_vany_readdir },
- { SSH_FXP_REMOVE, sftp_vany_remove },
- { SSH_FXP_MKDIR, sftp_vany_mkdir },
- { SSH_FXP_RMDIR, sftp_vany_rmdir },
- { SSH_FXP_REALPATH, sftp_v345_realpath },
- { SSH_FXP_STAT, sftp_v456_stat },
- { SSH_FXP_RENAME, sftp_v56_rename },
- { SSH_FXP_READLINK, sftp_vany_readlink },
- { SSH_FXP_SYMLINK, sftp_v345_symlink },
- { SSH_FXP_EXTENDED, sftp_vany_extended }
-};
+ {SSH_FXP_INIT, sftp_vany_already_init},
+ {SSH_FXP_OPEN, sftp_v56_open},
+ {SSH_FXP_CLOSE, sftp_vany_close},
+ {SSH_FXP_READ, sftp_vany_read},
+ {SSH_FXP_WRITE, sftp_vany_write},
+ {SSH_FXP_LSTAT, sftp_v456_lstat},
+ {SSH_FXP_FSTAT, sftp_v456_fstat},
+ {SSH_FXP_SETSTAT, sftp_vany_setstat},
+ {SSH_FXP_FSETSTAT, sftp_vany_fsetstat},
+ {SSH_FXP_OPENDIR, sftp_vany_opendir},
+ {SSH_FXP_READDIR, sftp_vany_readdir},
+ {SSH_FXP_REMOVE, sftp_vany_remove},
+ {SSH_FXP_MKDIR, sftp_vany_mkdir},
+ {SSH_FXP_RMDIR, sftp_vany_rmdir},
+ {SSH_FXP_REALPATH, sftp_v345_realpath},
+ {SSH_FXP_STAT, sftp_v456_stat},
+ {SSH_FXP_RENAME, sftp_v56_rename},
+ {SSH_FXP_READLINK, sftp_vany_readlink},
+ {SSH_FXP_SYMLINK, sftp_v345_symlink},
+ {SSH_FXP_EXTENDED, sftp_vany_extended}};
static const struct sftpextension sftp_v5_extensions[] = {
- { "fsync@openssh.com", "1", sftp_vany_fsync },
- { "hardlink@openssh.com", "1", sftp_vany_hardlink },
- { "posix-rename@openssh.com", "1", sftp_vany_posix_rename },
- { "posix-rename@openssh.org", "", sftp_vany_posix_rename },
- { "space-available", "", sftp_vany_space_available },
- { "statfs@openssh.org", "", sftp_vany_statfs },
- { "text-seek", "", sftp_vany_text_seek },
- { "statvfs@openssh.com", "2", sftp_vany_statvfs },
- { "fstatvfs@openssh.com", "2", sftp_vany_fstatvfs },
+ {"fsync@openssh.com", "1", sftp_vany_fsync},
+ {"hardlink@openssh.com", "1", sftp_vany_hardlink},
+ {"posix-rename@openssh.com", "1", sftp_vany_posix_rename},
+ {"posix-rename@openssh.org", "", sftp_vany_posix_rename},
+ {"space-available", "", sftp_vany_space_available},
+ {"statfs@openssh.org", "", sftp_vany_statfs},
+ {"text-seek", "", sftp_vany_text_seek},
+ {"statvfs@openssh.com", "2", sftp_vany_statvfs},
+ {"fstatvfs@openssh.com", "2", sftp_vany_fstatvfs},
};
const struct sftpprotocol sftp_v5 = {
- sizeof sftpv5tab / sizeof (struct sftpcmd),
- sftpv5tab,
- 5,
- (SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_PERMISSIONS
- |SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME
- |SSH_FILEXFER_ATTR_OWNERGROUP
- |SSH_FILEXFER_ATTR_SUBSECOND_TIMES
- |SSH_FILEXFER_ATTR_BITS),
- SSH_FX_LOCK_CONFLICT,
- sftp_v456_sendnames,
- sftp_v456_sendattrs,
- sftp_v456_parseattrs,
- sftp_v456_encode,
- sftp_v456_decode,
- sizeof sftp_v5_extensions / sizeof (struct sftpextension),
- sftp_v5_extensions,
+ sizeof sftpv5tab / sizeof(struct sftpcmd),
+ sftpv5tab,
+ 5,
+ (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+ SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+ SSH_FILEXFER_ATTR_OWNERGROUP | SSH_FILEXFER_ATTR_SUBSECOND_TIMES |
+ SSH_FILEXFER_ATTR_BITS),
+ SSH_FX_LOCK_CONFLICT,
+ sftp_v456_sendnames,
+ sftp_v456_sendattrs,
+ sftp_v456_parseattrs,
+ sftp_v456_encode,
+ sftp_v456_decode,
+ sizeof sftp_v5_extensions / sizeof(struct sftpextension),
+ sftp_v5_extensions,
};
/*
diff --git a/v6.c b/v6.c
index 3ca6acb..e557bed 100644
--- a/v6.c
+++ b/v6.c
@@ -28,6 +28,7 @@
#include "debug.h"
#include "utils.h"
#include "globals.h"
+#include "queue.h"
#include <unistd.h>
#include <string.h>
#include <errno.h>
@@ -69,7 +70,7 @@ uint32_t sftp_v6_realpath(struct sftpjob *job) {
break;
case SSH_FXP_REALPATH_STAT_ALWAYS:
/* Follow links and fail if the path doesn't exist */
- rpflags = RP_READLINK|RP_MUST_EXIST;
+ rpflags = RP_READLINK | RP_MUST_EXIST;
break;
default:
return SSH_FX_BAD_MESSAGE;
@@ -80,7 +81,7 @@ uint32_t sftp_v6_realpath(struct sftpjob *job) {
switch(control_byte) {
case SSH_FXP_REALPATH_NO_CHECK:
/* Don't stat, send dummy attributes */
- memset(&attrs, 0, sizeof attrs);
+ sftp_memset(&attrs, 0, sizeof attrs);
attrs.name = resolvedpath;
break;
case SSH_FXP_REALPATH_STAT_IF:
@@ -88,7 +89,7 @@ uint32_t sftp_v6_realpath(struct sftpjob *job) {
if(stat(resolvedpath, &sb) >= 0 || lstat(resolvedpath, &sb) >= 0)
sftp_stat_to_attrs(job->a, &sb, &attrs, 0xFFFFFFFF, resolvedpath);
else {
- memset(&attrs, 0, sizeof attrs);
+ sftp_memset(&attrs, 0, sizeof attrs);
attrs.name = resolvedpath;
}
break;
@@ -118,7 +119,8 @@ uint32_t sftp_v6_link(struct sftpjob *job) {
if(readonly)
return SSH_FX_PERMISSION_DENIED;
pcheck(sftp_parse_path(job, &newlinkpath));
- pcheck(sftp_parse_string(job, &oldpath, 0)); /* aka existing-path/target-paths */
+ pcheck(
+ sftp_parse_string(job, &oldpath, 0)); /* aka existing-path/target-paths */
pcheck(sftp_parse_uint8(job, &symbolic));
D(("sftp_link %s %s [%s]", oldpath, newlinkpath,
symbolic ? "symbolic" : "hard"));
@@ -156,76 +158,85 @@ uint32_t sftp_v6_version_select(struct sftpjob *job) {
if(!workqueue) {
pcheck(sftp_parse_path(job, &newversion));
/* Handle known versions */
- if(!strcmp(newversion, "3")) { protocol = &sftp_v3; return SSH_FX_OK; }
- if(!strcmp(newversion, "4")) { protocol = &sftp_v4; return SSH_FX_OK; }
- if(!strcmp(newversion, "5")) { protocol = &sftp_v5; return SSH_FX_OK; }
- if(!strcmp(newversion, "6")) { protocol = &sftp_v6; return SSH_FX_OK; }
+ if(!strcmp(newversion, "3")) {
+ protocol = &sftp_v3;
+ return SSH_FX_OK;
+ }
+ if(!strcmp(newversion, "4")) {
+ protocol = &sftp_v4;
+ return SSH_FX_OK;
+ }
+ if(!strcmp(newversion, "5")) {
+ protocol = &sftp_v5;
+ return SSH_FX_OK;
+ }
+ if(!strcmp(newversion, "6")) {
+ protocol = &sftp_v6;
+ return SSH_FX_OK;
+ }
sftp_send_status(job, SSH_FX_INVALID_PARAMETER, "unknown version");
} else
- sftp_send_status(job, SSH_FX_INVALID_PARAMETER, "badly timed version-select");
+ sftp_send_status(job, SSH_FX_INVALID_PARAMETER,
+ "badly timed version-select");
/* We MUST close the channel. (-13, s5.5). */
- exit(-1);
+ sftp_state_set(sftp_state_stop);
+ return HANDLER_RESPONDED; /* even though we sent nothing */
}
static const struct sftpcmd sftpv6tab[] = {
- { SSH_FXP_INIT, sftp_vany_already_init },
- { SSH_FXP_OPEN, sftp_v56_open },
- { SSH_FXP_CLOSE, sftp_vany_close },
- { SSH_FXP_READ, sftp_vany_read },
- { SSH_FXP_WRITE, sftp_vany_write },
- { SSH_FXP_LSTAT, sftp_v456_lstat },
- { SSH_FXP_FSTAT, sftp_v456_fstat },
- { SSH_FXP_SETSTAT, sftp_vany_setstat },
- { SSH_FXP_FSETSTAT, sftp_vany_fsetstat },
- { SSH_FXP_OPENDIR, sftp_vany_opendir },
- { SSH_FXP_READDIR, sftp_vany_readdir },
- { SSH_FXP_REMOVE, sftp_vany_remove },
- { SSH_FXP_MKDIR, sftp_vany_mkdir },
- { SSH_FXP_RMDIR, sftp_vany_rmdir },
- { SSH_FXP_REALPATH, sftp_v6_realpath },
- { SSH_FXP_STAT, sftp_v456_stat },
- { SSH_FXP_RENAME, sftp_v56_rename },
- { SSH_FXP_READLINK, sftp_vany_readlink },
- { SSH_FXP_LINK, sftp_v6_link },
- { SSH_FXP_EXTENDED, sftp_vany_extended }
-};
+ {SSH_FXP_INIT, sftp_vany_already_init},
+ {SSH_FXP_OPEN, sftp_v56_open},
+ {SSH_FXP_CLOSE, sftp_vany_close},
+ {SSH_FXP_READ, sftp_vany_read},
+ {SSH_FXP_WRITE, sftp_vany_write},
+ {SSH_FXP_LSTAT, sftp_v456_lstat},
+ {SSH_FXP_FSTAT, sftp_v456_fstat},
+ {SSH_FXP_SETSTAT, sftp_vany_setstat},
+ {SSH_FXP_FSETSTAT, sftp_vany_fsetstat},
+ {SSH_FXP_OPENDIR, sftp_vany_opendir},
+ {SSH_FXP_READDIR, sftp_vany_readdir},
+ {SSH_FXP_REMOVE, sftp_vany_remove},
+ {SSH_FXP_MKDIR, sftp_vany_mkdir},
+ {SSH_FXP_RMDIR, sftp_vany_rmdir},
+ {SSH_FXP_REALPATH, sftp_v6_realpath},
+ {SSH_FXP_STAT, sftp_v456_stat},
+ {SSH_FXP_RENAME, sftp_v56_rename},
+ {SSH_FXP_READLINK, sftp_vany_readlink},
+ {SSH_FXP_LINK, sftp_v6_link},
+ {SSH_FXP_EXTENDED, sftp_vany_extended}};
/* TODO: file locking */
static const struct sftpextension sftp_v6_extensions[] = {
- { "fsync@openssh.com", "1", sftp_vany_fsync },
- { "hardlink@openssh.com", "1", sftp_vany_hardlink },
- { "posix-rename@openssh.com", "1", sftp_vany_posix_rename },
- { "posix-rename@openssh.org", "", sftp_vany_posix_rename },
- { "space-available", "", sftp_vany_space_available },
- { "statfs@openssh.org", "", sftp_vany_statfs },
- { "text-seek", "", sftp_vany_text_seek },
- { "version-select", "", sftp_v6_version_select },
- { "statvfs@openssh.com", "2", sftp_vany_statvfs },
- { "fstatvfs@openssh.com", "2", sftp_vany_fstatvfs },
+ {"fsync@openssh.com", "1", sftp_vany_fsync},
+ {"hardlink@openssh.com", "1", sftp_vany_hardlink},
+ {"posix-rename@openssh.com", "1", sftp_vany_posix_rename},
+ {"posix-rename@openssh.org", "", sftp_vany_posix_rename},
+ {"space-available", "", sftp_vany_space_available},
+ {"statfs@openssh.org", "", sftp_vany_statfs},
+ {"text-seek", "", sftp_vany_text_seek},
+ {"version-select", "", sftp_v6_version_select},
+ {"statvfs@openssh.com", "2", sftp_vany_statvfs},
+ {"fstatvfs@openssh.com", "2", sftp_vany_fstatvfs},
};
const struct sftpprotocol sftp_v6 = {
- sizeof sftpv6tab / sizeof (struct sftpcmd),
- sftpv6tab,
- 6,
- (SSH_FILEXFER_ATTR_SIZE
- |SSH_FILEXFER_ATTR_PERMISSIONS
- |SSH_FILEXFER_ATTR_ACCESSTIME
- |SSH_FILEXFER_ATTR_CTIME
- |SSH_FILEXFER_ATTR_MODIFYTIME
- |SSH_FILEXFER_ATTR_OWNERGROUP
- |SSH_FILEXFER_ATTR_SUBSECOND_TIMES
- |SSH_FILEXFER_ATTR_BITS
- |SSH_FILEXFER_ATTR_LINK_COUNT),
- SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK,
- sftp_v456_sendnames,
- sftp_v456_sendattrs,
- sftp_v456_parseattrs,
- sftp_v456_encode,
- sftp_v456_decode,
- sizeof sftp_v6_extensions / sizeof (struct sftpextension),
- sftp_v6_extensions,
+ sizeof sftpv6tab / sizeof(struct sftpcmd),
+ sftpv6tab,
+ 6,
+ (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+ SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_CTIME |
+ SSH_FILEXFER_ATTR_MODIFYTIME | SSH_FILEXFER_ATTR_OWNERGROUP |
+ SSH_FILEXFER_ATTR_SUBSECOND_TIMES | SSH_FILEXFER_ATTR_BITS |
+ SSH_FILEXFER_ATTR_LINK_COUNT),
+ SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK,
+ sftp_v456_sendnames,
+ sftp_v456_sendattrs,
+ sftp_v456_parseattrs,
+ sftp_v456_encode,
+ sftp_v456_decode,
+ sizeof sftp_v6_extensions / sizeof(struct sftpextension),
+ sftp_v6_extensions,
};
/*
diff --git a/xfns.c b/xfns.c
index 014c0c2..0b4d2e1 100644
--- a/xfns.c
+++ b/xfns.c
@@ -27,22 +27,22 @@
#include <stdarg.h>
#include <stdio.h>
-void xclose(int fd) {
+void sftp_xclose(int fd) {
if(close(fd) < 0)
- fatal("error calling close: %s", strerror(errno));
+ sftp_fatal("error calling close: %s", strerror(errno));
}
-void xdup2(int fd, int newfd) {
+void sftp_xdup2(int fd, int newfd) {
if(dup2(fd, newfd) < 0)
- fatal("error calling dup2: %s", strerror(errno));
+ sftp_fatal("error calling dup2: %s", strerror(errno));
}
-void xpipe(int *pfd) {
+void sftp_xpipe(int *pfd) {
if(pipe(pfd) < 0)
- fatal("error calling pipe: %s", strerror(errno));
+ sftp_fatal("error calling pipe: %s", strerror(errno));
}
-int xprintf(const char *fmt, ...) {
+int sftp_xprintf(const char *fmt, ...) {
va_list ap;
int rc;
@@ -50,7 +50,7 @@ int xprintf(const char *fmt, ...) {
rc = vfprintf(stdout, fmt, ap);
va_end(ap);
if(rc < 0)
- fatal("error writing to stdout: %s", strerror(errno));
+ sftp_fatal("error writing to stdout: %s", strerror(errno));
return rc;
}
diff --git a/xfns.h b/xfns.h
index f53d929..3d84c3e 100644
--- a/xfns.h
+++ b/xfns.h
@@ -21,38 +21,38 @@
/** @file xfns.h @brief Die-on-error utility function interface */
#ifndef XFNS_H
-#define XFNS_H
+# define XFNS_H
/** @brief Close @p fd
* @param fd File descriptor to close
*
- * Calls fatal() on error.
+ * Calls sftp_fatal() on error.
*/
-void xclose(int fd);
+void sftp_xclose(int fd);
/** @brief Duplicate @p fd
* @param fd File descriptor to duplicate
* @param newfd New file descriptor
*
- * Calls fatal() on error.
+ * Calls sftp_fatal() on error.
*/
-void xdup2(int fd, int newfd);
+void sftp_xdup2(int fd, int newfd);
/** @brief Create a pipe
* @param pfd Where to store endpoint file descriptors
*
- * Calls fatal() on error.
+ * Calls sftp_fatal() on error.
*/
-void xpipe(int *pfd);
+void sftp_xpipe(int *pfd);
/** @brief Write to stdout
* @param fmt Format string as per @c printf()
* @param ... Arguments
* @return Number of characters written
*
- * Calls fatal() on error.
+ * Calls sftp_fatal() on error.
*/
-int xprintf(const char *fmt, ...) attribute((format(printf,1,2)));
+int sftp_xprintf(const char *fmt, ...) attribute((format(printf, 1, 2)));
#endif /* XFNS_H */
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/lib/debug/.build-id/c9/ad725ee72e62c80fa42516aad68ea57ff99fd3.debug
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/lib/debug/.build-id/f5/2772528a302cf8099f74d9339c045178bf346a.debug
No differences were encountered between the control files of package gesftpserver
Control files of package gesftpserver-dbgsym: lines which differ (wdiff format)
Build-Ids: f52772528a302cf8099f74d9339c045178bf346a c9ad725ee72e62c80fa42516aad68ea57ff99fd3