From c83c0ac17babbc8b3f4bb82dab2cfeb03065d867 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Tue, 15 Jan 2008 17:52:24 +0000 Subject: [PATCH] Added and implemented Silc DIR API. --- CHANGES.RUNTIME | 6 + TODO | 8 +- configure.ad | 4 +- includes/silc.h.in | 4 +- includes/silcwin32.h | 6 +- lib/silcutil/silcdir.h | 240 ++++++++++++++++++++++++++++ lib/silcutil/silcerrno.h | 2 +- lib/silcutil/tests/Makefile.am | 3 +- lib/silcutil/tests/test_silcdir.c | 53 +++++++ lib/silcutil/unix/Makefile.am | 5 +- lib/silcutil/unix/silcunixdir.c | 249 ++++++++++++++++++++++++++++++ 11 files changed, 566 insertions(+), 14 deletions(-) create mode 100644 lib/silcutil/silcdir.h create mode 100644 lib/silcutil/tests/test_silcdir.c create mode 100644 lib/silcutil/unix/silcunixdir.c diff --git a/CHANGES.RUNTIME b/CHANGES.RUNTIME index 400f6eb3..e9168998 100644 --- a/CHANGES.RUNTIME +++ b/CHANGES.RUNTIME @@ -1,3 +1,9 @@ +Tue Jan 15 19:44:36 EET 2008 Pekka Riikonen + + * Added SILC Dir API to lib/silcutil/silcdir.h. Implemented it + for Unix (POSIX). Affected files are lib/silcutil/silcdir.h, + lib/silcutil/unix/silcunixdir.c. + Sun Jan 13 17:11:26 EET 2008 Pekka Riikonen * Added silc_buffer_memcmp and silc_buffer_tail. Fixed SilcBuffer diff --git a/TODO b/TODO index 569d4dd8..9ae27025 100644 --- a/TODO +++ b/TODO @@ -97,10 +97,6 @@ Runtime library, lib/silcutil/ o Fix universal time decoding (doesn't accept all formats) in silctime.c. - o Add directory opening/traversing functions - - o regex from /lib/contrib to lib/silcutil, define SILC Regex API. (***DONE) - o Additional scheduler changes: optimize silc_schedule_wakeup. Wakeup only if the scheduler is actually waiting something. If it is delivering tasks wakeup is not needed. @@ -111,6 +107,10 @@ Runtime library, lib/silcutil/ SILC currently supports SOCKS4 and SOCKS5 but it needs to be compiled in separately. + o Add directory opening/traversing functions (***DONE, TODO Windows & Symbian) + + o regex from /lib/contrib to lib/silcutil, define SILC Regex API. (***DONE) + o Add functions to manipulate environment variables. (***DONE) o Add functions to loading shared/dynamic object symbols (replaces the diff --git a/configure.ad b/configure.ad index 7467c0c3..a162625a 100644 --- a/configure.ad +++ b/configure.ad @@ -3,7 +3,7 @@ # # Author: Pekka Riikonen # -# Copyright (C) 2000 - 2007 Pekka Riikonen +# Copyright (C) 2000 - 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 @@ -228,7 +228,7 @@ AC_CHECK_HEADERS(unistd.h string.h errno.h fcntl.h assert.h) AC_CHECK_HEADERS(sys/types.h sys/stat.h sys/time.h stddef.h) AC_CHECK_HEADERS(netinet/in.h netinet/tcp.h xti.h netdb.h sys/resource.h) AC_CHECK_HEADERS(pwd.h grp.h termcap.h paths.h) -AC_CHECK_HEADERS(ncurses.h signal.h ctype.h utime.h) +AC_CHECK_HEADERS(ncurses.h signal.h ctype.h utime.h dirent.h) AC_CHECK_HEADERS(arpa/inet.h sys/mman.h limits.h termios.h locale.h langinfo.h) # Data type checking diff --git a/includes/silc.h.in b/includes/silc.h.in index 669c1343..c64d33b8 100644 --- a/includes/silc.h.in +++ b/includes/silc.h.in @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 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 @@ -130,6 +130,7 @@ extern "C" { #include #include #include +#include #ifdef HAVE_SIGNAL_H #include @@ -255,6 +256,7 @@ extern "C" { #include "silcthread.h" #include "silcschedule.h" #include "silclog.h" +#include "silcdir.h" #include "silcfileutil.h" #include "silcbuffer.h" #include "silcbuffmt.h" diff --git a/includes/silcwin32.h b/includes/silcwin32.h index 41af9794..79430bd9 100644 --- a/includes/silcwin32.h +++ b/includes/silcwin32.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2003 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 @@ -31,8 +31,8 @@ #include "regexpr.h" #endif /* HAVE_SILCDEFS_H */ -#define snprintf _snprintf -#define vsnprintf _vsnprintf +#define snprintf silc_snprintf +#define vsnprintf silc_vsnprintf #ifdef WIN32 #define strcasecmp stricmp diff --git a/lib/silcutil/silcdir.h b/lib/silcutil/silcdir.h new file mode 100644 index 00000000..25fb314b --- /dev/null +++ b/lib/silcutil/silcdir.h @@ -0,0 +1,240 @@ +/* + + silcdir.h + + Author: Pekka Riikonen + + Copyright (C) 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +/****h* silcutil/SILC Directory Interface + * + * DESCRIPTION + * + * The SILC Directory API provides portable way to open and read directories + * and their content. + * + * EXAMPLE + * + * SilcDir dir; + * SilcDirEntry entry; + * + * dir = silc_dir_open("foodir"); + * + * while ((entry = silc_dir_read(dir, NULL))) + * printf("File name: %s", silc_dir_entry_name(entry)); + * + * silc_dir_close(dir); + * + ***/ + +#ifndef SILCDIR_H +#define SILCDIR_H + +/****s* silcutil/SilcDirAPI/SilcDir + * + * NAME + * + * typedef struct SilcDirStruct *SilcDir; + * + * DESCRIPTION + * + * The directory context. This is allocated by silc_dir_open and + * freed by calling silc_dir_close. + * + ***/ +typedef struct SilcDirStruct *SilcDir; + +/****s* silcutil/SilcDirAPI/SilcDirEntry + * + * NAME + * + * typedef struct SilcDirEntryStruct *SilcDirEntry; + * + * DESCRIPTION + * + * The directory entry context. The entry is usually a file in the + * directory. + * + ***/ +typedef struct SilcDirEntryStruct *SilcDirEntry; + +/****d* silcutil/SilcDirAPI/SilcDirEntryModen + * + * NAME + * + * typedef enum { ... } SilcDirEntryMode; + * + * DESCRIPTION + * + * The directory entry mode bits. These bits specify the entry mode, + * type and protection. + * + ***/ +typedef enum { + /* Type */ + SILC_DIR_ENTRY_IFDIR = 0x00000001, /* Entry is directory */ + SILC_DIR_ENTRY_IFCHR = 0x00000002, /* Entry is character device */ + SILC_DIR_ENTRY_IFBLK = 0x00000004, /* Entry is block device */ + SILC_DIR_ENTRY_IFREG = 0x00000008, /* Entry is regular file */ + SILC_DIR_ENTRY_IFIFO = 0x00000010, /* Entry is FIFO */ + SILC_DIR_ENTRY_IFLNK = 0x00000020, /* Entry is symbolic link */ + SILC_DIR_ENTRY_IFSOCK = 0x00000040, /* Entry is socket */ + + /* Protection */ + SILC_DIR_ENTRY_IRUSR = 0x00000080, /* Owner has read permission */ + SILC_DIR_ENTRY_IWUSR = 0x00000100, /* Owner has write permission */ + SILC_DIR_ENTRY_IXUSR = 0x00000200, /* Owner has execute permission */ + SILC_DIR_ENTRY_IRGRP = 0x00000400, /* Group has read permission */ + SILC_DIR_ENTRY_IWGRP = 0x00000800, /* Group has write permission */ + SILC_DIR_ENTRY_IXGRP = 0x00001000, /* Group has execute permission */ + SILC_DIR_ENTRY_IROTH = 0x00002000, /* Others have read permission */ + SILC_DIR_ENTRY_IWOTH = 0x00004000, /* Others have write permission */ + SILC_DIR_ENTRY_IXOTH = 0x00008000, /* Others have execute permission */ +} SilcDirEntryMode; + +/****s* silcutil/SilcDirAPI/SilcDirEntryStat + * + * NAME + * + * typedef struct SilcDirEntryObject { ... } *SilcDirEntryStat, + * SilcDirEntryStatStruct; + * + * DESCRIPTION + * + * The directory entry status information structure. The structure + * contains various information about the entry in the directory. + * This context is returned by silc_dir_read or silc_dir_entry_stat. + * + ***/ +typedef struct SilcDirEntryStatObject { + 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 nlink; /* Number of hard links */ + SilcDirEntryMode mode; /* Entry mode */ +} *SilcDirEntryStat, SilcDirEntryStatStruct; + +/****f* silcutil/SilcDirAPI/silc_dir_open + * + * SYNOPSIS + * + * SilcDir silc_dir_open(const char *name); + * + * DESCRIPTION + * + * Opens the directory named `name' and returns its context. Returns NULL + * on error and sets the silc_errno. This function must be called before + * being able to read the directory and its contents. + * + ***/ +SilcDir silc_dir_open(const char *name); + +/****f* silcutil/SilcDirAPI/silc_dir_close + * + * SYNOPSIS + * + * void silc_dir_close(SilcDir dir); + * + * DESCRIPTION + * + * Closes the directory `dir'. + * + ***/ +void silc_dir_close(SilcDir dir); + +/****f* silcutil/SilcDirAPI/silc_dir_read + * + * SYNOPSIS + * + * SilcDirEntry silc_dir_read(SilcDir dir, SilcDirEntryStat *status); + * + * DESCRIPTION + * + * Reads next entry (file) from the directory `dir'. The silc_dir_open + * must be called first before reading from the directory. Returns the + * next entry context or NULL if there are no more entries or error occurs. + * In case of error the silc_errno is also set. + * + * If the `status' is non-NULL this will also call silc_dir_entry_stat + * and returns the status into the `status' pointer. + * + * The returned context remains valid until the silc_dir_read is called + * again. + * + ***/ +SilcDirEntry silc_dir_read(SilcDir dir, SilcDirEntryStat *status); + +/****f* silcutil/SilcDirAPI/silc_dir_rewind + * + * SYNOPSIS + * + * void silc_dir_rewind(SilcDir dir); + * + * DESCRIPTION + * + * Rewinds the directory `dir' to the beginning of the directory. Calling + * silc_dir_read after this will return the first entry in the directory. + * + ***/ +void silc_dir_rewind(SilcDir dir); + +/****f* silcutil/SilcDirAPI/silc_dir_name + * + * SYNOPSIS + * + * const char *silc_dir_name(SilcDir dir); + * + * DESCRIPTION + * + * Returns the name of the directory from `dir' context. + * + ***/ +const char *silc_dir_name(SilcDir dir); + +/****f* silcutil/SilcDirAPI/silc_dir_entry_name + * + * SYNOPSIS + * + * const char *silc_dir_entry_name(SilcDirEntry entry); + * + * DESCRIPTION + * + * Returns the name of the entry (file) `entry'. The returned pointer + * remains valid until the silc_dir_read is called again. + * + ***/ +const char *silc_dir_entry_name(SilcDirEntry entry); + +/****f* silcutil/SilcDirAPI/silc_dir_entry_stat + * + * SYNOPSIS + * + * SilcDirEntryStat silc_dir_entry_stat(SilcDir dir, SilcDirEntry entry); + * + * DESCRIPTION + * + * Returns the status of the entry. The status context contains details + * of the entry (file) in the directory. Returns NULL on error and sets + * the silc_errno. + * + * The returned contest is valid until the silc_dir_read is called again. + * + ***/ +SilcDirEntryStat silc_dir_entry_stat(SilcDir dir, SilcDirEntry entry); + +#endif /* SILCDIR_H */ diff --git a/lib/silcutil/silcerrno.h b/lib/silcutil/silcerrno.h index ebf32928..f4760d8a 100644 --- a/lib/silcutil/silcerrno.h +++ b/lib/silcutil/silcerrno.h @@ -44,7 +44,7 @@ * // Get the detailed reason for the error too * if (silc_some_routine() == FALSE) { * fprintf(stderr, "%s (%d) (%s)", silc_errno_string(silc_errno), - * silc_errno, silc_errno_reason); + * silc_errno, silc_errno_reason()); * exit(1); * } * diff --git a/lib/silcutil/tests/Makefile.am b/lib/silcutil/tests/Makefile.am index a08a0863..94f01274 100644 --- a/lib/silcutil/tests/Makefile.am +++ b/lib/silcutil/tests/Makefile.am @@ -22,7 +22,7 @@ bin_PROGRAMS = test_silcstrutil test_silcstringprep test_silchashtable \ test_silcnet test_silcstack test_silcmime test_silcfdstream \ test_silcatomic test_silcmutex test_silctime test_silcthread \ test_silcdll test_silcenv test_silctimer test_silcbitops \ - test_silcregex test_silcbuffmt + test_silcregex test_silcbuffmt test_silcdir test_silcstrutil_SOURCES = test_silcstrutil.c test_silcstringprep_SOURCES = test_silcstringprep.c @@ -45,6 +45,7 @@ test_silctimer_SOURCES = test_silctimer.c test_silcbitops_SOURCES = test_silcbitops.c test_silcregex_SOURCES = test_silcregex.c test_silcbuffmt_SOURCES = test_silcbuffmt.c +test_silcdir_SOURCES = test_silcdir.c LIBS = $(SILC_COMMON_LIBS) LDADD = -L.. -L../.. -lsilc diff --git a/lib/silcutil/tests/test_silcdir.c b/lib/silcutil/tests/test_silcdir.c new file mode 100644 index 00000000..e9e36941 --- /dev/null +++ b/lib/silcutil/tests/test_silcdir.c @@ -0,0 +1,53 @@ +/* SilcDir tests */ + +#include "silc.h" + +int main(int argc, char **argv) +{ + SilcBool success = FALSE; + SilcDir dir; + SilcDirEntry entry; + SilcDirEntryStat status; + + if (argc > 1 && !strcmp(argv[1], "-d")) { + silc_log_debug(TRUE); + silc_log_quick(TRUE); + silc_log_debug_hexdump(TRUE); + silc_log_set_debug_string("*dir*,*errno*"); + } + + dir = silc_dir_open("/etc/"); + if (!dir) + goto err; + + printf("%s:\n", silc_dir_name(dir)); + 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, + silc_dir_entry_name(entry)); + + fflush(stdout); + + silc_dir_close(dir); + + success = TRUE; + + err: + SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE")); + fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE"); + + return success; +} diff --git a/lib/silcutil/unix/Makefile.am b/lib/silcutil/unix/Makefile.am index bb9719e1..1a1c7c31 100644 --- a/lib/silcutil/unix/Makefile.am +++ b/lib/silcutil/unix/Makefile.am @@ -3,7 +3,7 @@ # # Author: Pekka Riikonen # -# Copyright (C) 2001 - 2006 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 @@ -25,6 +25,7 @@ libsilcunixutil_la_SOURCES = \ silcunixnet.c \ silcunixutil.c \ silcunixsocketstream.c \ - silcunixthread.c + silcunixthread.c \ + silcunixdir.c include $(top_srcdir)/Makefile.defines.in diff --git a/lib/silcutil/unix/silcunixdir.c b/lib/silcutil/unix/silcunixdir.c new file mode 100644 index 00000000..e2fa08d5 --- /dev/null +++ b/lib/silcutil/unix/silcunixdir.c @@ -0,0 +1,249 @@ +/* + + silcunixdir.c + + Author: Pekka Riikonen + + Copyright (C) 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*/ + +#include "silc.h" + +/************************** Types and definitions ***************************/ + +/* Directory entry context */ +struct SilcDirEntryStruct { + struct dirent *entry; /* Entry */ + SilcDirEntryStatStruct status; /* Status */ +}; + +/* The directory context */ +struct SilcDirStruct { + DIR *dir; /* Directory */ + char *name; /* Directory name */ + struct SilcDirEntryStruct entry; /* Current entry */ +}; + +/****************************** SILC Dir API ********************************/ + +/* Open directory */ + +SilcDir silc_dir_open(const char *name) +{ + SilcDir dir; + + SILC_LOG_DEBUG(("Open directory '%s'", name)); + + dir = silc_calloc(1, sizeof(*dir)); + if (!dir) + return NULL; + + dir->name = silc_strdup(name); + if (!dir->name) { + silc_free(dir); + return NULL; + } + + if (dir->name[strlen(dir->name) - 1] == '/') + dir->name[strlen(dir->name) - 1] = '\0'; + + dir->dir = opendir(name); + if (!dir->dir) { + silc_set_errno_posix(errno); + silc_free(dir->name); + silc_free(dir); + return NULL; + } + + return dir; +} + +/* Close directory */ + +void silc_dir_close(SilcDir dir) +{ + if (!dir) + return; + + SILC_LOG_DEBUG(("Close directory '%s'", dir->name)); + + closedir(dir->dir); + silc_free(dir->name); + silc_free(dir); +} + +/* Read next entry in the directory */ + +SilcDirEntry silc_dir_read(SilcDir dir, SilcDirEntryStat *status) +{ + if (!dir) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + + SILC_LOG_DEBUG(("Read directory '%s'", dir->name)); + + dir->entry.entry = readdir(dir->dir); + if (!dir->entry.entry) { + if (errno) + silc_set_errno_posix(errno); + return NULL; + } + + if (status) + *status = silc_dir_entry_stat(dir, &dir->entry); + + return (SilcDirEntry)&dir->entry; +} + +/* Rewind directory */ + +void silc_dir_rewind(SilcDir dir) +{ + if (!dir) + return; + + SILC_LOG_DEBUG(("Rewind directory '%s'", dir->name)); + + rewinddir(dir->dir); +} + +/* Return directory name */ + +const char *silc_dir_name(SilcDir dir) +{ + if (!dir) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + + return dir->name; +} + +/* Return entry name */ + +const char *silc_dir_entry_name(SilcDirEntry entry) +{ + if (!entry) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + + 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