"Fossies" - the Fresh Open Source Software Archive 
Member "qdiff-0.9.1/tfiletools.cc" (21 Oct 2008, 7344 Bytes) of package /linux/privat/old/qdiff-0.9.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*GPL*START*
2 *
3 * tfilesync.h - file and directory handling tolls header file
4 *
5 * Copyright (C) 2000 by Johannes Overmann <Johannes.Overmann@gmx.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * *GPL*END*/
21
22 #include <sys/types.h>
23 #include <dirent.h>
24 #include "tfiletools.h"
25
26 #define COUNT_VERBOSE_STEP 1000
27
28 // TFile implementation
29
30 TFile::FileType TFile::filetype() const {
31 if(isregular()) return FT_REGULAR;
32 else if(isdir()) return FT_DIR;
33 else if(issymlink()) return FT_SYMLINK;
34 else if(ischardev()) return FT_CHARDEV;
35 else if(isblockdev()) return FT_BLOCKDEV;
36 else if(isfifo()) return FT_FIFO;
37 else if(issocket()) return FT_SOCKET;
38 else return FT_UNKNOWN;
39 }
40
41 tstring TFile::filetypeLongStr() const {
42 switch(filetype()) {
43 case FT_SOCKET: return "socket";
44 case FT_SYMLINK: return "symbolic link";
45 case FT_REGULAR: return "regular file";
46 case FT_BLOCKDEV: return "block device";
47 case FT_DIR: return "directory";
48 case FT_CHARDEV: return "character device";
49 case FT_FIFO: return "fifo";
50 default: { tstring t; t.sprintf("%#o", int(filetypebits())); return t; }
51 }
52 }
53
54 char TFile::filetypeChar() const {
55 switch(filetype()) {
56 case FT_SOCKET: return 's';
57 case FT_SYMLINK: return 'l';
58 case FT_REGULAR: return '-';
59 case FT_BLOCKDEV: return 'b';
60 case FT_DIR: return 'd';
61 case FT_CHARDEV: return 'c';
62 case FT_FIFO: return 'p';
63 default: return '?';
64 }
65 }
66
67 tstring TFile::filetypeStr7() const {
68 switch(filetype()) {
69 case FT_SOCKET: return "socket ";
70 case FT_SYMLINK: return "symlink";
71 case FT_REGULAR: return "regular";
72 case FT_BLOCKDEV: return "blockdv";
73 case FT_DIR: return "dir ";
74 case FT_CHARDEV: return "chardev";
75 case FT_FIFO: return "fifo ";
76 default: return "unknown";
77 }
78 }
79
80 void TFile::getstat() const {
81 if(stated) return;
82 if(name_.empty()) throw TNotInitializedException("TFile");
83 TFile *t = const_cast<TFile*>(this);
84 #ifndef __STRICT_ANSI__
85 if(follow_links) {
86 #endif
87 if(stat(name_.c_str(), &(t->statbuf))) throw TFileOperationErrnoException(name_.c_str(), "stat");
88 #ifndef __STRICT_ANSI__
89 } else {
90 if(lstat(name_.c_str(), &(t->statbuf))) throw TFileOperationErrnoException(name_.c_str(), "lstat");
91 }
92 #endif
93 t->stated = true;
94 num_stated++;
95 }
96
97
98
99 // TDir implementation
100
101 size_t TDir::numRecursive(bool low_mem, const char *verbose, bool count_files, bool count_dirs) const {
102 size_t r = 0;
103 if(count_files) r = numFiles();
104 if(count_dirs) r += numDirs();
105 if(verbose) {
106 verbose_num += r;
107 if(verbose_num > (old_verbose_num + COUNT_VERBOSE_STEP)) {
108 printf("counting %s in %s: %11u\r", count_files ? (count_dirs ? "files and dirs" : "files") : (count_dirs ? "dirs" : "nothing"), verbose, unsigned(verbose_num));
109 fflush(stdout);
110 old_verbose_num = verbose_num;
111 }
112 }
113 for(size_t i = 0; i < numDirs(); i++)
114 r += dir(i).numRecursive(low_mem, verbose, count_files, count_dirs);
115 if(low_mem) freeMem();
116 return r;
117 }
118
119 void TDir::scan() const {
120 if(scanned) return;
121 assert(subTreeContext);
122 if(name().empty()) throw TNotInitializedException("TDir");
123 TDir *t = const_cast<TDir*>(this);
124 // maximum depth already reached? if so treat directory as empty
125 if(depth >= subTreeContext->max_depth)
126 {
127 t->scanned = true;
128 return;
129 }
130 // prevent crossing filesystems?
131 if(!subTreeContext->cross_filesystems) {
132 if(subTreeContext->root->device() != device()) {
133 // consider directory empty because it is on a different filesystem than the subtree root
134 t->scanned = true;
135 return;
136 }
137 }
138 // scan directory
139 struct dirent *dire = 0;
140 DIR *tdir = opendir(name().c_str());
141 if(tdir == 0) throw TFileOperationErrnoException(name().c_str(), "opendir");
142 size_t dirs_left = hardlinks() - 2;
143 while((dire = readdir(tdir)) != 0) {
144 if((dire->d_name[0] != '.') || (strcmp(".", dire->d_name) && strcmp("..", dire->d_name))) {
145 TFile f((name() + "/") + dire->d_name);
146 if((dirs_left || no_leaf_optimize) && f.isdir()) {
147 t->name2dirid[dire->d_name] = dirs.size();
148 t->dirs[dirs.size()] = TDir(f, *subTreeContext, depth + 1);
149 dirs_left--;
150 } else {
151 t->name2fileid[dire->d_name] = files.size();
152 t->files[files.size()] = f;
153 }
154 }
155 }
156 closedir(tdir);
157 t->scanned = true;
158 // update access time
159 invalidateStat();
160 }
161
162 size_t TDir::verbose_num = 0;
163 size_t TDir::old_verbose_num = 0;
164 bool TFile::follow_links = false;
165 size_t TFile::num_stated = 0;
166 #ifdef WIN32
167 bool TDir::no_leaf_optimize = true;
168 #else
169 bool TDir::no_leaf_optimize = false;
170 #endif
171
172
173 // global functions
174 tvector<tstring> findFilesRecursive(const TDir& dir) {
175 // return value
176 tvector<tstring> r;
177
178 // add files
179 for(size_t i = 0; i < dir.numFiles(); i++)
180 r.push_back(dir.file(i).name());
181
182 // add dirs recursively
183 for(size_t j = 0; j < dir.numDirs(); j++)
184 r += findFilesRecursive(dir.dir(j));
185
186 // return list
187 return r;
188 }
189
190
191 tvector<tstring> filterExtensions(const tvector<tstring>& list, const tvector<tstring>& extensions, bool remove) {
192 // create lookup map
193 tmap<tstring,int> ext;
194 for(size_t i = 0; i < extensions.size(); i++)
195 ext[extensions[i]] = 1;
196
197 // filter list
198 tvector<tstring> r;
199 for(size_t j = 0; j < list.size(); j++) {
200 tstring e = list[j];
201 e.extractFilenameExtension();
202 if(ext.contains(e) != remove)
203 r.push_back(list[j]);
204 }
205
206 // return list
207 return r;
208 }
209
210
211 void makeDirectoriesIncludingParentsIfNecessary(const tstring& dirname, bool verbose, bool dummy) {
212 // check whether dirname already exists
213 try {
214 TFile f(dirname);
215 // if it exists and is a directory we are done
216 if(f.isdir()) return;
217 }
218 // else we need to create the parent directory and then dirname
219 catch(const TFileOperationErrnoException& e) {
220 if(e.err == ENOENT) {
221 // create parent dir
222 tstring parent = dirname;
223 parent.removeDirSlash();
224 parent.extractPath();
225 if(!parent.empty())
226 makeDirectoriesIncludingParentsIfNecessary(parent, verbose, dummy); // recurse
227
228 // create dirname
229 if(verbose)
230 printf("creating directory '%s'\n", dirname.c_str());
231 if(!dummy)
232 if(mkdir(dirname.c_str(), S_IRWXU) == -1)
233 throw TFileOperationErrnoException(dirname.c_str(), "mkdir");
234 return;
235 } else throw;
236 }
237
238 // if we get here dirname exists and is not a directory: error
239 throw TFileOperationErrnoException(dirname.c_str(), "makeDirectoriesIncludingParentsIfNecessary", ENOTDIR);
240 }
241