Updating ChangeLog for 4.22.10
[centerim.git] / kksystr / src / kkfsys.cc
blob8fd3c8ca1dae3857ec4c9ec321726fc9c61cb4bd
1 /*
3 * kkfsys file system related routines
4 * $Id: kkfsys.cc,v 1.7 2002/07/03 14:38:58 konst Exp $
6 * Copyright (C) 1999-2001 by Konstantin Klyagin <k@thekonst.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
25 #include "kkfsys.h"
27 unsigned long kfilesize(char *fname) {
28 struct stat buf;
29 if(!stat(fname, &buf)) return buf.st_size; else return 0;
32 void freads(FILE *f, char *s, int maxlen) {
33 s[0] = 0;
34 fgets(s, maxlen, f);
36 for(int i = strlen(s)-1; ; i--)
37 if(i >= 0 && strchr("\r\n", s[i])) s[i] = 0; else break;
40 int fcopy(const char *source, const char *dest) {
41 FILE *inpf, *outf;
42 int ret = -1, bc;
43 char buf[8192];
45 if(inpf = fopen(source, "r")) {
46 if(outf = fopen(dest, "w")) {
47 ret = bc = 0;
49 while((bc = fread(buf, 1, 8192, inpf))) {
50 fwrite(buf, bc, 1, outf);
51 ret += bc;
52 if(bc < 8192) break;
55 fclose(inpf);
58 fclose(outf);
61 return ret;
64 int fmove(const char *source, const char *dest) {
65 int ret = fcopy(source, dest);
66 if(ret != -1) unlink(source);
67 return ret;
70 void stepftw(const char *fname, int *stopwalk, int (*fn)(const char *file, const struct stat *sb, int flag)) {
71 struct stat st;
72 int flag;
74 flag = FTW_F;
76 if(lstat(fname, &st)) {
77 #ifdef FTW_NS
78 flag = FTW_NS;
79 #endif
80 } else {
81 if(S_ISLNK(st.st_mode)) {
82 #ifdef FTW_SL
83 flag = FTW_SL;
84 #endif
85 } else
86 if(S_ISREG(st.st_mode)) flag = FTW_F; else
87 if(S_ISDIR(st.st_mode)) {
88 flag = FTW_D;
89 #ifdef FTW_DNR
90 if(access(fname, R_OK)) flag = FTW_DNR;
91 #endif
95 if(fn) {
96 if((*fn)(fname, &st, flag)) {
97 *stopwalk = 1;
98 } else if(flag == FTW_D) {
99 if(stubnftw(fname, fn, 0, 1)) *stopwalk = 1;
104 int stubnftw(const char *dir, int (*fn)(const char *file, const struct stat *sb, int flag), int depth, int flags) {
105 DIR *dr;
106 struct dirent *ent;
107 char *fname;
108 int stopwalk = 0;
110 if(!flags) {
111 stepftw(dir, &stopwalk, fn);
112 } else if(dr = opendir(dir)) {
113 while((ent = readdir(dr)) && !stopwalk) {
114 if( !strcmp(ent->d_name, ".") ||
115 !strcmp(ent->d_name, "..")) continue;
117 fname = (char *) malloc(strlen(dir) + strlen(ent->d_name) + 2);
118 strcpy(fname, dir);
119 if(fname[strlen(fname)] != '/') strcat(fname, "/");
120 strcat(fname, ent->d_name);
122 stepftw(fname, &stopwalk, fn);
123 free(fname);
126 closedir(dr);
129 return stopwalk;
132 string pathfind(const string &name, const string &path, int amode) {
133 string token, current, buf = path;
135 while(!(token = getword(buf, ":")).empty()) {
136 current = token + "/" + name;
137 if(!access(current.c_str(), amode)) return current;
140 return "";
143 bool mksubdirs(string dir) {
144 string subname, created;
145 bool errhappen = false;
147 if(!dir.empty())
148 if(dir[0] == '/') created = "/";
150 while(!dir.empty() && !errhappen) {
151 subname = getword(dir, "/");
153 if(!created.empty())
154 if(*(created.end()-1) != '/') created += "/";
156 created += subname;
158 if(access(created.c_str(), F_OK))
159 errhappen = mkdir(created.c_str(), S_IRWXU);
162 return !errhappen;
165 string readlink(const string &fname) {
166 char rfname[1024];
167 int n;
169 if((n = ::readlink(fname.c_str(), rfname, 1024)) != -1) {
170 rfname[n] = 0;
171 return rfname;
172 } else {
173 return "";
177 bool samefile(const string &fname1, const string &fname2) {
178 bool r;
179 struct stat st1, st2;
181 if(r = !stat(fname1.c_str(), &st1) && !stat(fname2.c_str(), &st2)) {
182 r = st1.st_ino == st2.st_ino;
183 } else {
184 r = fname1 == fname2;
187 return r;
190 #define FINDFILE_PUSH(m) \
191 if((mode & m) && !regexec(&r, fname.c_str(), 0, 0, 0)) \
192 lst.push_back(fname);
194 vector<string> filefind(const string &mask, const string &aroot, int mode) {
195 vector<string> lst, rlst;
196 vector<string>::iterator is;
197 regex_t r;
198 DIR *d;
199 string fname, root;
200 struct dirent *de;
201 struct stat st;
203 root = aroot;
204 if(root.substr(root.size()-1) != "/") root += "/";
206 if(!regcomp(&r, mask.c_str(), REG_EXTENDED)) {
207 if(d = opendir(root.c_str())) {
208 while(de = readdir(d)) {
209 fname = de->d_name;
210 if((fname != ".") && (fname != "..")) {
211 fname = root + fname;
213 if(!stat(fname.c_str(), &st)) {
214 if(S_ISREG(st.st_mode)) {
215 FINDFILE_PUSH(FFIND_FILE);
216 } else if(S_ISDIR(st.st_mode)) {
217 FINDFILE_PUSH(FFIND_DIR);
218 rlst = filefind(mask, fname, mode);
219 for(is = rlst.begin(); is != rlst.end(); is++) {
220 lst.push_back(*is);
222 } else if(S_ISLNK(st.st_mode)) {
223 FINDFILE_PUSH(FFIND_LINK);
229 closedir(d);
232 regfree(&r);
235 return lst;