179 lines
4.4 KiB
C++
179 lines
4.4 KiB
C++
////////////////////////////////////////////////////////////////////////
|
|
// FILE: fileutils.cpp
|
|
// AUTHOR: Johannes Winkelmann, jw@tks6.net
|
|
// COPYRIGHT: (c) 2002-2005 by Johannes Winkelmann
|
|
// ---------------------------------------------------------------------
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
#include <iostream>
|
|
#include <cstring>
|
|
#include <algorithm>
|
|
|
|
#include "md5.h"
|
|
#include "httpup.h"
|
|
#include "fileutils.h"
|
|
|
|
using namespace std;
|
|
|
|
int FileUtils::deltree(const char* directory)
|
|
{
|
|
int ret = 0;
|
|
|
|
struct stat info;
|
|
if (stat(directory, &info)) {
|
|
// already removed
|
|
return 0;
|
|
}
|
|
if (!S_ISDIR(info.st_mode)) {
|
|
return unlink(directory);
|
|
}
|
|
|
|
DIR* dir = opendir(directory);
|
|
struct dirent* entry;
|
|
while ((entry = readdir(dir)) != 0) {
|
|
if (entry->d_name[0] == '.' &&
|
|
(entry->d_name[1] == '.' || entry->d_name[1] == '\0')) {
|
|
continue;
|
|
}
|
|
struct stat info;
|
|
string pathName = string(directory) + "/" + string(entry->d_name);
|
|
if (stat(pathName.c_str(), &info) != 0) {
|
|
cout << entry->d_name << endl;
|
|
return -1;
|
|
}
|
|
if (S_ISDIR(info.st_mode)) {
|
|
if (deltree(pathName.c_str())) {
|
|
ret = -1;
|
|
}
|
|
rmdir(pathName.c_str());
|
|
} else {
|
|
if (unlink(pathName.c_str())) {
|
|
ret = -1;
|
|
}
|
|
}
|
|
}
|
|
closedir(dir);
|
|
if (rmdir(directory)) {
|
|
ret = -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int FileUtils::mktree(const string& directory)
|
|
{
|
|
int ret = 0;
|
|
size_t pos = 0;
|
|
string fName;
|
|
while ((pos = directory.find( '/', pos+1)) != string::npos ) {
|
|
fName = directory.substr(0, pos);
|
|
struct stat info;
|
|
if (stat(fName.c_str(), &info)) {
|
|
if (mkdir(fName.c_str(), 0755)) {
|
|
ret = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
bool FileUtils::fmd5sum(const string& fileName, unsigned char* result)
|
|
{
|
|
struct md5_context ctx;
|
|
unsigned char buffer[1000];
|
|
|
|
FILE* f = fopen(fileName.c_str(), "r");
|
|
if (!f) {
|
|
return false;
|
|
}
|
|
md5_starts( &ctx );
|
|
int i = 0;
|
|
while( ( i = fread( buffer, 1, sizeof( buffer ), f ) ) > 0 ) {
|
|
md5_update( &ctx, buffer, i );
|
|
}
|
|
fclose(f);
|
|
|
|
md5_finish( &ctx, result );
|
|
return true;
|
|
}
|
|
|
|
void FileUtils::listFiles(const string& target)
|
|
{
|
|
list<string> files;
|
|
string newTarget = target;
|
|
|
|
if (newTarget != ".") {
|
|
if (newTarget[newTarget.length()-1] != '/') {
|
|
newTarget += "/";
|
|
}
|
|
}
|
|
|
|
string repoFile = newTarget + "/" + HttpUp::REPOCURRENTFILE;
|
|
FILE* fp = fopen(repoFile.c_str(), "r");
|
|
if (fp) {
|
|
char line[512];
|
|
while (fgets(line, 512, fp)) {
|
|
line[strlen(line)-1] = '\0';
|
|
files.push_back(line);
|
|
}
|
|
fclose(fp);
|
|
|
|
listFilesRec(newTarget, "", files);
|
|
} else {
|
|
cerr << "Failed to open " << repoFile << endl;
|
|
}
|
|
}
|
|
|
|
void FileUtils::listFilesRec(const string& base,
|
|
const string& offset,
|
|
list<string>& files)
|
|
{
|
|
string newOff = offset;
|
|
if (newOff.length() > 0) {
|
|
newOff += "/";
|
|
}
|
|
|
|
DIR* dir = opendir((base + newOff).c_str());
|
|
if (dir) {
|
|
struct dirent* d;
|
|
string name;
|
|
while ((d = readdir(dir))) {
|
|
|
|
name = d->d_name;
|
|
if (name == HttpUp::REPOCURRENTFILE ||
|
|
name == HttpUp::URLINFO ||
|
|
name == "." || name == "..") {
|
|
continue;
|
|
}
|
|
|
|
if (find(files.begin(), files.end(),
|
|
newOff + d->d_name) == files.end()) {
|
|
cout << "? ";
|
|
} else {
|
|
cout << "= ";
|
|
}
|
|
cout << newOff
|
|
<< d->d_name << endl;
|
|
|
|
struct stat buf;
|
|
if (stat(((base + newOff) + d->d_name).c_str(), &buf) == 0 &&
|
|
S_ISDIR(buf.st_mode)) {
|
|
listFilesRec(base, newOff + d->d_name, files);
|
|
}
|
|
}
|
|
|
|
closedir(dir);
|
|
}
|
|
}
|
|
|