X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcsftp%2Fsftp_fs_memory.c;h=dc0557612845f5381a79cb66eed4053095a0b417;hb=40f8443d8d3a6577336ee66d18e04d9ac4d956bb;hp=9aac497000fbcdfa063b6eeac6822ce47e01967c;hpb=33b943ac6034b92fcc5c09802f9fe9add12a51c9;p=silc.git diff --git a/lib/silcsftp/sftp_fs_memory.c b/lib/silcsftp/sftp_fs_memory.c index 9aac4970..dc055761 100644 --- a/lib/silcsftp/sftp_fs_memory.c +++ b/lib/silcsftp/sftp_fs_memory.c @@ -1,10 +1,10 @@ /* - sftp_fs_memory.c + sftp_fs_memory.c Author: Pekka Riikonen - Copyright (C) 2001 Pekka Riikonen + Copyright (C) 2001 - 2004 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 @@ -19,29 +19,30 @@ /* $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,7 +52,7 @@ 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 '..' @@ -75,13 +76,15 @@ static bool mem_add_entry(MemFSEntry dir, MemFSEntry entry, 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; @@ -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) + SilcUInt32 name_len) { int i; @@ -203,7 +208,7 @@ static MemFSEntry mem_find_entry_path(MemFSEntry dir, const char *p) not check subdirectories recursively. */ static bool mem_del_entry_name(MemFSEntry dir, const char *name, - uint32 name_len, bool check_perm) + SilcUInt32 name_len, bool check_perm) { MemFSEntry entry; @@ -227,11 +232,15 @@ static MemFSFileHandle mem_create_handle(MemFS fs, int fd, MemFSEntry entry) 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; @@ -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 mem_find_handle(MemFS fs, SilcUInt32 handle) { if (handle > fs->handles_count) return NULL; @@ -305,28 +316,47 @@ 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); - return (void *)fs; + filesystem = silc_calloc(1, sizeof(*filesystem)); + if (!filesystem) { + silc_free(fs->root); + silc_free(fs); + return NULL; + } + + 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,20 +368,23 @@ 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; - if (!mem_add_entry(dir ? dir : fs->root, entry, FALSE)) + if (!mem_add_entry(dir ? dir : memfs->root, entry, FALSE)) return NULL; return entry; @@ -364,21 +397,24 @@ 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) +bool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir) { - MemFS fs = (MemFS)context; + MemFS memfs = (MemFS)fs->fs_context; bool ret; if (dir) return mem_del_entry(dir, FALSE); /* Remove from root */ - ret = mem_del_entry(fs->root, FALSE); + ret = mem_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); return ret; } @@ -391,45 +427,47 @@ 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, +bool 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->name = strdup(filename); entry->data = strdup(realpath); entry->directory = FALSE; - return mem_add_entry(dir ? dir : fs->root, entry, FALSE); + return mem_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, +bool 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 mem_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) + SilcUInt32 data_len) { MemFS fs = (MemFS)context; - uint32 handle; + SilcUInt32 handle; if (data_len < 4) return NULL; @@ -440,19 +478,21 @@ SilcSFTPHandle mem_get_handle(void *context, SilcSFTP sftp, unsigned char *mem_encode_handle(void *context, SilcSFTP sftp, SilcSFTPHandle handle, - uint32 *handle_len) + 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, +void mem_open(void *context, SilcSFTP sftp, const char *filename, SilcSFTPFileOperation pflags, SilcSFTPAttributes attrs, @@ -480,20 +520,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,9 +548,9 @@ 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); return; @@ -518,8 +558,12 @@ void mem_open(void *context, SilcSFTP sftp, /* File opened, return handle */ handle = mem_create_handle(fs, fd, entry); - (*callback)(sftp, SILC_SFTP_STATUS_OK, (SilcSFTPHandle)handle, - callback_context); + 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, @@ -532,9 +576,9 @@ void mem_close(void *context, SilcSFTP sftp, 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(errno), NULL, NULL, callback_context); return; } @@ -546,8 +590,8 @@ void mem_close(void *context, SilcSFTP sftp, void mem_read(void *context, SilcSFTP sftp, SilcSFTPHandle handle, - uint64 offset, - uint32 len, + SilcUInt64 offset, + SilcUInt32 len, SilcSFTPDataCallback callback, void *callback_context) { @@ -559,10 +603,14 @@ void mem_read(void *context, SilcSFTP sftp, len = 32768; data = silc_malloc(len); + if (!data) { + (*callback)(sftp, SILC_SFTP_STATUS_EOF, NULL, 0, callback_context); + return; + } lseek(h->fd, (off_t)offset, SEEK_SET); /* 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); @@ -573,7 +621,7 @@ void mem_read(void *context, SilcSFTP sftp, } /* 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); @@ -581,9 +629,9 @@ void mem_read(void *context, SilcSFTP sftp, void mem_write(void *context, SilcSFTP sftp, SilcSFTPHandle handle, - uint64 offset, + SilcUInt64 offset, const unsigned char *data, - uint32 data_len, + SilcUInt32 data_len, SilcSFTPStatusCallback callback, void *callback_context) { @@ -593,9 +641,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(errno), NULL, NULL, callback_context); return; } @@ -609,7 +657,7 @@ void mem_remove(void *context, SilcSFTP sftp, 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); } @@ -620,7 +668,7 @@ void mem_rename(void *context, SilcSFTP sftp, 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); } @@ -631,7 +679,7 @@ void mem_mkdir(void *context, SilcSFTP sftp, 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); } @@ -641,7 +689,7 @@ void mem_rmdir(void *context, SilcSFTP sftp, 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); } @@ -655,7 +703,7 @@ void mem_opendir(void *context, SilcSFTP sftp, 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); @@ -667,19 +715,23 @@ 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); + 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, @@ -693,7 +745,7 @@ 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; @@ -708,6 +760,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 +775,41 @@ void mem_readdir(void *context, SilcSFTP sftp, filesize = sizeof(*entry); memset(long_name, 0, sizeof(long_name)); - date = ctime(&entry->created); + date = (char *)silc_get_time(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); + memset(&stats, 0, sizeof(stats)); + stat(entry->data + 7, &stats); + } /* Long name format is: drwx------ 1 324210 Apr 8 08:40 mail/ 1234567890 123 12345678 123456789012 */ - snprintf(long_name, sizeof(long_name), - "%c%c%c%c------ %3d %8lu %12s %s%s", + 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; @@ -790,7 +857,7 @@ void mem_stat(void *context, SilcSFTP sftp, struct stat 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); @@ -802,7 +869,7 @@ 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); @@ -812,6 +879,10 @@ void mem_stat(void *context, SilcSFTP sftp, } 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); @@ -822,7 +893,7 @@ void mem_stat(void *context, SilcSFTP sftp, attrs->mtime = stats.st_mtime; /* 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); @@ -840,7 +911,7 @@ void mem_lstat(void *context, SilcSFTP sftp, struct stat 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); @@ -852,16 +923,24 @@ 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 */ +#ifndef SILC_WIN32 ret = lstat(entry->data + 7, &stats); +#else + ret = stat(entry->data + 7, &stats); +#endif if (ret == -1) { (*callback)(sftp, silc_sftp_map_errno(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); @@ -872,7 +951,7 @@ void mem_lstat(void *context, SilcSFTP sftp, attrs->mtime = stats.st_mtime; /* 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); @@ -891,7 +970,7 @@ void mem_fstat(void *context, SilcSFTP sftp, 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); @@ -901,6 +980,10 @@ void mem_fstat(void *context, SilcSFTP sftp, } 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); @@ -911,12 +994,12 @@ void mem_fstat(void *context, SilcSFTP sftp, attrs->mtime = stats.st_mtime; /* 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, @@ -924,7 +1007,7 @@ void mem_setstat(void *context, SilcSFTP sftp, 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); } @@ -935,7 +1018,7 @@ void mem_fsetstat(void *context, SilcSFTP sftp, 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); } @@ -956,7 +1039,7 @@ void mem_symlink(void *context, SilcSFTP sftp, 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); } @@ -970,42 +1053,55 @@ void mem_realpath(void *context, SilcSFTP sftp, 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; - } + 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, + 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 = { +const struct SilcSFTPFilesystemOpsStruct silc_sftp_fs_memory = { mem_get_handle, mem_encode_handle, mem_open,