diff options
Diffstat (limited to 'sftp-server.c')
-rw-r--r-- | sftp-server.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/sftp-server.c b/sftp-server.c index 1d13e97b2..e82280057 100644 --- a/sftp-server.c +++ b/sftp-server.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | #include "includes.h" | 16 | #include "includes.h" |
17 | RCSID("$OpenBSD: sftp-server.c,v 1.45 2004/02/19 21:15:04 markus Exp $"); | 17 | RCSID("$OpenBSD: sftp-server.c,v 1.47 2004/06/25 05:38:48 dtucker Exp $"); |
18 | 18 | ||
19 | #include "buffer.h" | 19 | #include "buffer.h" |
20 | #include "bufaux.h" | 20 | #include "bufaux.h" |
@@ -31,11 +31,7 @@ RCSID("$OpenBSD: sftp-server.c,v 1.45 2004/02/19 21:15:04 markus Exp $"); | |||
31 | #define get_string(lenp) buffer_get_string(&iqueue, lenp); | 31 | #define get_string(lenp) buffer_get_string(&iqueue, lenp); |
32 | #define TRACE debug | 32 | #define TRACE debug |
33 | 33 | ||
34 | #ifdef HAVE___PROGNAME | ||
35 | extern char *__progname; | 34 | extern char *__progname; |
36 | #else | ||
37 | char *__progname; | ||
38 | #endif | ||
39 | 35 | ||
40 | /* input and output queue */ | 36 | /* input and output queue */ |
41 | Buffer iqueue; | 37 | Buffer iqueue; |
@@ -260,7 +256,7 @@ send_msg(Buffer *m) | |||
260 | } | 256 | } |
261 | 257 | ||
262 | static void | 258 | static void |
263 | send_status(u_int32_t id, u_int32_t error) | 259 | send_status(u_int32_t id, u_int32_t status) |
264 | { | 260 | { |
265 | Buffer msg; | 261 | Buffer msg; |
266 | const char *status_messages[] = { | 262 | const char *status_messages[] = { |
@@ -276,14 +272,14 @@ send_status(u_int32_t id, u_int32_t error) | |||
276 | "Unknown error" /* Others */ | 272 | "Unknown error" /* Others */ |
277 | }; | 273 | }; |
278 | 274 | ||
279 | TRACE("sent status id %u error %u", id, error); | 275 | TRACE("sent status id %u error %u", id, status); |
280 | buffer_init(&msg); | 276 | buffer_init(&msg); |
281 | buffer_put_char(&msg, SSH2_FXP_STATUS); | 277 | buffer_put_char(&msg, SSH2_FXP_STATUS); |
282 | buffer_put_int(&msg, id); | 278 | buffer_put_int(&msg, id); |
283 | buffer_put_int(&msg, error); | 279 | buffer_put_int(&msg, status); |
284 | if (version >= 3) { | 280 | if (version >= 3) { |
285 | buffer_put_cstring(&msg, | 281 | buffer_put_cstring(&msg, |
286 | status_messages[MIN(error,SSH2_FX_MAX)]); | 282 | status_messages[MIN(status,SSH2_FX_MAX)]); |
287 | buffer_put_cstring(&msg, ""); | 283 | buffer_put_cstring(&msg, ""); |
288 | } | 284 | } |
289 | send_msg(&msg); | 285 | send_msg(&msg); |
@@ -839,9 +835,29 @@ process_rename(void) | |||
839 | status = errno_to_portable(errno); | 835 | status = errno_to_portable(errno); |
840 | else if (S_ISREG(sb.st_mode)) { | 836 | else if (S_ISREG(sb.st_mode)) { |
841 | /* Race-free rename of regular files */ | 837 | /* Race-free rename of regular files */ |
842 | if (link(oldpath, newpath) == -1) | 838 | if (link(oldpath, newpath) == -1) { |
843 | status = errno_to_portable(errno); | 839 | if (errno == EOPNOTSUPP |
844 | else if (unlink(oldpath) == -1) { | 840 | #ifdef LINK_OPNOTSUPP_ERRNO |
841 | || errno == LINK_OPNOTSUPP_ERRNO | ||
842 | #endif | ||
843 | ) { | ||
844 | struct stat st; | ||
845 | |||
846 | /* | ||
847 | * fs doesn't support links, so fall back to | ||
848 | * stat+rename. This is racy. | ||
849 | */ | ||
850 | if (stat(newpath, &st) == -1) { | ||
851 | if (rename(oldpath, newpath) == -1) | ||
852 | status = | ||
853 | errno_to_portable(errno); | ||
854 | else | ||
855 | status = SSH2_FX_OK; | ||
856 | } | ||
857 | } else { | ||
858 | status = errno_to_portable(errno); | ||
859 | } | ||
860 | } else if (unlink(oldpath) == -1) { | ||
845 | status = errno_to_portable(errno); | 861 | status = errno_to_portable(errno); |
846 | /* clean spare link */ | 862 | /* clean spare link */ |
847 | unlink(newpath); | 863 | unlink(newpath); |
@@ -863,20 +879,20 @@ process_readlink(void) | |||
863 | { | 879 | { |
864 | u_int32_t id; | 880 | u_int32_t id; |
865 | int len; | 881 | int len; |
866 | char link[MAXPATHLEN]; | 882 | char buf[MAXPATHLEN]; |
867 | char *path; | 883 | char *path; |
868 | 884 | ||
869 | id = get_int(); | 885 | id = get_int(); |
870 | path = get_string(NULL); | 886 | path = get_string(NULL); |
871 | TRACE("readlink id %u path %s", id, path); | 887 | TRACE("readlink id %u path %s", id, path); |
872 | if ((len = readlink(path, link, sizeof(link) - 1)) == -1) | 888 | if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) |
873 | send_status(id, errno_to_portable(errno)); | 889 | send_status(id, errno_to_portable(errno)); |
874 | else { | 890 | else { |
875 | Stat s; | 891 | Stat s; |
876 | 892 | ||
877 | link[len] = '\0'; | 893 | buf[len] = '\0'; |
878 | attrib_clear(&s.attrib); | 894 | attrib_clear(&s.attrib); |
879 | s.name = s.long_name = link; | 895 | s.name = s.long_name = buf; |
880 | send_names(id, 1, &s); | 896 | send_names(id, 1, &s); |
881 | } | 897 | } |
882 | xfree(path); | 898 | xfree(path); |