1: /******************************************************************************
2: ezht - Copyright (C) 2004 Tradcrafts
3: This file is part of the ezht.
4:
5: ezht is free software; you can redistribute it and/or modify
6: it under the terms of the GNU General Public License as published by the
7: Free Software Foundation; either version 2 of the License, or (at your
8: option) any later version.
9:
10: ezht is distributed in the hope that it will be useful, but
11: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13: more details.
14:
15: You should have received a copy of the GNU General Public License along with
16: this program; see the file COPYING. If not, write to the Free Software
17: Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18: ******************************************************************************/
19:
20: #include <unistd.h>
21: #include <string.h>
22: #include <ctype.h>
23: #include <list>
24: #include <string>
25:
26:
27: /* 最初に指定文字('?'を含んでよい)の現れるポインタ
28: (見つからなければNULL)を返す。*/
29: static const char * StrChr(const char *s,int c)
30: {
31: if(c=='?')
32: return (*s)!='\0' ? s : 0;
33: return strchr(s,c);
34: }
35:
36: /* 文字列 d がワイルドカードを含む文字列 s に一致すれば真を返す */
37: static int WildMatch(const char *d,const char *s)
38: {
39:
40: for(;*s!='\0';s++)
41: switch(*s){
42: case '*':
43: while(*(++s)=='*')
44: ;
45: if(*s=='\0')
46: return 1; //matches
47: d=StrChr(d,*s);
48: if( !d )
49: return 0;//unmatched
50: do{
51: if(WildMatch(d,s))
52: return 1;
53: }while(NULL!=(d=StrChr(d+1,*s)));
54: return 0;
55: case '?':
56: if( *d++ == '\0' )
57: return 0;
58: break;
59: default:
60: if( *s != *d++ )
61: return 0;
62: break;
63: }
64: return *d=='\0';
65: }
66:
67: #include <string.h>
68: #include <dirent.h>
69: #include <sys/stat.h>
70:
71: struct listdirstruc
72: {
73: bool isdir;
74: bool iswild;
75: std::string name;
76: };
77:
78: static int __listdir(const char *dirnam, std::list<listdirstruc> patlist,
79: int ind,std::list<std::string> &list);
80:
81: static inline bool ischild(const char *fname)
82: {
83: if( strcmp(fname,".")==0 || strcmp(fname,"..")==0 )
84: return false;
85: else
86: return true;
87: }
88:
89: #define TEMPBUF_SIZE 2048
90: static char tempbuf[TEMPBUF_SIZE];
91:
92: int ezht_glob(const char *pattern,std::list<std::string> &results)
93: {
94: std::list<listdirstruc> patlist;
95: listdirstruc *p;
96: int i,j,len;
97: bool iswild;
98: char c;
99:
100: len = strlen(pattern);
101:
102: if(len==0)
103: return 0;
104:
105:
106: if( pattern[0]=='/' ){
107: listdirstruc s;
108: s.name = "/";
109: s.iswild = false;
110: s.isdir = true;
111: patlist.push_back(s);
112: i=1;
113: }
114: else
115: i=0;
116:
117: for( ; i<len ;i++){
118: iswild = false;
119: j = i;
120: while( (c=pattern[i])!='/' && c!='\0'){
121: if( c=='*' || c=='?' )
122: iswild = true;
123: i++;
124: }
125: if(j!=i){
126: listdirstruc s;
127: s.iswild = iswild;
128: s.isdir = true;
129: strncpy(tempbuf,pattern+j,i-j);
130: tempbuf[i-j]='\0';
131: s.name = tempbuf;
132: patlist.push_back(s);
133: }
134: }
135:
136: std::list<listdirstruc>::iterator term=patlist.end();
137: --term;
138: for(std::list<listdirstruc>::iterator cur=patlist.begin(); cur!=term;){
139: std::list<listdirstruc>::iterator next = cur;
140: ++next;
141: if( ! (*cur).iswild && ! (*next).iswild ){
142: if( (*cur).name == "/" )
143: (*cur).name += (*next).name;
144: else
145: (*cur).name += "/" + (*next).name;
146: if( next == term )
147: break;
148: patlist.erase(next);
149: }
150: else
151: cur++;
152: }
153:
154: (*patlist.rbegin()).isdir = false;
155:
156: DIR *dirp;
157: struct dirent *ent;
158:
159: int nmatched = 0;
160: p = & (*patlist.begin());
161:
162:
163: if( p->isdir ){
164: if( p->iswild ){
165: getcwd(tempbuf,TEMPBUF_SIZE);
166: dirp = opendir(tempbuf);
167: if( dirp ){
168: while( (ent=readdir(dirp)) != NULL )
169: if( ischild(ent->d_name) && WildMatch(ent->d_name,p->name.c_str()) )
170: nmatched += __listdir(ent->d_name,patlist,1,results);
171: closedir(dirp);
172: }
173: }
174: else
175: nmatched = __listdir(p->name.c_str(),patlist,1,results);
176: }
177: else{
178: if( p->iswild ){
179: getcwd(tempbuf,TEMPBUF_SIZE);
180: dirp = opendir(tempbuf);
181: if( dirp ){
182: while( (ent=readdir(dirp))!=NULL )
183: if( ischild(ent->d_name) && WildMatch(ent->d_name,p->name.c_str()) ){
184: results.push_back(ent->d_name);
185: nmatched ++;
186: }
187: closedir(dirp);
188: }
189: }
190: else{
191: if( access(p->name.c_str(),F_OK) == 0 ){
192: results.push_back(p->name);
193: nmatched = 1;
194: }
195: }
196: }
197:
198: results.sort(); // 昇順にソート
199:
200: return nmatched;
201: }
202:
203:
204: static int __listdir(const char *dirnam, std::list<listdirstruc> patlist, int ind,
205: std::list<std::string> &results)
206: {
207: std::string Name = dirnam;
208: DIR *dirp;
209: struct dirent *ent;
210: listdirstruc *p;
211: int nmatched = 0;
212:
213:
214: std::list<listdirstruc>::iterator itr=patlist.begin();
215: for(int i=0; i<ind; i++)
216: itr++;
217:
218: p = &(*itr);
219:
220: if( Name!="/" )
221: Name = Name + "/";
222:
223: if( p->isdir ){
224: dirp = opendir(dirnam);
225: if( dirp ){
226: if( p->iswild ){
227: while( (ent=readdir(dirp))!=NULL )
228: if( ischild(ent->d_name) && WildMatch(ent->d_name,p->name.c_str()) )
229: nmatched += __listdir( (Name+ent->d_name).c_str() ,
230: patlist , ind+1 ,results);
231: closedir(dirp);
232: }
233: else{
234: closedir(dirp);
235: nmatched = __listdir( (Name+p->name).c_str() , patlist , ind+1 ,results);
236: }
237: }
238: }
239: else{
240: if( p->iswild ){
241: dirp = opendir(dirnam);
242: if(dirp){
243: while( (ent=readdir(dirp))!=NULL )
244: if( ischild(ent->d_name) && WildMatch(ent->d_name,p->name.c_str()) ){
245: std::string path = Name;
246: path += ent->d_name;
247: results.push_back(path);
248: nmatched++;
249: }
250: closedir(dirp);
251: }
252: }
253: else{
254: std::string path = Name;
255: path += p->name;
256: if( access(path.c_str(),F_OK)==0 ){
257: results.push_back(path);
258: nmatched=1;
259: }
260: }
261: }
262:
263: return nmatched;
264: }
265: