Changed SILC code to use new SRT and SCT APIs.
[silc.git] / lib / silcsftp / sftp_fs_memory.c
index 23d032a5ea47a090497e311e09d6f3c75faa5a96..afa2d2291c36d259dd55b081445e6649d24b9b26 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  sftp_fs_memory.c 
+  sftp_fs_memory.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2008 Pekka Riikonen
 
   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
 /* $Id$ */
 /* XXX TODO Win32 support */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcsftp.h"
 #include "silcsftp_fs.h"
 #include "sftp_util.h"
 
 #define DIR_SEPARATOR "/"
 
-/* Memory filesystem entry */
+const struct SilcSFTPFilesystemOpsStruct silc_sftp_fs_memory;
+
 typedef struct MemFSEntryStruct {
-  char *name;                       /* Name of the entry */
-  char *data;                      /* Data of the entry */
-  bool directory;                  /* TRUE if this is directory */
-  SilcSFTPFSMemoryPerm perm;       /* Permissions */
   struct MemFSEntryStruct **entry;  /* Files and sub-directories */
-  uint32 entry_count;              /* Number of files and sub-directories */
+  SilcUInt32 entry_count;                  /* Number of files and sub-directories */
   struct MemFSEntryStruct *parent;  /* non-NULL if `directory' is TRUE,
                                       includes parent directory. */
-  unsigned long created;           /* Time of creation */
+  SilcUInt32 created;              /* Time of creation */
+  char *name;                       /* Name of the entry */
+  char *data;                      /* Data of the entry */
+  unsigned int directory : 1;      /* Set if this is directory */
+  unsigned int perm : 7;           /* Permissions */
 } *MemFSEntry;
 
 /* File handle. */
 typedef struct {
-  uint32 handle;                   /* Handle index */
+  SilcUInt32 handle;               /* Handle index */
   int fd;                          /* Real file handle */
   MemFSEntry entry;                /* Filesystem entry */
 } *MemFSFileHandle;
@@ -51,13 +52,13 @@ typedef struct {
   MemFSEntry root;                 /* Root of the filesystem hierarchy */
   SilcSFTPFSMemoryPerm root_perm;
   MemFSFileHandle *handles;        /* Open file handles */
-  uint32 handles_count;
+  SilcUInt32 handles_count;
 } *MemFS;
 
 /* Generates absolute path from relative path that may include '.' and '..'
    in the path. */
 
