"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.
For more information about "tfiletools.cc" see the
Fossies "Dox" file reference documentation.
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