]> andersk Git - openssh.git/commitdiff
- djm@cvs.openbsd.org 2008/04/18 12:32:11
authordjm <djm>
Mon, 19 May 2008 04:53:33 +0000 (04:53 +0000)
committerdjm <djm>
Mon, 19 May 2008 04:53:33 +0000 (04:53 +0000)
     [sftp-client.c sftp-client.h sftp-server.c sftp.1 sftp.c sftp.h]
     introduce sftp extension methods statvfs@openssh.com and
     fstatvfs@openssh.com that implement statvfs(2)-like operations,
     based on a patch from miklos AT szeredi.hu (bz#1399)
     also add a "df" command to the sftp client that uses the
     statvfs@openssh.com to produce a df(1)-like display of filesystem
     space and inode utilisation
     ok markus@

ChangeLog
sftp-client.c
sftp-client.h
sftp-server.c
sftp.1
sftp.c
sftp.h

index 994800c042470db358f58b914838830e96d2e8e3..6de33a138f9b565756cad27f84b2e8d03b67205a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
      Use arc4random_uniform() when the desired random number upper bound
      is not a power of two
      ok deraadt@ millert@
+   - djm@cvs.openbsd.org 2008/04/18 12:32:11
+     [sftp-client.c sftp-client.h sftp-server.c sftp.1 sftp.c sftp.h]
+     introduce sftp extension methods statvfs@openssh.com and
+     fstatvfs@openssh.com that implement statvfs(2)-like operations,
+     based on a patch from miklos AT szeredi.hu (bz#1399)
+     also add a "df" command to the sftp client that uses the
+     statvfs@openssh.com to produce a df(1)-like display of filesystem
+     space and inode utilisation
+     ok markus@
 
 20080403
  - (djm) [openbsd-compat/bsd-poll.c] Include stdlib.h to avoid compile-
index 69c6377859070b44555df41d8fb5fbe7eb63e286..1e54348b7e24b1c9904abe3724acd7da79194b16 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.c,v 1.81 2008/03/23 12:54:01 djm Exp $ */
+/* $OpenBSD: sftp-client.c,v 1.82 2008/04/18 12:32:11 djm Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
  *
@@ -24,6 +24,7 @@
 
 #include <sys/types.h>
 #include <sys/param.h>
+#include <sys/statvfs.h>
 #include "openbsd-compat/sys-queue.h"
 #ifdef HAVE_SYS_STAT_H
 # include <sys/stat.h>
@@ -65,7 +66,9 @@ struct sftp_conn {
        u_int num_requests;
        u_int version;
        u_int msg_id;
-#define SFTP_EXT_POSIX_RENAME  1
+#define SFTP_EXT_POSIX_RENAME  0x00000001
+#define SFTP_EXT_STATVFS       0x00000002
+#define SFTP_EXT_FSTATVFS      0x00000004
        u_int exts;
 };
 
@@ -238,6 +241,56 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
        return(a);
 }
 
+static int
+get_decode_statvfs(int fd, struct statvfs *st, u_int expected_id, int quiet)
+{
+       Buffer msg;
+       u_int type, id, flag;
+
+       buffer_init(&msg);
+       get_msg(fd, &msg);
+
+       type = buffer_get_char(&msg);
+       id = buffer_get_int(&msg);
+
+       debug3("Received statvfs reply T:%u I:%u", type, id);
+       if (id != expected_id)
+               fatal("ID mismatch (%u != %u)", id, expected_id);
+       if (type == SSH2_FXP_STATUS) {
+               int status = buffer_get_int(&msg);
+
+               if (quiet)
+                       debug("Couldn't statvfs: %s", fx2txt(status));
+               else
+                       error("Couldn't statvfs: %s", fx2txt(status));
+               buffer_free(&msg);
+               return -1;
+       } else if (type != SSH2_FXP_EXTENDED_REPLY) {
+               fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
+                   SSH2_FXP_EXTENDED_REPLY, type);
+       }
+
+       bzero(st, sizeof(*st));
+       st->f_bsize = buffer_get_int(&msg);
+       st->f_frsize = buffer_get_int(&msg);
+       st->f_blocks = buffer_get_int64(&msg);
+       st->f_bfree = buffer_get_int64(&msg);
+       st->f_bavail = buffer_get_int64(&msg);
+       st->f_files = buffer_get_int64(&msg);
+       st->f_ffree = buffer_get_int64(&msg);
+       st->f_favail = buffer_get_int64(&msg);
+       st->f_fsid = buffer_get_int(&msg);
+       flag = buffer_get_int(&msg);
+       st->f_namemax = buffer_get_int(&msg);
+
+       st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
+       st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
+
+       buffer_free(&msg);
+
+       return 0;
+}
+
 struct sftp_conn *
 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
 {
@@ -272,8 +325,15 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
                char *value = buffer_get_string(&msg, NULL);
 
                debug2("Init extension: \"%s\"", name);
-               if (strcmp(name, "posix-rename@openssh.com") == 0)
+               if (strcmp(name, "posix-rename@openssh.com") == 0 &&
+                   strcmp(value, "1") == 0)
                        exts |= SFTP_EXT_POSIX_RENAME;
+               if (strcmp(name, "statvfs@openssh.com") == 0 &&
+                   strcmp(value, "1") == 0)
+                       exts |= SFTP_EXT_STATVFS;
+               if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
+                   strcmp(value, "1") == 0)
+                       exts |= SFTP_EXT_FSTATVFS;
                xfree(name);
                xfree(value);
        }
@@ -749,6 +809,60 @@ do_readlink(struct sftp_conn *conn, char *path)
 }
 #endif
 
+int
+do_statvfs(struct sftp_conn *conn, const char *path, struct statvfs *st,
+    int quiet)
+{
+       Buffer msg;
+       u_int id;
+
+       if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
+               error("Server does not support statvfs@openssh.com extension");
+               return -1;
+       }
+
+       id = conn->msg_id++;
+
+       buffer_init(&msg);
+       buffer_clear(&msg);
+       buffer_put_char(&msg, SSH2_FXP_EXTENDED);
+       buffer_put_int(&msg, id);
+       buffer_put_cstring(&msg, "statvfs@openssh.com");
+       buffer_put_cstring(&msg, path);
+       send_msg(conn->fd_out, &msg);
+       buffer_free(&msg);
+
+       return get_decode_statvfs(conn->fd_in, st, id, quiet);
+}
+
+#ifdef notyet
+int
+do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
+    struct statvfs *st, int quiet)
+{
+       Buffer msg;
+       u_int id;
+
+       if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
+               error("Server does not support fstatvfs@openssh.com extension");
+               return -1;
+       }
+
+       id = conn->msg_id++;
+
+       buffer_init(&msg);
+       buffer_clear(&msg);
+       buffer_put_char(&msg, SSH2_FXP_EXTENDED);
+       buffer_put_int(&msg, id);
+       buffer_put_cstring(&msg, "fstatvfs@openssh.com");
+       buffer_put_string(&msg, handle, handle_len);
+       send_msg(conn->fd_out, &msg);
+       buffer_free(&msg);
+
+       return get_decode_statvfs(conn->fd_in, st, id, quiet);
+}
+#endif
+
 static void
 send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
     char *handle, u_int handle_len)
index fd0630e9a781e95da0a10d3fc9175601b1f7693a..b102e118047752715ca7ad8d648641b5501f2ffe 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.h,v 1.15 2008/01/11 07:22:28 chl Exp $ */
+/* $OpenBSD: sftp-client.h,v 1.16 2008/04/18 12:32:11 djm Exp $ */
 
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
@@ -70,6 +70,10 @@ int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *);
 /* Canonicalise 'path' - caller must free result */
 char *do_realpath(struct sftp_conn *, char *);
 
+/* Get statistics for filesystem hosting file at "path" */
+struct statvfs;
+int do_statvfs(struct sftp_conn *, const char *, struct statvfs *, int);
+
 /* Rename 'oldpath' to 'newpath' */
 int do_rename(struct sftp_conn *, char *, char *);
 
index d9549f5bc66c36be0141cd194c41948014662be5..300fd5cfdb192ca72d4abf48237106bcebed11d1 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-server.c,v 1.78 2008/02/27 20:21:15 djm Exp $ */
+/* $OpenBSD: sftp-server.c,v 1.79 2008/04/18 12:32:11 djm Exp $ */
 /*
  * Copyright (c) 2000-2004 Markus Friedl.  All rights reserved.
  *
@@ -23,6 +23,8 @@
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
 #endif
+#include <sys/mount.h>
+#include <sys/statvfs.h>
 
 #include <dirent.h>
 #include <errno.h>
@@ -475,6 +477,33 @@ send_attrib(u_int32_t id, const Attrib *a)
        buffer_free(&msg);
 }
 
+static void
+send_statvfs(u_int32_t id, struct statvfs *st)
+{
+       Buffer msg;
+       u_int64_t flag;
+
+       flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0;
+       flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0;
+
+       buffer_init(&msg);
+       buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY);
+       buffer_put_int(&msg, id);
+       buffer_put_int(&msg, st->f_bsize);
+       buffer_put_int(&msg, st->f_frsize);
+       buffer_put_int64(&msg, st->f_blocks);
+       buffer_put_int64(&msg, st->f_bfree);
+       buffer_put_int64(&msg, st->f_bavail);
+       buffer_put_int64(&msg, st->f_files);
+       buffer_put_int64(&msg, st->f_ffree);
+       buffer_put_int64(&msg, st->f_favail);
+       buffer_put_int(&msg, st->f_fsid);
+       buffer_put_int(&msg, flag);
+       buffer_put_int(&msg, st->f_namemax);
+       send_msg(&msg);
+       buffer_free(&msg);
+}
+
 /* parse incoming */
 
 static void
@@ -490,6 +519,10 @@ process_init(void)
        /* POSIX rename extension */
        buffer_put_cstring(&msg, "posix-rename@openssh.com");
        buffer_put_cstring(&msg, "1"); /* version */
+       buffer_put_cstring(&msg, "statvfs@openssh.com");
+       buffer_put_cstring(&msg, "1"); /* version */
+       buffer_put_cstring(&msg, "fstatvfs@openssh.com");
+       buffer_put_cstring(&msg, "1"); /* version */
        send_msg(&msg);
        buffer_free(&msg);
 }
