op_file.c
Go to the documentation of this file.00001
00012 #include <sys/stat.h>
00013 #include <unistd.h>
00014 #include <fcntl.h>
00015 #include <dirent.h>
00016 #include <fnmatch.h>
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <errno.h>
00020 #include <string.h>
00021 #include <limits.h>
00022
00023 #include "op_file.h"
00024 #include "op_libiberty.h"
00025
00026 int op_file_readable(char const * file)
00027 {
00028 struct stat st;
00029 return !stat(file, &st) && S_ISREG(st.st_mode) && !access(file, R_OK);
00030 }
00031
00032
00033 time_t op_get_mtime(char const * file)
00034 {
00035 struct stat st;
00036
00037 if (stat(file, &st))
00038 return 0;
00039
00040 return st.st_mtime;
00041 }
00042
00043
00044 int create_dir(char const * dir)
00045 {
00046 if (mkdir(dir, 0755)) {
00047
00048 if (errno == EEXIST)
00049 return 0;
00050 return errno;
00051 }
00052
00053 return 0;
00054 }
00055
00056
00057 int create_path(char const * path)
00058 {
00059 int ret = 0;
00060
00061 char * str = xstrdup(path);
00062
00063 char * pos = str[0] == '/' ? str + 1 : str;
00064
00065 for ( ; (pos = strchr(pos, '/')) != NULL; ++pos) {
00066 *pos = '\0';
00067 ret = create_dir(str);
00068 *pos = '/';
00069 if (ret)
00070 break;
00071 }
00072
00073 free(str);
00074 return ret;
00075 }
00076
00077
00078 inline static int is_dot_or_dotdot(char const * name)
00079 {
00080 return name[0] == '.' &&
00081 (name[1] == '\0' ||
00082 (name[1] == '.' && name[2] == '\0'));
00083 }
00084
00085
00086
00087
00088 static char * make_pathname_from_dirent(char const * basedir,
00089 struct dirent * ent,
00090 struct stat * st_buf)
00091 {
00092 int name_len;
00093 char * name;
00094 name_len = strlen(basedir) + strlen("/") + strlen(ent->d_name) + 1;
00095 name = xmalloc(name_len);
00096 sprintf(name, "%s/%s", basedir, ent->d_name);
00097 if (stat(name, st_buf) != 0)
00098 {
00099 struct stat lstat_buf;
00100 int err = errno;
00101 if (lstat(name, &lstat_buf) == 0 &&
00102 S_ISLNK(lstat_buf.st_mode)) {
00103
00104 } else {
00105 fprintf(stderr, "stat failed for %s (%s)\n",
00106 name, strerror(err));
00107 }
00108 free(name);
00109 name = NULL;
00110 }
00111 return name;
00112 }
00113
00114
00115 int get_matching_pathnames(void * name_list, get_pathname_callback getpathname,
00116 char const * base_dir, char const * filter,
00117 enum recursion_type recursion)
00118 {
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 #define NO_MATCH 0
00131 #define MATCH 1
00132
00133 DIR * dir;
00134 struct dirent * ent;
00135 struct stat stat_buffer;
00136 int match;
00137 char * name = NULL;
00138
00139 if (!(dir = opendir(base_dir)))
00140 return -1;
00141 while ((ent = readdir(dir)) != 0) {
00142 if (is_dot_or_dotdot(ent->d_name))
00143 continue;
00144 if (fnmatch(filter, ent->d_name, 0) == 0)
00145 match = 1;
00146 else
00147 match = 0;
00148
00149 switch (recursion | match) {
00150 case NO_RECURSION + NO_MATCH:
00151 case MATCH_ANY_ENTRY_RECURSION + NO_MATCH:
00152
00153 break;
00154 case NO_RECURSION + MATCH:
00155 getpathname(ent->d_name, name_list);
00156 break;
00157 case MATCH_ANY_ENTRY_RECURSION + MATCH:
00158 name = make_pathname_from_dirent(base_dir, ent,
00159 &stat_buffer);
00160 if (name) {
00161 if (S_ISDIR(stat_buffer.st_mode)) {
00162 get_matching_pathnames(
00163 name_list, getpathname,
00164 name, filter, recursion);
00165 } else {
00166 getpathname(name, name_list);
00167 }
00168 }
00169 free(name);
00170 break;
00171 case MATCH_DIR_ONLY_RECURSION + NO_MATCH:
00172 case MATCH_DIR_ONLY_RECURSION + MATCH:
00173 name = make_pathname_from_dirent(base_dir, ent,
00174 &stat_buffer);
00175 if (name && S_ISDIR(stat_buffer.st_mode)) {
00176
00177
00178
00179
00180 if (!fnmatch(filter, name, 0)) {
00181 getpathname(name, name_list);
00182 } else {
00183 get_matching_pathnames(
00184 name_list, getpathname,
00185 name, filter, recursion);
00186 }
00187 }
00188 free(name);
00189 break;
00190 }
00191 }
00192 closedir(dir);
00193
00194 return 0;
00195 }