1 ////////////////////////////////////////////////////////////////////////
2 // FILE: fileutils.cpp
3 // AUTHOR: Johannes Winkelmann, jw@tks6.net
4 // COPYRIGHT: (c) 2002-2005 by Johannes Winkelmann
5 // ---------------------------------------------------------------------
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 ////////////////////////////////////////////////////////////////////////
11
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
15 #include <dirent.h>
16 #include <iostream>
17
18 #include "md5.h"
19 #include "httpup.h"
20 #include "fileutils.h"
21
22 using namespace std;
23
24 int FileUtils::deltree(const char* directory)
25 {
26 int ret = 0;
27
28 struct stat info;
29 if (stat(directory, &info)) {
30 // already removed
31 return 0;
32 }
33 if (!S_ISDIR(info.st_mode)) {
34 return unlink(directory);
35 }
36
37 DIR* dir = opendir(directory);
38 struct dirent* entry;
39 while ((entry = readdir(dir)) != 0) {
40 if (entry->d_name[0] == '.' &&
41 (entry->d_name[1] == '.' || entry->d_name[1] == '\0')) {
42 continue;
43 }
44 struct stat info;
45 string pathName = string(directory) + "/" + string(entry->d_name);
46 if (stat(pathName.c_str(), &info) != 0) {
47 cout << entry->d_name << endl;
48 return -1;
49 }
50 if (S_ISDIR(info.st_mode)) {
51 if (deltree(pathName.c_str())) {
52 ret = -1;
53 }
54 rmdir(pathName.c_str());
55 } else {
56 if (unlink(pathName.c_str())) {
57 ret = -1;
58 }
59 }
60 }
61 closedir(dir);
62 if (rmdir(directory)) {
63 ret = -1;
64 }
65
66 return ret;
67 }
68
69 int FileUtils::mktree(const string& directory)
70 {
71 int ret = 0;
72 size_t pos = 0;
73 string fName;
74 while ((pos = directory.find( '/', pos+1)) != string::npos ) {
75 fName = directory.substr(0, pos);
76 struct stat info;
77 if (stat(fName.c_str(), &info)) {
78 if (mkdir(fName.c_str(), 0755)) {
79 ret = -1;
80 }
81 }
82 }
83
84 return ret;
85 }
86
87
88 bool FileUtils::fmd5sum(const string& fileName, unsigned char* result)
89 {
90 struct md5_context ctx;
91 unsigned char buffer[1000];
92
93 FILE* f = fopen(fileName.c_str(), "r");
94 if (!f) {
95 return false;
96 }
97 md5_starts( &ctx );
98 int i = 0;
99 while( ( i = fread( buffer, 1, sizeof( buffer ), f ) ) > 0 ) {
100 md5_update( &ctx, buffer, i );
101 }
102 fclose(f);
103
104 md5_finish( &ctx, result );
105 return true;
106 }
107
108 void FileUtils::listFiles(const string& target)
109 {
110 list<string> files;
111 string newTarget = target;
112
113 if (newTarget != ".") {
114 if (newTarget[newTarget.length()-1] != '/') {
115 newTarget += "/";
116 }
117 }
118
119 string repoFile = newTarget + "/" + HttpUp::REPOCURRENTFILE;
120 FILE* fp = fopen(repoFile.c_str(), "r");
121 if (fp) {
122 char line[512];
123 while (fgets(line, 512, fp)) {
124 line[strlen(line)-1] = '\0';
125 files.push_back(line);
126 }
127 fclose(fp);
128
129 listFilesRec(newTarget, "", files);
130 } else {
131 cerr << "Failed to open " << repoFile << endl;
132 }
133 }
134
135 void FileUtils::listFilesRec(const string& base,
136 const string& offset,
137 list<string>& files)
138 {
139 string newOff = offset;
140 if (newOff.length() > 0) {
141 newOff += "/";
142 }
143
144 DIR* dir = opendir((base + newOff).c_str());
145 if (dir) {
146 struct dirent* d;
147 string name;
148 while ((d = readdir(dir))) {
149
150 name = d->d_name;
151 if (name == HttpUp::REPOCURRENTFILE ||
152 name == HttpUp::URLINFO ||
153 name == "." || name == "..") {
154 continue;
155 }
156
157 if (find(files.begin(), files.end(),
158 newOff + d->d_name) == files.end()) {
159 cout << "? ";
160 } else {
161 cout << "= ";
162 }
163 cout << newOff
164 << d->d_name << endl;
165
166 struct stat buf;
167 if (stat(((base + newOff) + d->d_name).c_str(), &buf) == 0 &&
168 S_ISDIR(buf.st_mode)) {
169 listFilesRec(base, newOff + d->d_name, files);
170 }
171 }
172
173 closedir(dir);
174 }
175 }
|