-static char *mem_expand_path(MemFSEntry root, const char *path)
+static char *memfs_expand_path(MemFSEntry root, const char *path)
 {
   if (!strstr(path, "./") && !strstr(path, "../") &&
       !strstr(path, "/..") && !strstr(path, "/."))
@@ -69,19 +70,21 @@ static char *mem_expand_path(MemFSEntry root, const char *path)
 
 /* Add `entry' to directory `dir'. */
 
-static bool mem_add_entry(MemFSEntry dir, MemFSEntry entry,
-                         bool check_perm)
+static SilcBool memfs_add_entry(MemFSEntry dir, MemFSEntry entry,
+                               SilcBool check_perm)
 {
   int i;
 
   /* Must be both write and exec permissions */
-  if (check_perm && 
-      !((dir->perm & SILC_SFTP_FS_PERM_WRITE) && 
+  if (check_perm &&
+      !((dir->perm & SILC_SFTP_FS_PERM_WRITE) &&
        (dir->perm & SILC_SFTP_FS_PERM_EXEC)))
     return FALSE;
 
   if (!dir->entry) {
     dir->entry = silc_calloc(3, sizeof(*entry));
+    if (!dir->entry)
+      return FALSE;
     dir->entry[0] = entry;
     dir->entry_count = 3;
     entry->created = time(0);
@@ -99,6 +102,8 @@ static bool mem_add_entry(MemFSEntry dir, MemFSEntry entry,
 
   dir->entry = silc_realloc(dir->entry, sizeof(*dir->entry) *
                            (dir->entry_count + 3));
+  if (!dir->entry)
+    return FALSE;
   for (i = dir->entry_count + 1; i < dir->entry_count + 3; i++)
     dir->entry[i] = NULL;
   dir->entry[dir->entry_count] = entry;
@@ -110,7 +115,7 @@ static bool mem_add_entry(MemFSEntry dir, MemFSEntry entry,
 
 /* Removes entry `entry' and all entries under it recursively. */
 
-static bool mem_del_entry(MemFSEntry entry, bool check_perm)
+static SilcBool memfs_del_entry(MemFSEntry entry, SilcBool check_perm)
 {
   int i;
 
@@ -124,7 +129,7 @@ static bool mem_del_entry(MemFSEntry entry, bool check_perm)
   /* Delete all entries recursively under this entry */
   for (i = 0; i < entry->entry_count; i++) {
     if (entry->entry[i]) {
-      if (!mem_del_entry(entry->entry[i], FALSE))
+      if (!memfs_del_entry(entry->entry[i], FALSE))
        return FALSE;
     }
   }
@@ -145,11 +150,11 @@ static bool mem_del_entry(MemFSEntry entry, bool check_perm)
   return TRUE;
 }
 
-/* Finds first occurence of entry named `name' under the directory `dir'. 
+/* Finds first occurence of entry named `name' under the directory `dir'.
    This does not check subdirectories recursively. */
 
-static MemFSEntry mem_find_entry(MemFSEntry dir, const char *name,
-                                uint32 name_len)
+static MemFSEntry memfs_find_entry(MemFSEntry dir, const char *name,
+                                  SilcUInt32 name_len)
 {
   int i;
 
@@ -167,13 +172,13 @@ static MemFSEntry mem_find_entry(MemFSEntry dir, const char *name,
 /* Finds the entry by the `path' which may include full path or
    relative path. */
 
-static MemFSEntry mem_find_entry_path(MemFSEntry dir, const char *p)
+static MemFSEntry memfs_find_entry_path(MemFSEntry dir, const char *p)
 {
   MemFSEntry entry = NULL;
   int len;
   char *path, *cp;
 
-  cp = path = mem_expand_path(dir, p);
+  cp = path = memfs_expand_path(dir, p);
 
   if (strlen(cp) == 1 && cp[0] == '/')
     return dir;
@@ -182,7 +187,7 @@ static MemFSEntry mem_find_entry_path(MemFSEntry dir, const char *p)
     cp++;
   len = strcspn(cp, DIR_SEPARATOR);
   while (cp && len) {
-    entry = mem_find_entry(dir, cp, len);
+    entry = memfs_find_entry(dir, cp, len);
     if (!entry) {
       silc_free(cp);
       return NULL;
@@ -202,8 +207,8 @@ static MemFSEntry mem_find_entry_path(MemFSEntry dir, const char *p)
 /* Deletes entry by the name `name' from the directory `dir'. This does
    not check subdirectories recursively. */
 
-static bool mem_del_entry_name(MemFSEntry dir, const char *name,
-                              uint32 name_len, bool check_perm)
+static SilcBool memfs_del_entry_name(MemFSEntry dir, const char *name,
+                                    SilcUInt32 name_len, SilcBool check_perm)
 {
   MemFSEntry entry;
 
@@ -211,27 +216,31 @@ static bool mem_del_entry_name(MemFSEntry dir, const char *name,
   if (check_perm)
     return FALSE;
 
-  entry = mem_find_entry(dir, name, name_len);
+  entry = memfs_find_entry(dir, name, name_len);
 
   if (entry)
-    return mem_del_entry(entry, check_perm);
+    return memfs_del_entry(entry, check_perm);
 
   return FALSE;
 }
 
 /* Create new handle and add it to the list of open handles. */
 
-static MemFSFileHandle mem_create_handle(MemFS fs, int fd, MemFSEntry entry)
+static MemFSFileHandle memfs_create_handle(MemFS fs, int fd, MemFSEntry entry)
 {
   MemFSFileHandle handle;
   int i;
 
   handle = silc_calloc(1, sizeof(*handle));
+  if (!handle)
+    return NULL;
   handle->fd = fd;
   handle->entry = entry;
 
   if (!fs->handles) {
     fs->handles = silc_calloc(5, sizeof(*fs->handles));
+    if (!fs->handles)
+      return NULL;
     fs->handles[0] = handle;
     fs->handles_count = 5;
 
@@ -253,6 +262,8 @@ static MemFSFileHandle mem_create_handle(MemFS fs, int fd, MemFSEntry entry)
 
   fs->handles = silc_realloc(fs->handles, sizeof(*fs->handles) *
                             (fs->handles_count + 5));
+  if (!fs->handles)
+    return NULL;
   for (i = fs->handles_count + 1; i < fs->handles_count + 5; i++)
     fs->handles[i] = NULL;
   fs->handles[fs->handles_count] = handle;
@@ -264,7 +275,7 @@ static MemFSFileHandle mem_create_handle(MemFS fs, int fd, MemFSEntry entry)
 
 /* Deletes the handle and remove it from the open handle list. */
 
-static bool mem_del_handle(MemFS fs, MemFSFileHandle handle)
+static SilcBool memfs_del_handle(MemFS fs, MemFSFileHandle handle)
 {
   if (handle->handle > fs->handles_count)
     return FALSE;
@@ -275,7 +286,7 @@ static bool mem_del_handle(MemFS fs, MemFSFileHandle handle)
   if (fs->handles[handle->handle] == handle) {
     fs->handles[handle->handle] = NULL;
     if (handle->fd != -1)
-      close(handle->fd);
+      silc_file_close(handle->fd);
     silc_free(handle);
     return TRUE;
   }
@@ -285,7 +296,7 @@ static bool mem_del_handle(MemFS fs, MemFSFileHandle handle)
 
 /* Find handle by handle index. */
 
-static MemFSFileHandle mem_find_handle(MemFS fs, uint32 handle)
+static MemFSFileHandle memfs_find_handle(MemFS fs, SilcUInt32 handle)
 {
   if (handle > fs->handles_count)
     return NULL;
@@ -305,28 +316,52 @@ static MemFSFileHandle mem_find_handle(MemFS fs, uint32 handle)
    silc_sftp_fs_memory_free. The `perm' is the permissions for the root
    directory of the filesystem (/ dir). */
 
-void *silc_sftp_fs_memory_alloc(SilcSFTPFSMemoryPerm perm)
+SilcSFTPFilesystem silc_sftp_fs_memory_alloc(SilcSFTPFSMemoryPerm perm)
 {
+  SilcSFTPFilesystem filesystem;
   MemFS fs;
 
   fs = silc_calloc(1, sizeof(*fs));
+  if (!fs)
+    return NULL;
+
   fs->root = silc_calloc(1, sizeof(*fs->root));
+  if (!fs->root) {
+    silc_free(fs);
+    return NULL;
+  }
+
   fs->root->perm = perm;
   fs->root_perm = perm;
   fs->root->directory = TRUE;
   fs->root->name = strdup(DIR_SEPARATOR);
+  if (!fs->root->name) {
+    silc_free(fs->root);
+    silc_free(fs);
+  }
+
+  filesystem = silc_calloc(1, sizeof(*filesystem));
+  if (!filesystem) {
+    silc_free(fs->root->name);
+    silc_free(fs->root);
+    silc_free(fs);
+    return NULL;
+  }
 
-  return (void *)fs;
+  filesystem->fs = (struct SilcSFTPFilesystemOpsStruct *)&silc_sftp_fs_memory;
+  filesystem->fs_context = (void *)fs;
+
+  return filesystem;
 }
 
 /* Frees the memory filesystem context. */
 
-void silc_sftp_fs_memory_free(void *context)
+void silc_sftp_fs_memory_free(SilcSFTPFilesystem fs)
 {
-  MemFS fs = (MemFS)context;
+  MemFS memfs = (MemFS)fs->fs_context;
 
-  silc_free(fs->root);
-  silc_free(fs);
+  silc_free(memfs->root);
+  silc_free(memfs);
 }
 
 /* Adds a new directory to the memory filesystem. Returns the directory
@@ -338,21 +373,31 @@ void silc_sftp_fs_memory_free(void *context)
    not free the returned context. The `perm' will indicate the permissions
    for the directory and they work in POSIX style. */
 
-void *silc_sftp_fs_memory_add_dir(void *context, void *dir,
+void *silc_sftp_fs_memory_add_dir(SilcSFTPFilesystem fs, void *dir,
                                  SilcSFTPFSMemoryPerm perm,
                                  const char *name)
 {
-  MemFS fs = (MemFS)context;
+  MemFS memfs = (MemFS)fs->fs_context;
   MemFSEntry entry;
 
   entry = silc_calloc(1, sizeof(*entry));
+  if (!entry)
+    return NULL;
+
   entry->perm = perm;
-  entry->name = strdup(name);
   entry->directory = TRUE;
-  entry->parent = dir ? dir : fs->root;
+  entry->parent = dir ? dir : memfs->root;
+  entry->name = strdup(name);
+  if (!entry->name) {
+    silc_free(entry);
+    return NULL;
+  }
 
-  if (!mem_add_entry(dir ? dir : fs->root, entry, FALSE))
+  if (!memfs_add_entry(dir ? dir : memfs->root, entry, FALSE)) {
+    silc_free(entry->name);
+    silc_free(entry);
     return NULL;
+  }
 
   return entry;
 }
@@ -364,21 +409,29 @@ void *silc_sftp_fs_memory_add_dir(void *context, void *dir,
    in memory file system. The filesystem does not allow removing directories
    with remote access using the filesystem access function sftp_rmdir. */
 
-bool silc_sftp_fs_memory_del_dir(void *context, void *dir)
+SilcBool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir)
 {
-  MemFS fs = (MemFS)context;
-  bool ret;
+  MemFS memfs = (MemFS)fs->fs_context;
+  SilcBool ret;
 
   if (dir)
-    return mem_del_entry(dir, FALSE);
+    return memfs_del_entry(dir, FALSE);
 
   /* Remove from root */
-  ret = mem_del_entry(fs->root, FALSE);
+  ret = memfs_del_entry(memfs->root, FALSE);
 
-  fs->root = silc_calloc(1, sizeof(*fs->root));
-  fs->root->perm = fs->root_perm;
-  fs->root->directory = TRUE;
-  fs->root->name = strdup(DIR_SEPARATOR);
+  memfs->root = silc_calloc(1, sizeof(*memfs->root));
+  if (!memfs->root)
+    return FALSE;
+
+  memfs->root->perm = memfs->root_perm;
+  memfs->root->directory = TRUE;
+  memfs->root->name = strdup(DIR_SEPARATOR);
+  if (!memfs->root->name) {
+    silc_free(memfs->root);
+    memfs->root = NULL;
+    return FALSE;
+  }
 
   return ret;
 }
@@ -391,73 +444,83 @@ bool silc_sftp_fs_memory_del_dir(void *context, void *dir)
    file and they work in POSIX style. Returns TRUE if the file was
    added to the directory. */
 
-bool silc_sftp_fs_memory_add_file(void *context,
-                                 void *dir,
-                                 SilcSFTPFSMemoryPerm perm,
-                                 const char *filename,
-                                 const char *realpath)
+SilcBool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
+                                     SilcSFTPFSMemoryPerm perm,
+                                     const char *filename,
+                                     const char *realpath)
 {
-  MemFS fs = (MemFS)context;
+  MemFS memfs = (MemFS)fs->fs_context;
   MemFSEntry entry;
 
   entry = silc_calloc(1, sizeof(*entry));
+  if (!entry)
+    return FALSE;
+
   entry->perm = perm;
+  entry->directory = FALSE;
   entry->name = strdup(filename);
   entry->data = strdup(realpath);
-  entry->directory = FALSE;
+  if (!entry->name || !entry->data) {
+    silc_free(entry->name);
+    silc_free(entry->data);
+    silc_free(entry);
+    return FALSE;
+  }
 
-  return mem_add_entry(dir ? dir : fs->root, entry, FALSE);
+  return memfs_add_entry(dir ? dir : memfs->root, entry, FALSE);
 }
 
 /* Removes a file indicated by the `filename' from the directory
    indicated by the `dir'. Returns TRUE if the removing was success. */
 
-bool silc_sftp_fs_memory_del_file(void *context, void *dir,
-                                 const char *filename)
+SilcBool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
+                                     const char *filename)
 {
-  MemFS fs = (MemFS)context;
+  MemFS memfs = (MemFS)fs->fs_context;
 
   if (!filename)
     return FALSE;
 
-  return mem_del_entry_name(dir ? dir : fs->root, filename, 
+  return memfs_del_entry_name(dir ? dir : memfs->root, filename,
                            strlen(filename), FALSE);
 }
 
-SilcSFTPHandle mem_get_handle(void *context, SilcSFTP sftp,
-                             const unsigned char *data,
-                             uint32 data_len)
+SilcSFTPHandle memfs_get_handle(void *context, SilcSFTP sftp,
+                               const unsigned char *data,
+                               SilcUInt32 data_len)
 {
   MemFS fs = (MemFS)context;
-  uint32 handle;
+  SilcUInt32 handle;
 
   if (data_len < 4)
     return NULL;
 
   SILC_GET32_MSB(handle, data);
-  return (SilcSFTPHandle)mem_find_handle(fs, handle);
+  return (SilcSFTPHandle)memfs_find_handle(fs, handle);
 }
 
-unsigned char *mem_encode_handle(void *context, SilcSFTP sftp,
-                                SilcSFTPHandle handle,
-                                uint32 *handle_len)
+unsigned char *memfs_encode_handle(void *context, SilcSFTP sftp,
+                                  SilcSFTPHandle handle,
+                                  SilcUInt32 *handle_len)
 {
   unsigned char *data;
   MemFSFileHandle h = (MemFSFileHandle)handle;
 
   data = silc_calloc(4, sizeof(*data));
+  if (!data)
+    return NULL;
+
   SILC_PUT32_MSB(h->handle, data);
   *handle_len = 4;
-
   return data;
 }
 
-void mem_open(void *context, SilcSFTP sftp, 
-             const char *filename,
-             SilcSFTPFileOperation pflags,
-             SilcSFTPAttributes attrs,
-             SilcSFTPHandleCallback callback,
-             void *callback_context)
+void memfs_open(void *context, SilcSFTP sftp,
+               const char *filename,
+               SilcSFTPFileOperation pflags,
+               SilcSFTPAttributes attrs,
+               SilcSFTPHandleCallback callback,
+               void *callback_context)
 {
   MemFS fs = (MemFS)context;
   MemFSEntry entry;
@@ -471,7 +534,7 @@ void mem_open(void *context, SilcSFTP sftp,
   }
 
   /* Find such file */
-  entry = mem_find_entry_path(fs->root, filename);
+  entry = memfs_find_entry_path(fs->root, filename);
   if (!entry) {
     (*callback)(sftp, SILC_SFTP_STATUS_NO_SUCH_FILE, NULL, callback_context);
     return;
@@ -480,20 +543,20 @@ void mem_open(void *context, SilcSFTP sftp,
   if (entry->directory || !entry->data) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
 
   /* Check for reading */
-  if ((pflags & SILC_SFTP_FXF_READ) && 
+  if ((pflags & SILC_SFTP_FXF_READ) &&
       !(entry->perm & SILC_SFTP_FS_PERM_READ)) {
-    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL, 
+    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL,
                callback_context);
     return;
-  }    
+  }
 
   /* Check for writing */
-  if (((pflags & SILC_SFTP_FXF_WRITE) || (pflags & SILC_SFTP_FXF_APPEND)) && 
+  if (((pflags & SILC_SFTP_FXF_WRITE) || (pflags & SILC_SFTP_FXF_APPEND)) &&
       !(entry->perm & SILC_SFTP_FS_PERM_WRITE)) {
-    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL, 
+    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL,
                callback_context);
     return;
   }
@@ -508,84 +571,93 @@ void mem_open(void *context, SilcSFTP sftp,
     flags |= O_APPEND;
 
   /* Attempt to open the file for real. */
-  fd = open(entry->data + 7, flags, 
-           (attrs->flags & SILC_SFTP_ATTR_PERMISSIONS ?
-            attrs->permissions : 0600));
+  fd = silc_file_open_mode(entry->data + 7, flags,
+                          (attrs->flags & SILC_SFTP_ATTR_PERMISSIONS ?
+                           attrs->permissions : 0600));
   if (fd == -1) {
-    (*callback)(sftp, silc_sftp_map_errno(errno), NULL, callback_context);
+    (*callback)(sftp, silc_sftp_map_errno(silc_errno), NULL, callback_context);
     return;
   }
 
   /* File opened, return handle */
-  handle = mem_create_handle(fs, fd, entry);
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (SilcSFTPHandle)handle, 
-             callback_context);
+  handle = memfs_create_handle(fs, fd, entry);
+  if (handle)
+    (*callback)(sftp, SILC_SFTP_STATUS_OK, (SilcSFTPHandle)handle,
+               callback_context);
+  else
+    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL,
+               callback_context);
 }
 
-void mem_close(void *context, SilcSFTP sftp,
-              SilcSFTPHandle handle,
-              SilcSFTPStatusCallback callback,
-              void *callback_context)
+void memfs_close(void *context, SilcSFTP sftp,
+                SilcSFTPHandle handle,
+                SilcSFTPStatusCallback callback,
+                void *callback_context)
 {
   MemFS fs = (MemFS)context;
   MemFSFileHandle h = (MemFSFileHandle)handle;
   int ret;
 
   if (h->fd != -1) {
-    ret = close(h->fd);
+    ret = silc_file_close(h->fd);
     if (ret == -1) {
-      (*callback)(sftp, silc_sftp_map_errno(errno), NULL, NULL, 
+      (*callback)(sftp, silc_sftp_map_errno(silc_errno), NULL, NULL,
                  callback_context);
       return;
     }
   }
 
-  mem_del_handle(fs, h);
+  memfs_del_handle(fs, h);
   (*callback)(sftp, SILC_SFTP_STATUS_OK, NULL, NULL, callback_context);
 }
 
-void mem_read(void *context, SilcSFTP sftp,
-             SilcSFTPHandle handle,
-             uint64 offset, 
-             uint32 len,
-             SilcSFTPDataCallback callback,
-             void *callback_context)
+void memfs_read(void *context, SilcSFTP sftp,
+               SilcSFTPHandle handle,
+               SilcUInt64 offset,
+               SilcUInt32 len,
+               SilcSFTPDataCallback callback,
+               void *callback_context)
 {
   MemFSFileHandle h = (MemFSFileHandle)handle;
-  unsigned char *data;
+  unsigned char data[63488];
   int ret;
 
-  if (len > 32768)
-    len = 32768;
+  if (len > 63488)
+    len = 63488;
 
-  data = silc_malloc(len);
-  lseek(h->fd, (off_t)offset, SEEK_SET);
+  ret = lseek(h->fd, (off_t)offset, SEEK_SET);
+  if (ret < 0) {
+    if (!ret)
+      (*callback)(sftp, SILC_SFTP_STATUS_EOF, NULL, 0, callback_context);
+    else
+      (*callback)(sftp, silc_sftp_map_errno(silc_errno),
+                 NULL, 0, callback_context);
+    return;
+  }
 
   /* Attempt to read */
-  ret = read(h->fd, data, len);
+  ret = silc_file_read(h->fd, data, len);
   if (ret <= 0) {
     if (!ret)
       (*callback)(sftp, SILC_SFTP_STATUS_EOF, NULL, 0, callback_context);
     else
-      (*callback)(sftp, silc_sftp_map_errno(errno), NULL, 0, callback_context);
-    silc_free(data);
+      (*callback)(sftp, silc_sftp_map_errno(silc_errno),
+                 NULL, 0, callback_context);
     return;
   }
 
   /* Return data */
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const unsigned char *)data, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const unsigned char *)data,
              ret, callback_context);
-
-  silc_free(data);
 }
 
-void mem_write(void *context, SilcSFTP sftp,
-              SilcSFTPHandle handle,
-              uint64 offset,
-              const unsigned char *data,
-              uint32 data_len,
-              SilcSFTPStatusCallback callback,
-              void *callback_context)
+void memfs_write(void *context, SilcSFTP sftp,
+                SilcSFTPHandle handle,
+                SilcUInt64 offset,
+                const unsigned char *data,
+                SilcUInt32 data_len,
+                SilcSFTPStatusCallback callback,
+                void *callback_context)
 {
   MemFSFileHandle h = (MemFSFileHandle)handle;
   int ret;
@@ -593,9 +665,9 @@ void mem_write(void *context, SilcSFTP sftp,
   lseek(h->fd, (off_t)offset, SEEK_SET);
 
   /* Attempt to write */
-  ret = write(h->fd, data, data_len);
+  ret = silc_file_write(h->fd, data, data_len);
   if (ret <= 0) {
-    (*callback)(sftp, silc_sftp_map_errno(errno), NULL, NULL, 
+    (*callback)(sftp, silc_sftp_map_errno(silc_errno), NULL, NULL,
                callback_context);
     return;
   }
@@ -603,62 +675,62 @@ void mem_write(void *context, SilcSFTP sftp,
   (*callback)(sftp, SILC_SFTP_STATUS_OK, NULL, NULL, callback_context);
 }
 
-void mem_remove(void *context, SilcSFTP sftp,
-               const char *filename,
-               SilcSFTPStatusCallback callback,
-               void *callback_context)
+void memfs_remove(void *context, SilcSFTP sftp,
+                 const char *filename,
+                 SilcSFTPStatusCallback callback,
+                 void *callback_context)
 {
   /* Remove is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
-void mem_rename(void *context, SilcSFTP sftp,
-               const char *oldname,
-               const char *newname,
-               SilcSFTPStatusCallback callback,
-               void *callback_context)
+void memfs_rename(void *context, SilcSFTP sftp,
+                 const char *oldname,
+                 const char *newname,
+                 SilcSFTPStatusCallback callback,
+                 void *callback_context)
 {
   /* Rename is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
-void mem_mkdir(void *context, SilcSFTP sftp,
-              const char *path,
-              SilcSFTPAttributes attrs,
-              SilcSFTPStatusCallback callback,
-              void *callback_context)
+void memfs_mkdir(void *context, SilcSFTP sftp,
+                const char *path,
+                SilcSFTPAttributes attrs,
+                SilcSFTPStatusCallback callback,
+                void *callback_context)
 {
   /* Mkdir is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
-void mem_rmdir(void *context, SilcSFTP sftp,
-              const char *path,
-              SilcSFTPStatusCallback callback,
-              void *callback_context)
+void memfs_rmdir(void *context, SilcSFTP sftp,
+                const char *path,
+                SilcSFTPStatusCallback callback,
+                void *callback_context)
 {
   /* Rmdir is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
-void mem_opendir(void *context, SilcSFTP sftp,
-                const char *path,
-                SilcSFTPHandleCallback callback,
-                void *callback_context)
+void memfs_opendir(void *context, SilcSFTP sftp,
+                  const char *path,
+                  SilcSFTPHandleCallback callback,
+                  void *callback_context)
 {
   MemFS fs = (MemFS)context;
   MemFSEntry entry;
   MemFSFileHandle handle;
 
   if (!path || !strlen(path))
-    path = (const char *)strdup("/");
+    path = (const char *)DIR_SEPARATOR;
 
   /* Find such directory */
-  entry = mem_find_entry_path(fs->root, path);
+  entry = memfs_find_entry_path(fs->root, path);
   if (!entry) {
     (*callback)(sftp, SILC_SFTP_STATUS_NO_SUCH_FILE, NULL, callback_context);
     return;
@@ -667,25 +739,29 @@ void mem_opendir(void *context, SilcSFTP sftp,
   if (!entry->directory) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
 
   /* Must be read permissions to open a directory */
   if (!(entry->perm & SILC_SFTP_FS_PERM_READ)) {
-    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL, 
+    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL,
                callback_context);
     return;
   }
 
   /* Directory opened, return handle */
-  handle = mem_create_handle(fs, 0, entry);
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (SilcSFTPHandle)handle, 
-             callback_context);
+  handle = memfs_create_handle(fs, 0, entry);
+  if (handle)
+    (*callback)(sftp, SILC_SFTP_STATUS_OK, (SilcSFTPHandle)handle,
+               callback_context);
+  else
+    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL,
+               callback_context);
 }
 
-void mem_readdir(void *context, SilcSFTP sftp,
-                SilcSFTPHandle handle,
-                SilcSFTPNameCallback callback,
-                void *callback_context)
+void memfs_readdir(void *context, SilcSFTP sftp,
+                  SilcSFTPHandle handle,
+                  SilcSFTPNameCallback callback,
+                  void *callback_context)
 {
   MemFSFileHandle h = (MemFSFileHandle)handle;
   MemFSEntry entry;
@@ -693,9 +769,9 @@ void mem_readdir(void *context, SilcSFTP sftp,
   SilcSFTPAttributes attrs;
   int i;
   char long_name[256];
-  unsigned long filesize = 0;
+  SilcUInt64 filesize = 0;
   char *date;
-  struct stat stats;
+  SilcFileStatStruct stats;
 
   if (!h->entry->directory) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
@@ -708,6 +784,10 @@ void mem_readdir(void *context, SilcSFTP sftp,
   }
 
   name = silc_calloc(1, sizeof(*name));
+  if (!name) {
+    (*callback)(sftp, SILC_SFTP_STATUS_EOF, NULL, callback_context);
+    return;
+  }
   for (i = h->fd; i < 100 + h->fd; i++) {
     if (i >= h->entry->entry_count)
       break;
@@ -719,30 +799,40 @@ void mem_readdir(void *context, SilcSFTP sftp,
     filesize = sizeof(*entry);
     memset(long_name, 0, sizeof(long_name));
 
-    date = ctime(&entry->created);
+    date = (char *)silc_time_string(entry->created);
     if (strrchr(date, ':'))
       *strrchr(date, ':') = '\0';
 
-    if (!entry->directory)
-      if (!lstat(entry->data + 7, &stats))
-       filesize = stats.st_size;
+    if (!entry->directory) {
+      filesize = silc_file_size(entry->data + 7);
+      silc_file_stat(entry->data + 7, TRUE, &stats);
+    }
 
     /* Long name format is:
        drwx------   1   324210 Apr  8 08:40 mail/
        1234567890 123 12345678 123456789012 */
-    snprintf(long_name, sizeof(long_name) - 1,
-            "%c%c%c%c------ %3d %8lu %12s %s%s",
+    silc_snprintf(long_name, sizeof(long_name) - 1,
+            "%c%c%c%c------ %3d %8llu %12s %s%s",
             (entry->directory ? 'd' : '-'),
             ((entry->perm & SILC_SFTP_FS_PERM_READ) ? 'r' : '-'),
             ((entry->perm & SILC_SFTP_FS_PERM_WRITE) ? 'w' : '-'),
             ((entry->perm & SILC_SFTP_FS_PERM_EXEC) ? 'x' : '-'),
             (entry->directory ? (int)entry->entry_count : 1),
-            filesize, date, entry->name,
-            (entry->directory ? "/" : 
+#ifndef SILC_WIN32
+            (unsigned long long)filesize,
+#else
+            (unsigned long)filesize,
+#endif
+            date, entry->name,
+            (entry->directory ? "/" :
              ((entry->perm & SILC_SFTP_FS_PERM_EXEC) ? "*" : "")));
 
     /* Add attributes */
     attrs = silc_calloc(1, sizeof(*attrs));
+    if (!attrs) {
+      (*callback)(sftp, SILC_SFTP_STATUS_EOF, NULL, callback_context);
+      return;
+    }
     attrs->flags = (SILC_SFTP_ATTR_SIZE |
                    SILC_SFTP_ATTR_UIDGID);
     attrs->size = filesize;
@@ -750,8 +840,8 @@ void mem_readdir(void *context, SilcSFTP sftp,
     attrs->gid = 0;
     if (!entry->directory) {
       attrs->flags |= SILC_SFTP_ATTR_ACMODTIME;
-      attrs->atime = stats.st_atime;
-      attrs->mtime = stats.st_mtime;
+      attrs->atime = silc_time_epoch(&stats.last_access);
+      attrs->mtime = silc_time_epoch(&stats.last_mod);
     }
 
     /* Add the name */
@@ -778,22 +868,21 @@ void mem_readdir(void *context, SilcSFTP sftp,
   silc_sftp_name_free(name);
 }
 
-void mem_stat(void *context, SilcSFTP sftp,
-             const char *path,
-             SilcSFTPAttrCallback callback,
-             void *callback_context)
+void memfs_stat(void *context, SilcSFTP sftp,
+               const char *path,
+               SilcSFTPAttrCallback callback,
+               void *callback_context)
 {
   MemFS fs = (MemFS)context;
   MemFSEntry entry;
   SilcSFTPAttributes attrs;
-  int ret;
-  struct stat stats;
+  SilcFileStatStruct stats;
 
   if (!path || !strlen(path))
-    path = (const char *)strdup("/");
+    path = (const char *)DIR_SEPARATOR;
 
   /* Find such directory */
-  entry = mem_find_entry_path(fs->root, path);
+  entry = memfs_find_entry_path(fs->root, path);
   if (!entry) {
     (*callback)(sftp, SILC_SFTP_STATUS_NO_SUCH_FILE, NULL, callback_context);
     return;
@@ -802,48 +891,50 @@ void mem_stat(void *context, SilcSFTP sftp,
   if (entry->directory || !entry->data) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
 
   /* Get real stat */
-  ret = stat(entry->data + 7, &stats);
-  if (ret == -1) {
-    (*callback)(sftp, silc_sftp_map_errno(errno), NULL, callback_context);
+  if (!silc_file_stat(entry->data + 7, TRUE, &stats)) {
+    (*callback)(sftp, silc_sftp_map_errno(silc_errno), NULL, callback_context);
     return;
   }
 
   attrs = silc_calloc(1, sizeof(*attrs));
+  if (!attrs) {
+    (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
+    return;
+  }
   attrs->flags = (SILC_SFTP_ATTR_SIZE |
                  SILC_SFTP_ATTR_UIDGID |
                  SILC_SFTP_ATTR_ACMODTIME);
-  attrs->size = stats.st_size;
+  attrs->size = stats.size;
   attrs->uid = 0;                  /* We use always 0 UID and GID */
   attrs->gid = 0;
-  attrs->atime = stats.st_atime;
-  attrs->mtime = stats.st_mtime;
+  attrs->atime = silc_time_epoch(&stats.last_access);
+  attrs->mtime = silc_time_epoch(&stats.last_mod);
 
   /* Return attributes */
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs,
              callback_context);
 
   silc_sftp_attr_free(attrs);
 }
 
-void mem_lstat(void *context, SilcSFTP sftp,
-              const char *path,
-              SilcSFTPAttrCallback callback,
-              void *callback_context)
+void memfs_lstat(void *context, SilcSFTP sftp,
+                const char *path,
+                SilcSFTPAttrCallback callback,
+                void *callback_context)
 {
   MemFS fs = (MemFS)context;
   MemFSEntry entry;
   SilcSFTPAttributes attrs;
-  int ret;
-  struct stat stats;
+  SilcFileStatStruct stats;
 
   if (!path || !strlen(path))
-    path = (const char *)strdup("/");
+    path = (const char *)DIR_SEPARATOR;
 
   /* Find such directory */
-  entry = mem_find_entry_path(fs->root, path);
+  entry = memfs_find_entry_path(fs->root, path);
   if (!entry) {
     (*callback)(sftp, SILC_SFTP_STATUS_NO_SUCH_FILE, NULL, callback_context);
     return;
@@ -852,179 +943,197 @@ void mem_lstat(void *context, SilcSFTP sftp,
   if (entry->directory || !entry->data) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
 
   /* Get real stat */
-  ret = lstat(entry->data + 7, &stats);
-  if (ret == -1) {
-    (*callback)(sftp, silc_sftp_map_errno(errno), NULL, callback_context);
+  if (!silc_file_stat(entry->data + 7, FALSE, &stats)) {
+    (*callback)(sftp, silc_sftp_map_errno(silc_errno), NULL, callback_context);
     return;
   }
 
   attrs = silc_calloc(1, sizeof(*attrs));
+  if (!attrs) {
+    (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
+    return;
+  }
   attrs->flags = (SILC_SFTP_ATTR_SIZE |
                  SILC_SFTP_ATTR_UIDGID |
                  SILC_SFTP_ATTR_ACMODTIME);
-  attrs->size = stats.st_size;
+  attrs->size = stats.size;
   attrs->uid = 0;                  /* We use always 0 UID and GID */
   attrs->gid = 0;
-  attrs->atime = stats.st_atime;
-  attrs->mtime = stats.st_mtime;
+  attrs->atime = silc_time_epoch(&stats.last_access);
+  attrs->mtime = silc_time_epoch(&stats.last_mod);
 
   /* Return attributes */
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs,
              callback_context);
 
   silc_sftp_attr_free(attrs);
 }
 
-void mem_fstat(void *context, SilcSFTP sftp,
-              SilcSFTPHandle handle,
-              SilcSFTPAttrCallback callback,
-              void *callback_context)
+void memfs_fstat(void *context, SilcSFTP sftp,
+                SilcSFTPHandle handle,
+                SilcSFTPAttrCallback callback,
+                void *callback_context)
 {
   MemFSFileHandle h = (MemFSFileHandle)handle;
   SilcSFTPAttributes attrs;
-  int ret;
-  struct stat stats;
+  SilcFileStatStruct stats;
 
   if (h->entry->directory || !h->entry->data) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
 
   /* Get real stat */
-  ret = fstat(h->fd, &stats);
-  if (ret == -1) {
-    (*callback)(sftp, silc_sftp_map_errno(errno), NULL, callback_context);
+  if (!silc_file_fstat(h->fd, &stats)) {
+    (*callback)(sftp, silc_sftp_map_errno(silc_errno), NULL, callback_context);
     return;
   }
 
   attrs = silc_calloc(1, sizeof(*attrs));
+  if (!attrs) {
+    (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
+    return;
+  }
   attrs->flags = (SILC_SFTP_ATTR_SIZE |
                  SILC_SFTP_ATTR_UIDGID |
                  SILC_SFTP_ATTR_ACMODTIME);
-  attrs->size = stats.st_size;
+  attrs->size = stats.size;
   attrs->uid = 0;                  /* We use always 0 UID and GID */
   attrs->gid = 0;
-  attrs->atime = stats.st_atime;
-  attrs->mtime = stats.st_mtime;
+  attrs->atime = silc_time_epoch(&stats.last_access);
+  attrs->mtime = silc_time_epoch(&stats.last_mod);
 
   /* Return attributes */
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs,
              callback_context);
 
   silc_sftp_attr_free(attrs);
 }
-     
-void mem_setstat(void *context, SilcSFTP sftp,
-                const char *path,
-                SilcSFTPAttributes attrs,
-                SilcSFTPStatusCallback callback,
-                void *callback_context)
+
+void memfs_setstat(void *context, SilcSFTP sftp,
+                  const char *path,
+                  SilcSFTPAttributes attrs,
+                  SilcSFTPStatusCallback callback,
+                  void *callback_context)
 {
   /* Setstat is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
-void mem_fsetstat(void *context, SilcSFTP sftp,
-                 SilcSFTPHandle handle,
-                 SilcSFTPAttributes attrs,
-                 SilcSFTPStatusCallback callback,
-                 void *callback_context)
+void memfs_fsetstat(void *context, SilcSFTP sftp,
+                   SilcSFTPHandle handle,
+                   SilcSFTPAttributes attrs,
+                   SilcSFTPStatusCallback callback,
+                   void *callback_context)
 {
   /* Fsetstat is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
-void mem_readlink(void *context, SilcSFTP sftp,
-                 const char *path,
-                 SilcSFTPNameCallback callback,
-                 void *callback_context)
+void memfs_readlink(void *context, SilcSFTP sftp,
+                   const char *path,
+                   SilcSFTPNameCallback callback,
+                   void *callback_context)
 {
   /* Readlink is not supported */
   (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL,
              callback_context);
 }
 
-void mem_symlink(void *context, SilcSFTP sftp,
-                const char *linkpath,
-                const char *targetpath,
-                SilcSFTPStatusCallback callback,
-                void *callback_context)
+void memfs_symlink(void *context, SilcSFTP sftp,
+                  const char *linkpath,
+                  const char *targetpath,
+                  SilcSFTPStatusCallback callback,
+                  void *callback_context)
 {
   /* Symlink is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
-void mem_realpath(void *context, SilcSFTP sftp,
-                 const char *path,
-                 SilcSFTPNameCallback callback,
-                 void *callback_context)
+void memfs_realpath(void *context, SilcSFTP sftp,
+                   const char *path,
+                   SilcSFTPNameCallback callback,
+                   void *callback_context)
 {
   MemFS fs = (MemFS)context;
   char *realpath;
   SilcSFTPName name;
 
   if (!path || !strlen(path))
-    path = (const char *)strdup("/");
+    path = (const char *)DIR_SEPARATOR;
 
-  realpath = mem_expand_path(fs->root, path);
-  if (!realpath) {
-    (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
-    return;
-  }
+  realpath = memfs_expand_path(fs->root, path);
+  if (!realpath)
+    goto fail;
 
   name = silc_calloc(1, sizeof(*name));
+  if (!name)
+    goto fail;
+
   name->filename = silc_calloc(1, sizeof(*name->filename));
+  if (!name->filename)
+    goto fail;
   name->filename[0] = realpath;
   name->long_filename = silc_calloc(1, sizeof(*name->long_filename));
+  if (!name->long_filename)
+    goto fail;
   name->long_filename[0] = realpath;
   name->attrs = silc_calloc(1, sizeof(*name->attrs));
+  if (!name->attrs)
+    goto fail;
   name->attrs[0] = silc_calloc(1, sizeof(*name->attrs[0]));
+  if (!name->attrs[0])
+    goto fail;
   name->count = 1;
 
-  (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, (const SilcSFTPName)name, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPName)name,
              callback_context);
 
   silc_sftp_name_free(name);
+  return;
+
+ fail:
+  (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
 }
 
-void mem_extended(void *context, SilcSFTP sftp,
-                 const char *request,
-                 const unsigned char *data,
-                 uint32 data_len,
-                 SilcSFTPExtendedCallback callback,
-                 void *callback_context)
+void memfs_extended(void *context, SilcSFTP sftp,
+                   const char *request,
+                   const unsigned char *data,
+                   SilcUInt32 data_len,
+                   SilcSFTPExtendedCallback callback,
+                   void *callback_context)
 {
   /* Extended is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, 0, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, 0,
              callback_context);
 }
 
-struct SilcSFTPFilesystemStruct silc_sftp_fs_memory = {
-  mem_get_handle,
-  mem_encode_handle,
-  mem_open,
-  mem_close,
-  mem_read,
-  mem_write,
-  mem_remove,
-  mem_rename,
-  mem_mkdir,
-  mem_rmdir,
-  mem_opendir,
-  mem_readdir,
-  mem_stat,
-  mem_lstat,
-  mem_fstat,
-  mem_setstat,
-  mem_fsetstat,
-  mem_readlink,
-  mem_symlink,
-  mem_realpath,
-  mem_extended
+const struct SilcSFTPFilesystemOpsStruct silc_sftp_fs_memory = {
+  memfs_get_handle,
+  memfs_encode_handle,
+  memfs_open,
+  memfs_close,
+  memfs_read,
+  memfs_write,
+  memfs_remove,
+  memfs_rename,
+  memfs_mkdir,
+  memfs_rmdir,
+  memfs_opendir,
+  memfs_readdir,
+  memfs_stat,
+  memfs_lstat,
+  memfs_fstat,
+  memfs_setstat,
+  memfs_fsetstat,
+  memfs_readlink,
+  memfs_symlink,
+  memfs_realpath,
+  memfs_extended
 };