> Yes, sftp-server should dynamically allocate its handles up to the
> point where the system starts refusing to allocate file descriptors.
>
> Anyone want to make a patch?


Here's one.

Dynamically increase the handle table size as needed. When finding an
unused handle, use a LIFO instead of seaching the table linearly.
This makes handle allocation O(1).

Miklos


Index: ssh/sftp-server.c
================================================== =================
--- ssh.orig/sftp-server.c 2007-09-13 06:39:04.000000000 +0200
+++ ssh/sftp-server.c 2007-12-07 09:31:17.000000000 +0100
@@ -164,6 +164,7 @@ struct Handle {
int fd;
char *name;
u_int64_t bytes_read, bytes_write;
+ int next_unused;
};

enum {
@@ -172,40 +173,44 @@ enum {
HANDLE_FILE
};

-Handle handles[100];
-
-static void
-handle_init(void)
-{
- u_int i;
-
- for (i = 0; i < sizeof(handles)/sizeof(Handle); i++)
- handles[i].use = HANDLE_UNUSED;
+Handle *handles = NULL;
+u_int num_handles = 0;
+int first_unused = -1;
+
+static void handle_unused(int i)
+{
+ handles[i].use = HANDLE_UNUSED;
+ handles[i].next_unused = first_unused;
+ first_unused = i;
}

static int
handle_new(int use, const char *name, int fd, DIR *dirp)
{
- u_int i;
+ int i;

- for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) {
- if (handles[i].use == HANDLE_UNUSED) {
- handles[i].use = use;
- handles[i].dirp = dirp;
- handles[i].fd = fd;
- handles[i].name = xstrdup(name);
- handles[i].bytes_read = handles[i].bytes_write = 0;
- return i;
- }
- }
- return -1;
+ if (first_unused == -1) {
+ num_handles++;
+ handles = xrealloc(handles, num_handles, sizeof(Handle));
+ handle_unused(num_handles - 1);
+ }
+
+ i = first_unused;
+ first_unused = handles[i].next_unused;
+
+ handles[i].use = use;
+ handles[i].dirp = dirp;
+ handles[i].fd = fd;
+ handles[i].name = xstrdup(name);
+ handles[i].bytes_read = handles[i].bytes_write = 0;
+
+ return i;
}

static int
handle_is_ok(int i, int type)
{
- return i >= 0 && (u_int)i < sizeof(handles)/sizeof(Handle) &&
- handles[i].use == type;
+ return i >= 0 && (u_int)i < num_handles && handles[i].use == type;
}

static int
@@ -295,12 +300,12 @@ handle_close(int handle)

if (handle_is_ok(handle, HANDLE_FILE)) {
ret = close(handles[handle].fd);
- handles[handle].use = HANDLE_UNUSED;
xfree(handles[handle].name);
+ handle_unused(handle);
} else if (handle_is_ok(handle, HANDLE_DIR)) {
ret = closedir(handles[handle].dirp);
- handles[handle].use = HANDLE_UNUSED;
xfree(handles[handle].name);
+ handle_unused(handle);
} else {
errno = ENOENT;
}
@@ -328,7 +333,7 @@ handle_log_exit(void)
{
u_int i;

- for (i = 0; i < sizeof(handles)/sizeof(Handle); i++)
+ for (i = 0; i < num_handles; i++)
if (handles[i].use != HANDLE_UNUSED)
handle_log_close(i, "forced");
}
@@ -1249,8 +1254,6 @@ main(int argc, char **argv)
logit("session opened for local user %s from [%s]",
pw->pw_name, client_addr);

- handle_init();
-
in = dup(STDIN_FILENO);
out = dup(STDOUT_FILENO);

_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/li...enssh-unix-dev