From 5586a7f0e211638059148cc853e47caedf53d098 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sun, 3 Feb 2008 17:51:02 +0200 Subject: [PATCH] Added silc_file_stat, silc_file_fstat and silc_file_fsize --- lib/silcutil/silcfileutil.c | 178 +++++++++++++++++++++++++++--- lib/silcutil/silcfileutil.h | 145 +++++++++++++++++++++--- lib/silcutil/tests/test_silcdir.c | 28 ++--- lib/silcutil/unix/silcunixdir.c | 119 ++------------------ 4 files changed, 318 insertions(+), 152 deletions(-) diff --git a/lib/silcutil/silcfileutil.c b/lib/silcutil/silcfileutil.c index a4b9739c..e21da72d 100644 --- a/lib/silcutil/silcfileutil.c +++ b/lib/silcutil/silcfileutil.c @@ -165,6 +165,11 @@ char *silc_file_readfile(const char *filename, SilcUInt32 *return_len, } buffer = silc_calloc(filelen + 1, sizeof(*buffer)); + if (!buffer) { + silc_set_errno_posix(errno); + silc_file_close(fd); + return NULL; + } if ((silc_file_read(fd, buffer, filelen)) == -1) { memset(buffer, 0, sizeof(buffer)); @@ -183,26 +188,169 @@ char *silc_file_readfile(const char *filename, SilcUInt32 *return_len, return (char *)buffer; } -/* Returns the size of `filename'. Returns 0 on error. */ +/* Returns the size of `filename'. */ SilcUInt64 silc_file_size(const char *filename) { - int ret; - struct stat stats; + SilcFileStatStruct status; -#ifdef SILC_WIN32 - ret = stat(filename, &stats); -#endif /* SILC_WIN32 */ -#ifdef SILC_UNIX - ret = lstat(filename, &stats); -#endif /* SILC_UNIX */ -#ifdef SILC_SYMBIAN - ret = stat(filename, &stats); -#endif /* SILC_SYMBIAN */ - if (ret < 0) { - silc_set_errno_posix(errno); + if (!silc_file_stat(filename, FALSE, &status)) return 0; + + return status.size; +} + +/* Return file size */ + +SilcUInt64 silc_file_fsize(int fd) +{ + SilcFileStatStruct status; + + if (!silc_file_fstat(fd, &status)) + return 0; + + return status.size; +} + +/* Fill file status context */ + +static void silc_file_fill_stat(struct stat *status, + SilcFileStat return_stat) +{ + memset(return_stat, 0, sizeof(*return_stat)); + + silc_time_value(status->st_atime * 1000, &return_stat->last_access); + silc_time_value(status->st_mtime * 1000, &return_stat->last_mod); + silc_time_value(status->st_ctime * 1000, &return_stat->last_change); + + return_stat->rdev = status->st_rdev; + return_stat->dev = status->st_dev; + return_stat->nlink = status->st_nlink; + return_stat->gid = status->st_gid; + return_stat->uid = status->st_uid; + return_stat->size = status->st_size; + +#if defined(S_IFSOCK) + if (status->st_mode & S_IFSOCK) + return_stat->mode |= SILC_FILE_IFSOCK; +#endif /* S_IFSOCK */ +#if defined(S_IFLNK) + if (status->st_mode & S_IFLNK) + return_stat->mode |= SILC_FILE_IFLNK; +#endif /* S_IFLNK */ +#if defined(S_IFREG) + if (status->st_mode & S_IFREG) + return_stat->mode |= SILC_FILE_IFREG; +#endif /* S_IFREG */ +#if defined(S_IFBLK) + if (status->st_mode & S_IFBLK) + return_stat->mode |= SILC_FILE_IFBLK; +#endif /* S_IFBLK */ +#if defined(S_IFDIR) + if (status->st_mode & S_IFDIR) + return_stat->mode |= SILC_FILE_IFDIR; +#endif /* S_IFDIR */ +#if defined(S_IFCHR) + if (status->st_mode & S_IFCHR) + return_stat->mode |= SILC_FILE_IFCHR; +#endif /* S_IFCHR */ +#if defined(S_IFIFO) + if (status->st_mode & S_IFIFO) + return_stat->mode |= SILC_FILE_IFIFO; +#endif /* S_IFIFO */ +#if defined(S_IRUSR) + if (status->st_mode & S_IRUSR) + return_stat->mode |= SILC_FILE_IRUSR; +#endif /* S_IRUSR */ +#if defined(S_IWUSR) + if (status->st_mode & S_IWUSR) + return_stat->mode |= SILC_FILE_IWUSR; +#endif /* S_IWUSR */ +#if defined(S_IXUSR) + if (status->st_mode & S_IXUSR) + return_stat->mode |= SILC_FILE_IXUSR; +#endif /* S_IXUSR */ +#if defined(S_IRGRP) + if (status->st_mode & S_IRGRP) + return_stat->mode |= SILC_FILE_IRGRP; +#endif /* S_IRGRP */ +#if defined(S_IWGRP) + if (status->st_mode & S_IWGRP) + return_stat->mode |= SILC_FILE_IWGRP; +#endif /* S_IWGRP */ +#if defined(S_IXGRP) + if (status->st_mode & S_IXGRP) + return_stat->mode |= SILC_FILE_IXGRP; +#endif /* S_IXGRP */ +#if defined(S_IROTH) + if (status->st_mode & S_IROTH) + return_stat->mode |= SILC_FILE_IROTH; +#endif /* S_IROTH */ +#if defined(S_IWOTH) + if (status->st_mode & S_IWOTH) + return_stat->mode |= SILC_FILE_IWOTH; +#endif /* S_IWOTH */ +#if defined(S_IXOTH) + if (status->st_mode & S_IXOTH) + return_stat->mode |= SILC_FILE_IXOTH; +#endif /* S_IXOTH */ +} + +/* Return file status information */ + +SilcBool silc_file_stat(const char *filename, SilcBool follow_symlinks, + SilcFileStat return_stat) +{ + struct stat status; + + if (silc_unlikely(!filename || !return_stat)) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; } - return (SilcUInt64)stats.st_size; + SILC_LOG_DEBUG(("Get status for file '%s'", filename)); + + if (!follow_symlinks) { + if (silc_unlikely(stat(filename, &status) != 0)) { + silc_set_errno_posix(errno); + return FALSE; + } + } else { +#ifdef HAVE_LSTAT + if (silc_unlikely(lstat(filename, &status) != 0)) { + silc_set_errno_posix(errno); + return FALSE; + } +#else + if (silc_unlikely(stat(filename, &status) != 0)) { + silc_set_errno_posix(errno); + return FALSE; + } +#endif /* HAVE_LSTAT */ + } + + silc_file_fill_stat(&status, return_stat); + + return TRUE; +} + +/* Return file status information. */ + +SilcBool silc_file_fstat(int fd, SilcFileStat return_stat) +{ + struct stat status; + + if (silc_unlikely(!return_stat)) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + + if (silc_unlikely(fstat(fd, &status) != 0)) { + silc_set_errno_posix(errno); + return FALSE; + } + + silc_file_fill_stat(&status, return_stat); + + return TRUE; } diff --git a/lib/silcutil/silcfileutil.h b/lib/silcutil/silcfileutil.h index a02c49b3..08245538 100644 --- a/lib/silcutil/silcfileutil.h +++ b/lib/silcutil/silcfileutil.h @@ -17,7 +17,7 @@ */ -/****h* silcutil/SILC File Util Interface +/****h* silcutil/File Util Interface * * DESCRIPTION * @@ -29,9 +29,74 @@ #ifndef SILCFILEUTIL_H #define SILCFILEUTIL_H +/****d* silcutil/SilcFileMode + * + * NAME + * + * typedef enum { ... } SilcFileMode; + * + * DESCRIPTION + * + * A file mode bits that specify the file's mode, type and protection + * in the SilcFileStat context. + * + * SOURCE + */ +typedef enum { + /* Type */ + SILC_FILE_IFDIR = 0x00000001, /* Entry is directory */ + SILC_FILE_IFCHR = 0x00000002, /* Entry is character device */ + SILC_FILE_IFBLK = 0x00000004, /* Entry is block device */ + SILC_FILE_IFREG = 0x00000008, /* Entry is regular file */ + SILC_FILE_IFIFO = 0x00000010, /* Entry is FIFO */ + SILC_FILE_IFLNK = 0x00000020, /* Entry is symbolic link */ + SILC_FILE_IFSOCK = 0x00000040, /* Entry is socket */ + + /* Protection */ + SILC_FILE_IRUSR = 0x00000080, /* Owner has read permission */ + SILC_FILE_IWUSR = 0x00000100, /* Owner has write permission */ + SILC_FILE_IXUSR = 0x00000200, /* Owner has execute permission */ + SILC_FILE_IRGRP = 0x00000400, /* Group has read permission */ + SILC_FILE_IWGRP = 0x00000800, /* Group has write permission */ + SILC_FILE_IXGRP = 0x00001000, /* Group has execute permission */ + SILC_FILE_IROTH = 0x00002000, /* Others have read permission */ + SILC_FILE_IWOTH = 0x00004000, /* Others have write permission */ + SILC_FILE_IXOTH = 0x00008000, /* Others have execute permission */ +} SilcFileMode; +/***/ + +/****s* silcutil/SilcFileStat + * + * NAME + * + * typedef struct SilcFileStatObject { ... } *SilcFileStat, + * SilcFileStatStruct; + * + * DESCRIPTION + * + * The file entry status information structure. The structure contains + * various information about a file. The structure is filled by calling + * the silc_file_stat or silc_file_fstat functions. + * + * SOURCE + */ +typedef struct SilcFileStatObject { + SilcTimeStruct last_access; /* Time of last access */ + SilcTimeStruct last_mod; /* Time of last modification */ + SilcTimeStruct last_change; /* Time of last status change */ + SilcUInt64 size; /* Entry size in bytes */ + SilcUInt32 uid; /* Owner ID of the entry */ + SilcUInt32 gid; /* Group owner ID of the entry */ + SilcUInt32 dev; /* Entry device number */ + SilcUInt32 rdev; /* Device number if special file */ + SilcUInt32 nlink; /* Number of hard links */ + SilcFileMode mode; /* Entry mode */ +} *SilcFileStat, SilcFileStatStruct; +/***/ + /* Prototypes */ -/****f* silcutil/SilcFileUtilAPI/silc_file_open +/****f* silcutil/silc_file_open * * SYNOPSIS * @@ -47,7 +112,7 @@ ***/ int silc_file_open(const char *filename, int flags); -/****f* silcutil/SilcFileUtilAPI/silc_file_open_mode +/****f* silcutil/silc_file_open_mode * * SYNOPSIS * @@ -63,7 +128,7 @@ int silc_file_open(const char *filename, int flags); ***/ int silc_file_open_mode(const char *filename, int flags, int mode); -/****f* silcutil/SilcFileUtilAPI/silc_file_read +/****f* silcutil/silc_file_read * * SYNOPSIS * @@ -77,7 +142,7 @@ int silc_file_open_mode(const char *filename, int flags, int mode); ***/ int silc_file_read(int fd, unsigned char *buf, SilcUInt32 buf_len); -/****f* silcutil/SilcFileUtilAPI/silc_file_write +/****f* silcutil/silc_file_write * * SYNOPSIS * @@ -91,7 +156,7 @@ int silc_file_read(int fd, unsigned char *buf, SilcUInt32 buf_len); ***/ int silc_file_write(int fd, const char *buffer, SilcUInt32 len); -/****f* silcutil/SilcFileUtilAPI/silc_file_close +/****f* silcutil/silc_file_close * * SYNOPSIS * @@ -105,7 +170,7 @@ int silc_file_write(int fd, const char *buffer, SilcUInt32 len); ***/ int silc_file_close(int fd); -/****f* silcutil/SilcFileUtilAPI/silc_file_set_nonblock +/****f* silcutil/silc_file_set_nonblock * * SYNOPSIS * @@ -118,7 +183,7 @@ int silc_file_close(int fd); ***/ int silc_file_set_nonblock(int fd); -/****f* silcutil/SilcFileUtilAPI/silc_file_readfile +/****f* silcutil/silc_file_readfile * * SYNOPSIS * @@ -133,7 +198,7 @@ int silc_file_set_nonblock(int fd); * NULL terminated. * * If the `return_len' pointer is not NULL, it's filled with the length of - * the file. + * the file. The returned length does not include the terminator. * * If `stack' is non-NULL the returned buffer is allocated from `stack'. * The allocation consumes `stack' so caller should push the stack before @@ -143,7 +208,7 @@ int silc_file_set_nonblock(int fd); char *silc_file_readfile(const char *filename, SilcUInt32 *return_len, SilcStack stack); -/****f* silcutil/SilcFileUtilAPI/silc_file_writefile +/****f* silcutil/silc_file_writefile * * SYNOPSIS * @@ -159,7 +224,7 @@ char *silc_file_readfile(const char *filename, SilcUInt32 *return_len, int silc_file_writefile(const char *filename, const char *buffer, SilcUInt32 len); -/****f* silcutil/SilcFileUtilAPI/silc_file_writefile_mode +/****f* silcutil/silc_file_writefile_mode * * SYNOPSIS * @@ -175,7 +240,7 @@ int silc_file_writefile(const char *filename, const char *buffer, int silc_file_writefile_mode(const char *filename, const char *buffer, SilcUInt32 len, int mode); -/****f* silcutil/SilcFileUtilAPI/silc_file_size +/****f* silcutil/silc_file_size * * SYNOPSIS * @@ -183,9 +248,63 @@ int silc_file_writefile_mode(const char *filename, const char *buffer, * * DESCRIPTION * - * Returns the size of `filename'. Returns 0 on error. + * Returns the size of `filename'. Returns 0 on error and sets silc_errno. + * If silc_errno is not set the file size is 0 bytes if this returns 0. * ***/ SilcUInt64 silc_file_size(const char *filename); +/****f* silcutil/silc_file_fsize + * + * SYNOPSIS + * + * SilcUInt64 silc_file_fsize(int fd); + * + * DESCRIPTION + * + * Returns the size of the file indicated by open file descriptor `fd'. + * Returns 0 on error and sets silc_errno. If silc_errno is not set the + * file size is 0 bytes if this returns 0. + * + ***/ +SilcUInt64 silc_file_fsize(int fd); + +/****f* silcutil/silc_file_stat + * + * SYNOPSIS + * + * SilcBool silc_file_stat(const char *filename, SilcBool follow_symlinks, + * SilcFileStat return_stat); + * + * DESCRIPTION + * + * Returns status information of a file named `filename'. The status + * information is returned to `return_stat' structure. If the + * `follow_symlinks' is TRUE this will return the status of the file the + * symlink referts to. If it is FALSE, returns the status of the link + * itself. + * + * Returns FALSE on error and sets the silc_errno. Returns TRUE otherwise. + * + ***/ +SilcBool silc_file_stat(const char *filename, SilcBool follow_symlinks, + SilcFileStat return_stat); + +/****f* silcutil/silc_file_fstat + * + * SYNOPSIS + * + * SilcBool silc_file_fstat(int fd, SilcFileStat return_stat); + * + * DESCRIPTION + * + * Returns status information of a opened file indicated by the file + * descriptor `fd'. The status information is returned to the + * `return_stat' structure. + * + * Returns FALSE on error and sets the silc_errno. Returns TRUE otherwise. + * + ***/ +SilcBool silc_file_fstat(int fd, SilcFileStat return_stat); + #endif /* !SILCFILEUTIL_H */ diff --git a/lib/silcutil/tests/test_silcdir.c b/lib/silcutil/tests/test_silcdir.c index 151aad67..3f8bff74 100644 --- a/lib/silcutil/tests/test_silcdir.c +++ b/lib/silcutil/tests/test_silcdir.c @@ -7,7 +7,7 @@ int main(int argc, char **argv) SilcBool success = FALSE; SilcDir dir; SilcDirEntry entry; - SilcDirEntryStat status; + SilcFileStatStruct status; if (argc > 1 && !strcmp(argv[1], "-d")) { silc_log_debug(TRUE); @@ -24,19 +24,19 @@ int main(int argc, char **argv) while ((entry = silc_dir_read(dir, &status))) printf( "%c%c%c%c%c%c%c%c%c%c %3d %4d %4d %8lu %04d-%02d-%02d %02d:%02d %s\n", - status->mode & SILC_DIR_ENTRY_IFDIR ? 'd' : '-', - status->mode & SILC_DIR_ENTRY_IRUSR ? 'r' : '-', - status->mode & SILC_DIR_ENTRY_IWUSR ? 'w' : '-', - status->mode & SILC_DIR_ENTRY_IXUSR ? 'x' : '-', - status->mode & SILC_DIR_ENTRY_IRGRP ? 'r' : '-', - status->mode & SILC_DIR_ENTRY_IWGRP ? 'w' : '-', - status->mode & SILC_DIR_ENTRY_IXGRP ? 'x' : '-', - status->mode & SILC_DIR_ENTRY_IROTH ? 'r' : '-', - status->mode & SILC_DIR_ENTRY_IWOTH ? 'w' : '-', - status->mode & SILC_DIR_ENTRY_IXOTH ? 'x' : '-', - status->nlink, status->uid, status->gid, status->size, - status->last_mod.year, status->last_mod.month, status->last_mod.day, - status->last_mod.hour, status->last_mod.minute, + status.mode & SILC_FILE_IFDIR ? 'd' : '-', + status.mode & SILC_FILE_IRUSR ? 'r' : '-', + status.mode & SILC_FILE_IWUSR ? 'w' : '-', + status.mode & SILC_FILE_IXUSR ? 'x' : '-', + status.mode & SILC_FILE_IRGRP ? 'r' : '-', + status.mode & SILC_FILE_IWGRP ? 'w' : '-', + status.mode & SILC_FILE_IXGRP ? 'x' : '-', + status.mode & SILC_FILE_IROTH ? 'r' : '-', + status.mode & SILC_FILE_IWOTH ? 'w' : '-', + status.mode & SILC_FILE_IXOTH ? 'x' : '-', + status.nlink, status.uid, status.gid, status.size, + status.last_mod.year, status.last_mod.month, status.last_mod.day, + status.last_mod.hour, status.last_mod.minute, silc_dir_entry_name(entry)); fflush(stdout); diff --git a/lib/silcutil/unix/silcunixdir.c b/lib/silcutil/unix/silcunixdir.c index 49de3079..ffd3535c 100644 --- a/lib/silcutil/unix/silcunixdir.c +++ b/lib/silcutil/unix/silcunixdir.c @@ -24,7 +24,7 @@ /* Directory entry context */ struct SilcDirEntryStruct { struct dirent *entry; /* Entry */ - SilcDirEntryStatStruct status; /* Status */ + SilcFileStatStruct status; /* Status */ }; /* The directory context */ @@ -89,7 +89,7 @@ void silc_dir_close(SilcDir dir) /* Read next entry in the directory */ -SilcDirEntry silc_dir_read(SilcDir dir, SilcDirEntryStat *status) +SilcDirEntry silc_dir_read(SilcDir dir, SilcFileStat status) { if (!dir) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); @@ -105,8 +105,13 @@ SilcDirEntry silc_dir_read(SilcDir dir, SilcDirEntryStat *status) return NULL; } - if (status) - *status = silc_dir_entry_stat(dir, &dir->entry); + if (status) { + char *name = NULL; + silc_asprintf(&name, "%s/%s", dir->name, dir->entry.entry->d_name); + if (name) + silc_file_stat(name, TRUE, status); + silc_free(name); + } return (SilcDirEntry)&dir->entry; } @@ -146,109 +151,3 @@ const char *silc_dir_entry_name(SilcDirEntry entry) return (const char *)entry->entry->d_name; } - -/* Return entry status information */ - -SilcDirEntryStat silc_dir_entry_stat(SilcDir dir, SilcDirEntry entry) -{ - struct stat status; - char *name = NULL; - - if (!dir || !entry) { - silc_set_errno(SILC_ERR_INVALID_ARGUMENT); - return NULL; - } - - silc_asprintf(&name, "%s/%s", dir->name, entry->entry->d_name); - if (!name) - return NULL; - - SILC_LOG_DEBUG(("Get status for entry '%s'", name)); - - if (lstat(name, &status) != 0) { - silc_set_errno_posix(errno); - silc_free(name); - return NULL; - } - - silc_free(name); - - memset(&entry->status, 0, sizeof(entry->status)); - - silc_time_value(status.st_atime * 1000, &entry->status.last_access); - silc_time_value(status.st_mtime * 1000, &entry->status.last_mod); - silc_time_value(status.st_ctime * 1000, &entry->status.last_change); - - entry->status.dev = status.st_dev; - entry->status.nlink = status.st_nlink; - entry->status.gid = status.st_gid; - entry->status.uid = status.st_uid; - entry->status.size = status.st_size; - -#if defined(S_IFSOCK) - if (status.st_mode & S_IFSOCK) - entry->status.mode |= SILC_DIR_ENTRY_IFSOCK; -#endif /* S_IFSOCK */ -#if defined(S_IFLNK) - if (status.st_mode & S_IFLNK) - entry->status.mode |= SILC_DIR_ENTRY_IFLNK; -#endif /* S_IFLNK */ -#if defined(S_IFREG) - if (status.st_mode & S_IFREG) - entry->status.mode |= SILC_DIR_ENTRY_IFREG; -#endif /* S_IFREG */ -#if defined(S_IFBLK) - if (status.st_mode & S_IFBLK) - entry->status.mode |= SILC_DIR_ENTRY_IFBLK; -#endif /* S_IFBLK */ -#if defined(S_IFDIR) - if (status.st_mode & S_IFDIR) - entry->status.mode |= SILC_DIR_ENTRY_IFDIR; -#endif /* S_IFDIR */ -#if defined(S_IFCHR) - if (status.st_mode & S_IFCHR) - entry->status.mode |= SILC_DIR_ENTRY_IFCHR; -#endif /* S_IFCHR */ -#if defined(S_IFIFO) - if (status.st_mode & S_IFIFO) - entry->status.mode |= SILC_DIR_ENTRY_IFIFO; -#endif /* S_IFIFO */ -#if defined(S_IRUSR) - if (status.st_mode & S_IRUSR) - entry->status.mode |= SILC_DIR_ENTRY_IRUSR; -#endif /* S_IRUSR */ -#if defined(S_IWUSR) - if (status.st_mode & S_IWUSR) - entry->status.mode |= SILC_DIR_ENTRY_IWUSR; -#endif /* S_IWUSR */ -#if defined(S_IXUSR) - if (status.st_mode & S_IXUSR) - entry->status.mode |= SILC_DIR_ENTRY_IXUSR; -#endif /* S_IXUSR */ -#if defined(S_IRGRP) - if (status.st_mode & S_IRGRP) - entry->status.mode |= SILC_DIR_ENTRY_IRGRP; -#endif /* S_IRGRP */ -#if defined(S_IWGRP) - if (status.st_mode & S_IWGRP) - entry->status.mode |= SILC_DIR_ENTRY_IWGRP; -#endif /* S_IWGRP */ -#if defined(S_IXGRP) - if (status.st_mode & S_IXGRP) - entry->status.mode |= SILC_DIR_ENTRY_IXGRP; -#endif /* S_IXGRP */ -#if defined(S_IROTH) - if (status.st_mode & S_IROTH) - entry->status.mode |= SILC_DIR_ENTRY_IROTH; -#endif /* S_IROTH */ -#if defined(S_IWOTH) - if (status.st_mode & S_IWOTH) - entry->status.mode |= SILC_DIR_ENTRY_IWOTH; -#endif /* S_IWOTH */ -#if defined(S_IXOTH) - if (status.st_mode & S_IXOTH) - entry->status.mode |= SILC_DIR_ENTRY_IXOTH; -#endif /* S_IXOTH */ - - return (SilcDirEntryStat)&entry->status; -} -- 2.24.0