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
27 unsigned long kfilesize(char *fname
) {
29 if(!stat(fname
, &buf
)) return buf
.st_size
; else return 0;
32 void freads(FILE *f
, char *s
, int maxlen
) {
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
) {
45 if(inpf
= fopen(source
, "r")) {
46 if(outf
= fopen(dest
, "w")) {
49 while((bc
= fread(buf
, 1, 8192, inpf
))) {
50 fwrite(buf
, bc
, 1, outf
);
64 int fmove(const char *source
, const char *dest
) {
65 int ret
= fcopy(source
, dest
);
66 if(ret
!= -1) unlink(source
);
70 void stepftw(const char *fname
, int *stopwalk
, int (*fn
)(const char *file
, const struct stat
*sb
, int flag
)) {
76 if(lstat(fname
, &st
)) {
81 if(S_ISLNK(st
.st_mode
)) {
86 if(S_ISREG(st
.st_mode
)) flag
= FTW_F
; else
87 if(S_ISDIR(st
.st_mode
)) {
90 if(access(fname
, R_OK
)) flag
= FTW_DNR
;
96 if((*fn
)(fname
, &st
, flag
)) {
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
) {
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);
119 if(fname
[strlen(fname
)] != '/') strcat(fname
, "/");
120 strcat(fname
, ent
->d_name
);
122 stepftw(fname
, &stopwalk
, fn
);
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
;
143 bool mksubdirs(string dir
) {
144 string subname
, created
;
145 bool errhappen
= false;
148 if(dir
[0] == '/') created
= "/";
150 while(!dir
.empty() && !errhappen
) {
151 subname
= getword(dir
, "/");
154 if(*(created
.end()-1) != '/') created
+= "/";
158 if(access(created
.c_str(), F_OK
))
159 errhappen
= mkdir(created
.c_str(), S_IRWXU
);
165 string
readlink(const string
&fname
) {
169 if((n
= ::readlink(fname
.c_str(), rfname
, 1024)) != -1) {
177 bool samefile(const string
&fname1
, const string
&fname2
) {
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
;
184 r
= fname1
== fname2
;
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
;
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
)) {
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
++) {
222 } else if(S_ISLNK(st
.st_mode
)) {
223 FINDFILE_PUSH(FFIND_LINK
);