@@ -1099,6 +1132,42 @@ process_extended_posix_rename(u_int32_t id)
        xfree(newpath);
 }
 
+static void
+process_extended_statvfs(u_int32_t id)
+{
+       char *path;
+       struct statvfs st;
+
+       path = get_string(NULL);
+       debug3("request %u: statfs", id);
+       logit("statfs \"%s\"", path);
+
+       if (statvfs(path, &st) != 0)
+               send_status(id, errno_to_portable(errno));
+       else
+               send_statvfs(id, &st);
+        xfree(path);
+}
+
+static void
+process_extended_fstatvfs(u_int32_t id)
+{
+       int handle, fd;
+       struct statvfs st;
+
+       handle = get_handle();
+       debug("request %u: fstatvfs \"%s\" (handle %u)",
+           id, handle_to_name(handle), handle);
+       if ((fd = handle_to_fd(handle)) < 0) {
+               send_status(id, SSH2_FX_FAILURE);
+               return;
+       }
+       if (fstatvfs(fd, &st) != 0)
+               send_status(id, errno_to_portable(errno));
+       else
+               send_statvfs(id, &st);
+}
+
 static void
 process_extended(void)
 {
@@ -1109,6 +1178,10 @@ process_extended(void)
        request = get_string(NULL);
        if (strcmp(request, "posix-rename@openssh.com") == 0)
                process_extended_posix_rename(id);
+       else if (strcmp(request, "statvfs@openssh.com") == 0)
+               process_extended_statvfs(id);
+       else if (strcmp(request, "fstatvfs@openssh.com") == 0)
+               process_extended_fstatvfs(id);
        else
                send_status(id, SSH2_FX_OP_UNSUPPORTED);        /* MUST */
        xfree(request);
diff --git a/sftp.1 b/sftp.1
index faf05262987265475c97098e26627f9972809db0..3a8ed924df541fdbe3048ad993b3d536861eda64 100644 (file)
--- a/sftp.1
+++ b/sftp.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sftp.1,v 1.64 2007/05/31 19:20:16 jmc Exp $
+.\" $OpenBSD: sftp.1,v 1.65 2008/04/18 12:32:11 djm Exp $
 .\"
 .\" Copyright (c) 2001 Damien Miller.  All rights reserved.
 .\"
@@ -112,7 +112,7 @@ will abort if any of the following
 commands fail:
 .Ic get , put , rename , ln ,
 .Ic rm , mkdir , chdir , ls ,
-.Ic lchdir , chmod , chown , chgrp , lpwd
+.Ic lchdir , chmod , chown , chgrp , lpwd, df,
 and
 .Ic lmkdir .
 Termination on error can be suppressed on a command by command basis by
@@ -272,6 +272,24 @@ may contain
 characters and may match multiple files.
 .Ar own
 must be a numeric UID.
+.It Xo Ic df
+.Op Fl hi
+.Op Ar path
+.Xc
+Display usage information for the filesystem holding the current directory
+(or
+.Ar path
+if specified).
+If the
+.Fl h
+flag is specified, the capacity information will be displayed using
+"human-readable" suffixes.
+The
+.Fl i
+flag requests display of inode information in addition to capacity information.
+This command is only supported on servers that implement the
+.Dq statvfs@openssh.com
+extension.
 .It Ic exit
 Quit
 .Nm sftp .
diff --git a/sftp.c b/sftp.c
index 861c3db05031c20f239b578705b958671707ecbe..0745baf08136579e2b032c18043eb161140fe068 100644 (file)
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.99 2008/01/20 00:38:30 djm Exp $ */
+/* $OpenBSD: sftp.c,v 1.100 2008/04/18 12:32:11 djm Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
  *
@@ -25,6 +25,7 @@
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
+#include <sys/statvfs.h>
 
 #include <ctype.h>
 #include <errno.h>
@@ -42,6 +43,7 @@ typedef void EditLine;
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <util.h>
 #include <stdarg.h>
 
 #include "xmalloc.h"
@@ -104,6 +106,7 @@ extern char *__progname;
 #define I_CHGRP                2
 #define I_CHMOD                3
 #define I_CHOWN                4
+#define I_DF           24
 #define I_GET          5
 #define I_HELP         6
 #define I_LCHDIR       7
@@ -136,6 +139,7 @@ static const struct CMD cmds[] = {
        { "chgrp",      I_CHGRP },
        { "chmod",      I_CHMOD },
        { "chown",      I_CHOWN },
+       { "df",         I_DF },
        { "dir",        I_LS },
        { "exit",       I_QUIT },
        { "get",        I_GET },
@@ -200,6 +204,8 @@ help(void)
        printf("chgrp grp path                Change group of file 'path' to 'grp'\n");
        printf("chmod mode path               Change permissions of file 'path' to 'mode'\n");
        printf("chown own path                Change owner of file 'path' to 'own'\n");
+       printf("df [path]                     Display statistics for current directory or\n");
+       printf("                              filesystem containing 'path'\n");
        printf("help                          Display this help text\n");
        printf("get remote-path [local-path]  Download file\n");
        printf("lls [ls-options [path]]       Display local directory listing\n");
@@ -421,6 +427,33 @@ parse_ls_flags(char **argv, int argc, int *lflag)
        return optind;
 }
 
+static int
+parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
+{
+       extern int optind, optreset, opterr;
+       int ch;
+
+       optind = optreset = 1;
+       opterr = 0;
+
+       *hflag = *iflag = 0;
+       while ((ch = getopt(argc, argv, "hi")) != -1) {
+               switch (ch) {
+               case 'h':
+                       *hflag = 1;
+                       break;
+               case 'i':
+                       *iflag = 1;
+                       break;
+               default:
+                       error("%s: Invalid flag -%c", cmd, ch);
+                       return -1;
+               }
+       }
+
+       return optind;
+}
+
 static int
 is_dir(char *path)
 {
@@ -797,6 +830,56 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
        return (0);
 }
 
+static int
+do_df(struct sftp_conn *conn, char *path, int hflag, int iflag)
+{
+       struct statvfs st;
+       char s_used[FMT_SCALED_STRSIZE];
+       char s_avail[FMT_SCALED_STRSIZE];
+       char s_root[FMT_SCALED_STRSIZE];
+       char s_total[FMT_SCALED_STRSIZE];
+
+       if (do_statvfs(conn, path, &st, 1) == -1)
+               return -1;
+       if (iflag) {
+               printf("     Inodes        Used       Avail      "
+                   "(root)    %%Capacity\n");
+               printf("%11llu %11llu %11llu %11llu         %3llu%%\n",
+                   (unsigned long long)st.f_files,
+                   (unsigned long long)(st.f_files - st.f_ffree),
+                   (unsigned long long)st.f_favail,
+                   (unsigned long long)st.f_ffree,
+                   (unsigned long long)(100 * (st.f_files - st.f_ffree) /
+                   st.f_files));
+       } else if (hflag) {
+               strlcpy(s_used, "error", sizeof(s_used));
+               strlcpy(s_avail, "error", sizeof(s_avail));
+               strlcpy(s_root, "error", sizeof(s_root));
+               strlcpy(s_total, "error", sizeof(s_total));
+               fmt_scaled((st.f_blocks - st.f_bfree) * st.f_frsize, s_used);
+               fmt_scaled(st.f_bavail * st.f_frsize, s_avail);
+               fmt_scaled(st.f_bfree * st.f_frsize, s_root);
+               fmt_scaled(st.f_blocks * st.f_frsize, s_total);
+               printf("    Size     Used    Avail   (root)    %%Capacity\n");
+               printf("%7sB %7sB %7sB %7sB         %3llu%%\n",
+                   s_total, s_used, s_avail, s_root,
+                   (unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
+                   st.f_blocks));
+       } else {
+               printf("        Size         Used        Avail       "
+                   "(root)    %%Capacity\n");
+               printf("%12llu %12llu %12llu %12llu         %3llu%%\n",
+                   (unsigned long long)(st.f_frsize * st.f_blocks / 1024),
+                   (unsigned long long)(st.f_frsize *
+                   (st.f_blocks - st.f_bfree) / 1024),
+                   (unsigned long long)(st.f_frsize * st.f_bavail / 1024),
+                   (unsigned long long)(st.f_frsize * st.f_bfree / 1024),
+                   (unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
+                   st.f_blocks));
+       }
+       return 0;
+}
+
 /*
  * Undo escaping of glob sequences in place. Used to undo extra escaping
  * applied in makeargv() when the string is destined for a function that
@@ -972,7 +1055,7 @@ makeargv(const char *arg, int *argcp)
 }
 
 static int
-parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
+parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, int *hflag,
     unsigned long *n_arg, char **path1, char **path2)
 {
        const char *cmd, *cp = *cpp;
@@ -1016,7 +1099,7 @@ parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
        }
 
        /* Get arguments and parse flags */
-       *lflag = *pflag = *n_arg = 0;
+       *lflag = *pflag = *hflag = *n_arg = 0;
        *path1 = *path2 = NULL;
        optidx = 1;
        switch (cmdnum) {
@@ -1068,6 +1151,18 @@ parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
                if (cmdnum != I_RM)
                        undo_glob_escape(*path1);
                break;
+       case I_DF:
+               if ((optidx = parse_df_flags(cmd, argv, argc, hflag,
+                   iflag)) == -1)
+                       return -1;
+               /* Default to current directory if no path specified */
+               if (argc - optidx < 1)
+                       *path1 = NULL;
+               else {
+                       *path1 = xstrdup(argv[optidx]);
+                       undo_glob_escape(*path1);
+               }
+               break;
        case I_LS:
                if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1)
                        return(-1);
@@ -1130,7 +1225,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
     int err_abort)
 {
        char *path1, *path2, *tmp;
-       int pflag, lflag, iflag, cmdnum, i;
+       int pflag, lflag, iflag, hflag, cmdnum, i;
        unsigned long n_arg;
        Attrib a, *aa;
        char path_buf[MAXPATHLEN];
@@ -1138,7 +1233,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
        glob_t g;
 
        path1 = path2 = NULL;
-       cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &n_arg,
+       cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &hflag, &n_arg,
            &path1, &path2);
 
        if (iflag != 0)
@@ -1232,6 +1327,13 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
                path1 = make_absolute(path1, *pwd);
                err = do_globbed_ls(conn, path1, tmp, lflag);
                break;
+       case I_DF:
+               /* Default to current directory if no path specified */
+               if (path1 == NULL)
+                       path1 = xstrdup(*pwd);
+               path1 = make_absolute(path1, *pwd);
+               err = do_df(conn, path1, hflag, iflag);
+               break;
        case I_LCHDIR:
                if (chdir(path1) == -1) {
                        error("Couldn't change local directory to "
diff --git a/sftp.h b/sftp.h
index 0835da6ed414dab32fedebc9059334a85e293717..b101b95a03c4b2c669877fa705e532227c6e81c5 100644 (file)
--- a/sftp.h
+++ b/sftp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.h,v 1.7 2008/02/08 23:24:07 djm Exp $ */
+/* $OpenBSD: sftp.h,v 1.8 2008/04/18 12:32:11 djm Exp $ */
 
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
 #define SSH2_FXF_TRUNC                 0x00000010
 #define SSH2_FXF_EXCL                  0x00000020
 
+/* statvfs@openssh.com f_flag flags */
+#define SSH2_FXE_STATVFS_ST_RDONLY     0x00000001
+#define SSH2_FXE_STATVFS_ST_NOSUID     0x00000002
+
 /* status messages */
 #define SSH2_FX_OK                     0
 #define SSH2_FX_EOF                    1
This page took 0.345126 seconds and 5 git commands to generate.