LC_DELETE_1, // 50123
LC_DELETE_SUPERFLUOUS_1, // 50124
LC_SYNC_1, // 50125
+ LC_COPY_FILE_7, // 50126
+ LC_ADAPT_PROPERTIES_1, // 50127
+ LC_ADAPT_PROPERTIES_2, // 50128
};
const char* ReDirTools::m_version = "2015.03.22";
ReLogger* ReDirTools::m_logger = NULL;
rcTime += time(NULL);
}
ReFileTime_t rc;
- ReDirStatus_t::timeToFiletime(rcTime, rc);
+ ReFileUtils::timeToFiletime(rcTime, rc);
return rc;
}
/**
m_pathPatterns.set(buffer.str());
filter.m_pathPatterns = &m_pathPatterns;
}
- if ((m_interval = m_programArgs.getInt("trace") * CLOCKS_PER_SEC) != 0){
+ if ((m_interval = m_programArgs.getInt("trace") * CLOCKS_PER_SEC) != 0) {
m_triggerCount = 10;
}
if (m_programArgs.getString("output", buffer)[0] != '\0') {
int length;
if (buffer.empty())
m_verboseLevel = V_NORMAL;
- else if ( (length = ReStringUtils::lengthOfUnsigned(buffer.str(),
- buffer.length(), &nValue)) == 0 || length != buffer.length())
+ else if ((length = ReStringUtils::lengthOfUnsigned(buffer.str(),
+ buffer.length(), &nValue)) == 0 || length != (int) buffer.length())
help("not a verbose level (0..5): ", buffer.str());
else
m_verboseLevel = VerboseLevel(min(V_DEBUG, nValue));
m_traverser(NULL, this, logger),
m_filter(),
m_start(clock()),
- //m_statInfo(),
m_logger(logger) {
#pragma warning( pop )
}
m_programArgs.init(argc, argv);
if (m_programArgs.argCount() < m_minArguments)
m_programArgs.help(i18n("too few arguments"), false, stdout);
- if (m_hasStandardArgs){
+ if (m_hasStandardArgs) {
checkStandardFilterOptions();
setFilterFromProgramArgs(m_filter);
}
int max = m_programArgs.argCount() - m_reservedLast;
// Test whether the arguments are files or directories:
ReByteArray arg;
+ struct stat info;
for (int ii = m_reservedFirst; ii < max; ii++) {
arg = m_programArgs.arg(ii);
if (!exists(arg) != 0)
m_programArgs.help(
- ReByteArray(i18n("not a file or a directory: ")).append(arg)
- .str(), false, stderr);
+ ReByteArray(i18n("not a file or a directory: ")).append(arg).str(),
+ false, stderr);
}
// process the files:
for (int ii = m_reservedFirst; ii < max; ii++) {
- const char* arg = m_programArgs.arg(ii);
- if (S_ISDIR(m_statInfo.st_mode))
- processTree(arg);
- else
- processSingleFile(arg);
+ ReByteArray arg(m_programArgs.arg(ii));
+ if (exists(arg, &info)) {
+ if (S_ISDIR(info.st_mode))
+ processTree(arg.str());
+ else
+ processSingleFile(arg.str());
+ }
}
}
/**
duration == 0.0 ? 0.0 : (m_files + m_directories) / duration;
line.append(rate, " %.1f").append(i18n("/sec"), -1);
m_traverser.statisticAsString(line2);
- line2.appendChar(' ').appendTime(int(duration * 1000)).append(" ", 1).append(
- i18n("sec"));
+ line2.appendChar(' ').appendTime(int(duration * 1000)).append(" ", 1)
+ .append(i18n("sec"));
fprintf(m_output, "%s=== filtered: %s\n", prefix == NULL ? "" : prefix,
line.str());
fprintf(m_output, "%s=== total: %s\n", prefix == NULL ? "" : prefix,
if (fp == NULL) {
m_logger->sayF(LOG_ERROR | CAT_FILE, LC_BUILD_DIRECTORY_1,
i18n("cannot open file: $1 (errno: $2)")).arg(storageFile).arg(
- errno).end();
+ errno).end();
} else {
int level;
if (fp == NULL) {
if (logger != NULL)
logger->sayF(LOG_ERROR | CAT_FILE, LC_CALCULATE_CHECKSUM_1,
- i18n("cannot open file: $1 (errno: $2)")).arg(name).arg(
- errno).end();
+ i18n("cannot open file: $1 (errno: $2)")).arg(name).arg(errno)
+ .end();
} else {
ReMD5 digest;
size_t readBytes;
if (m_verboseLevel == V_NORMAL) {
if (countTimes == 2)
fprintf(m_output, "%s | %s | %s\n",
- ReDirStatus_t::filetimeToString(&modified, bufferTime),
- ReDirStatus_t::filetimeToString(&accessed, bufferTime2),
+ ReFileUtils::filetimeToString(&modified, bufferTime).str(),
+ ReFileUtils::filetimeToString(&accessed, bufferTime2).str(),
name);
else {
- ReDirStatus_t::filetimeToString(
+ ReFileUtils::filetimeToString(
filetimeIsUndefined(m_modified) ? &accessed : &modified,
bufferTime);
fprintf(m_output, "%s %s\n", bufferTime.str(), name);
ReByteArray bufferTime4;
if (countTimes == 2)
fprintf(m_output, "%s -> %s | %s -> %s | %s\n",
- ReDirStatus_t::filetimeToString(entry->modified(),
- bufferTime),
- ReDirStatus_t::filetimeToString(&modified, bufferTime2),
- ReDirStatus_t::filetimeToString(entry->accessed(),
- bufferTime3),
- ReDirStatus_t::filetimeToString(&accessed, bufferTime4),
+ ReFileUtils::filetimeToString(entry->modified(), bufferTime)
+ .str(),
+ ReFileUtils::filetimeToString(&modified, bufferTime2).str(),
+ ReFileUtils::filetimeToString(entry->accessed(),
+ bufferTime3).str(),
+ ReFileUtils::filetimeToString(&accessed, bufferTime4).str(),
name);
else {
- ReDirStatus_t::filetimeToString(
+ ReFileUtils::filetimeToString(
filetimeIsUndefined(m_modified) ? &m_accessed : &m_modified,
bufferTime);
fprintf(m_output, "%s -> %s %s\n",
- ReDirStatus_t::filetimeToString(entry->modified(),
- bufferTime2), bufferTime.str(), (char*) name);
+ ReFileUtils::filetimeToString(entry->modified(),
+ bufferTime2).str(), bufferTime.str(), (char*) name);
}
}
}
if (rc != 0 && logger != NULL)
logger->sayF(LOG_ERROR | CAT_FILE, LC_TOUCH_1,
i18n("cannot change filetime: $1 (errno: $2)")).arg(filename).arg(
- errno).end();
+ errno).end();
return rc;
}
i18n(
"deletes the files/folders of the target directory not existing in the source directory.\n"
"If a time expression is given only files will be deleted if they are older than this.\n"
- "a time expression is a date, a time, a date/time or a relative time.\n"
- "relative times are a number and a unit.\n"
+ "a time expression is a date, a time, a date/time or a relative time.\n"
+ "relative times are a number and a unit.\n"
"units: m(inutes) h(hours), d(days). Default: m(inutes)\n"
"examples: -E7d --delete=30d -E24h -E2009.3.2/12:00 -E1999.01.01"),
'E', "delete", true, NULL);
m_programArgs.addBool("deletebefore",
- i18n("deletes the superfluous files before copying.\n"
- "This needs fewer space but it is more dangerous:\n"
- "you have no time if the target is wrong: all files will be deleted"), 'B', "delete-before", false);
+ i18n(
+ "deletes the superfluous files before copying.\n"
+ "This needs fewer space but it is more dangerous:\n"
+ "you have no time if the target is wrong: all files will be deleted"),
+ 'B', "delete-before", false);
m_programArgs.addString("editor",
i18n(
"this editor will be started with a file containing a summary message (signals the end)"),
/**
* Copies a file.
*
- * @param entry the source file info
- * @param target the name of the target file
+ * @param dry logs the copy but do nothing (simulating mode)
+ * @param entry the source file info
+ * @param target the name of the target file
+ * @param targetName used for the logging
+ * @param trgProps NULL or the properties of the (existing) target file
*/
-void ReDirSync::copyFile(ReDirStatus_t* entry, const char* target) {
+void ReDirSync::copyFile(bool dry, ReDirStatus_t* entry, const char* target,
+ const char* targetName, ReFileProperties_t* trgProps) {
ReFileProperties_t* props;
#ifdef __linux__
- props = &entry->m_status;
+ props = entry->getStatus();
#else
ReFileProperties_t properties;
properties.m_modified = *entry->modified();
properties.m_size = entry->fileSize();
props = &properties;
#endif
- copyFile(entry->fullName(), props, target, m_buffer,
- ReLogger::globalLogger());
+ if (dry
+ || copyFile(entry->fullName(), entry->isLink(), props, target, m_buffer,
+ ReLogger::globalLogger())) {
+ if (m_verboseLevel >= V_NORMAL) {
+ if (entry->isLink())
+ //@ or use targetRelativePath
+ fprintf(m_output, "%c %s (symbolic link)%s\n",
+ trgProps != NULL ? '!' : '&', targetName,
+ dry ? " would be copied" : "");
+ else
+ fprintf(m_output, "%c%s%s\n", trgProps != NULL ? '!' : '+',
+ targetName, dry ? " would be copied" : "");
+ }
+ adaptProperties(entry->fullName(), props, target, NULL);
+ }
}
+/**
+ * Tries to make the target properties are the same as the source properties.
+ *
+ * @param source the name of the source file/directory
+ * @param srcProps the source properties
+ * @param target the name of the target file/directory
+ * @param trgProps the target properties. If NULL the file is new
+ * and all properties must be set
+ * @param verbose verbose level: determines the output messages
+ * @param prefix the first char of the output line
+ * @param output NULL or the output stream, e.g. stdout
+ * @param logger NULL or the logger for error messages
+ * @return <code>true</code>: success<br>
+ * <code>false</code>: error occurred
+ */
+bool ReDirSync::adaptProperties(const char* source,
+ ReFileProperties_t* srcProps, const char* target,
+ ReFileProperties_t* trgProps, VerboseLevel verbose, char prefix,
+ FILE* output, ReLogger* logger) {
+ bool rc = true;
+#ifdef __linux__
+ ReByteArray changed;
+ if (trgProps == NULL || srcProps->st_uid != trgProps->st_uid
+ || srcProps->st_gid != trgProps->st_gid) {
+ if (chown(target, srcProps->st_uid, srcProps->st_gid) != 0) {
+ rc = false;
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_ADAPT_PROPERTIES_1,
+ i18n("could not change owner/group: $1 (errno: $2)")).arg(
+ target).arg(errno).end();
+ } else if (trgProps != NULL && verbose >= V_NORMAL) {
+ if (verbose >= V_CHATTER) {
+ if (srcProps->st_uid != trgProps->st_uid)
+ changed.append(" UID: ").appendInt(srcProps->st_uid).append(
+ "->").appendInt(trgProps->st_uid);
+ if (srcProps->st_gid != trgProps->st_gid)
+ changed.append(" GID: ").appendInt(srcProps->st_gid).append(
+ "->").appendInt(trgProps->st_gid);
+ } else {
+ if (srcProps->st_uid != trgProps->st_uid)
+ changed.append(" UID");
+ if (srcProps->st_gid != trgProps->st_gid)
+ changed.append(" GID");
+ }
+ }
+ }
+ if (trgProps == NULL
+ || (srcProps->st_mode & ALLPERMS) != (trgProps->st_mode & ALLPERMS)) {
+ int mode = srcProps->st_mode & ALLPERMS;
+ if (chmod(target, mode) != 0 && logger != NULL) {
+ rc = false;
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_ADAPT_PROPERTIES_2,
+ i18n("could not change permissions: $1 (errno: $2)")).arg(
+ target).arg(errno).end();
+
+ } else if (verbose >= V_CHATTER) {
+ changed.append(" rights: ").appendInt(
+ (trgProps->st_mode & ALLPERMS), "%o").append("->").appendInt(
+ mode);
+ } else if (verbose == V_NORMAL) {
+ changed.append(" rights");
+ }
+ }
+ if (trgProps != NULL && verbose >= V_NORMAL && output != NULL) {
+ fprintf(output, "%c%s%s\n", prefix, source, changed.str());
+ }
+#else
+#error "not implemented"
+#endif
+ return rc;
+}
/**
* Copies a file.
*
* @param source the source file name
+ * @param isLink <code>true</code>: the source file is a symbolic link
* @param properties NULL or the properties of the source file
* @param target the name of the target file
* @param buffer OUT: the reading uses this buffer<br>
* @return <code>true</code>success<br>
* <code>false</code>error occurred
*/
-bool ReDirSync::copyFile(const char* source, ReFileProperties_t* properties,
- const char* target, ReByteArray& buffer, ReLogger* logger) {
+bool ReDirSync::copyFile(const char* source, bool isLink,
+ ReFileProperties_t* properties, const char* target, ReByteArray& buffer,
+ ReLogger* logger) {
bool rc = false;
#ifdef __linux__
struct stat info;
if (logger != NULL)
logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_1,
i18n("could not find: $1 (errno: $2)")).arg(source).arg(
- errno).end();
+ errno).end();
}
}
- FILE* fpSource = fopen(source, "rb");
- if (fpSource == NULL) {
- if (logger != NULL)
- logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_2,
- i18n("cannot open $1 (errno: $2)")).arg(source).arg(errno).end();
- } else {
- ReFileSize_t size =
- properties == NULL ? 0x7fffffff : properties->st_size;
- FILE* fpTarget = fopen(target, "w");
- if (fpTarget == NULL) {
+ if (isLink) {
+ char reference[512];
+ int referenceLength = 0;
+ if ((referenceLength = readlink(source, reference, sizeof reference))
+ < 0) {
if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_2,
+ i18n("cannot read link $1 (errno: $2)")).arg(source).arg(
+ errno).end();
+ } else {
+ reference[referenceLength] = '\0';
+ unlink(target);
+ if (symlink(reference, target) != 0 && logger != NULL)
logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_3,
- i18n("cannot open $1 (errno: $2)")).arg(target).arg(errno)
+ i18n("cannot create link $1 [$2] (errno: $3)")).arg(target)
+ .arg(reference).arg(errno).end();
+ }
+ } else {
+ FILE* fpSource = fopen(source, "rb");
+ if (fpSource == NULL) {
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_4,
+ i18n("cannot open $1 (errno: $2)")).arg(source).arg(errno)
.end();
} else {
- while (size > 0) {
- size_t blockSize = buffer.capacity();
- if ((int) blockSize > size)
- blockSize = size;
- if (fread(buffer.buffer(), blockSize, 1, fpSource) != 1) {
- if (logger != NULL)
- logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_5,
- i18n("cannot read $1 (errno: $2)")).arg(source).arg(
- errno).end();
- break;
- }
- size_t written;
- if ((written = fwrite(buffer.buffer(), 1, blockSize, fpTarget))
- != blockSize) {
- if (logger != NULL)
- logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_6,
- i18n("cannot write $1 [$2] (errno: $3)")).arg(
- target).arg(written).arg(errno).end();
- break;
+ ReFileSize_t size =
+ properties == NULL ? 0x7fffffff : properties->st_size;
+ FILE* fpTarget = fopen(target, "w");
+ if (fpTarget == NULL) {
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_5,
+ i18n("cannot open $1 (errno: $2)")).arg(target).arg(
+ errno).end();
+ } else {
+ while (size > 0) {
+ size_t blockSize = buffer.capacity();
+ if ((int) blockSize > size)
+ blockSize = size;
+ if (fread(buffer.buffer(), blockSize, 1, fpSource) != 1) {
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_6,
+ i18n("cannot read $1 (errno: $2)")).arg(source)
+ .arg(errno).end();
+ break;
+ }
+ size_t written;
+ if ((written = fwrite(buffer.buffer(), 1, blockSize,
+ fpTarget)) != blockSize) {
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_COPY_FILE_7,
+ i18n("cannot write $1 [$2] (errno: $3)")).arg(
+ target).arg(written).arg(errno).end();
+ break;
+ }
+ size -= blockSize;
}
- size -= blockSize;
+ rc = size == 0ll;
+ fclose(fpTarget);
+ if (properties != NULL)
+ setProperties(target, properties, logger);
}
- rc = size == 0ll;
- fclose(fpTarget);
- if (properties != NULL)
- setProperties(target, properties, logger);
+ fclose(fpSource);
}
- fclose(fpSource);
}
#elif defined __WIN32__
BOOL cancel = false;
* @param target the target directory
* @param deleteTime UNDEF or a time: only files older than this will be deleted
*/
-void ReDirSync::deleteSuperfluous(const ReByteArray& source, const ReByteArray& target,
- const ReFileTime_t& deleteTime){
+void ReDirSync::deleteSuperfluous(const ReByteArray& source,
+ const ReByteArray& target, const ReFileTime_t& deleteTime) {
ReTraceUnit& tracer = *this;
ReDirectory trg(target.str());
if (trg.findFirst(ReDirectory::ALL_FILES, false)) {
ReByteArray src, trg2;
struct stat info;
- ReFileTime_t modified;
bool ignoreTime = filetimeIsUndefined(deleteTime);
bool dry = m_programArgs.getBool("dry");
do {
- if (strcmp(".", trg.currentNode()) == 0 || strcmp("..", trg.currentNode()) == 0)
+ if (strcmp(".", trg.currentNode()) == 0
+ || strcmp("..", trg.currentNode()) == 0)
continue;
if (tracer.isCountTriggered() && tracer.isTimeTriggered())
tracer.trace(trg.currentFull().str());
src.set(source).append(trg.currentNode());
- if (lstat(src.str(), &info) == 0){
- if (S_ISDIR(info.st_mode)){
+ if (lstat(src.str(), &info) == 0) {
+ if (S_ISDIR(info.st_mode)) {
trg2.set(target).append(trg.currentNode());
deleteSuperfluous(src, trg2, deleteTime);
}
- } else if (ignoreTime || trg.currentModified() >= deleteTime){
- if (trg.currentIsDir()){
- if (! dry)
+ } else if (ignoreTime || trg.currentModified() >= deleteTime) {
+ if (trg.currentIsDir()) {
+ if (!dry)
ReDirectory::deleteTree(trg.currentFull().str(), true);
if (m_verboseLevel >= V_NORMAL)
- fprintf(m_output, "-%s%s\n", trg.currentFull().str(), dry ? " would be deleted (dir)" : "");
+ fprintf(m_output, "-%s%s\n", trg.currentFull().str(),
+ dry ? " would be deleted (dir)" : "");
} else {
if (unlink(trg.currentFull().str()) != 0)
- m_logger->sayF(LOG_ERROR | CAT_FILE, LC_DELETE_SUPERFLUOUS_1,
- i18n("cannot delete file: $1 (errno: $2)")).arg(trg.currentFull()).arg(
- errno).end();
+ m_logger->sayF(LOG_ERROR | CAT_FILE,
+ LC_DELETE_SUPERFLUOUS_1,
+ i18n("cannot delete file: $1 (errno: $2)")).arg(
+ trg.currentFull()).arg(errno).end();
else if (m_verboseLevel >= V_NORMAL)
- fprintf(m_output, "-%s%s\n", trg.currentFull().str(), dry ? " would be deleted" : "");
+ fprintf(m_output, "-%s%s\n", trg.currentFull().str(),
+ dry ? " would be deleted" : "");
}
}
} while (trg.findNext());
return rc;
}
-static void printStatus(FILE* fp, double duration, int files, int sumSizes, int treeDirs,
- int treeFiles, int64_t treeSumSizes){
+static void printStatus(FILE* fp, double duration, int files, int sumSizes,
+ int treeDirs, int treeFiles, int64_t treeSumSizes) {
fprintf(fp,
i18n(
"=== copied: %02d:%02d sec %7d file(s) %12.6f MByte (%.3f MB/sec).\n"
ReByteArray buffer;
ReByteArray target(m_programArgs.arg(m_programArgs.argCount() - 1));
target.removeLastChar(OS_SEPARATOR_CHAR);
- if (!exists(target))
+ struct stat info;
+ if (!exists(target, &info))
help(i18n("target does not exist: "), target.str());
- else if (!S_ISDIR(m_statInfo.st_mode))
+ else if (!S_ISDIR(info.st_mode))
help(i18n("target is not a directory: $1"), target.str());
size_t lengthTargetBase = target.length();
bool addOnly = m_programArgs.getBool("add");
ReFileTime_t deleteDate;
setFiletimeUndef(deleteDate);
bool deleteBefore = m_programArgs.getBool("deletebefore");
- if (m_programArgs.getString("delete", buffer) != NULL){
+ if (m_programArgs.getString("delete", buffer) != NULL) {
deleteTarget = true;
- if (! buffer.empty())
+ if (!buffer.empty())
deleteDate = checkDate(buffer.str());
}
source.reduceLength();
if (!exists(source))
help(i18n("source does not exist: $1"), source.str());
- else if (!S_ISDIR(m_statInfo.st_mode))
+ else if (!S_ISDIR(info.st_mode))
help(i18n("source is not a directory: $1"), source.str());
if (!endsWithSlash) {
// the basename of the source will be appended to the target:
int level;
ReDirStatus_t* entry;
ReByteArray line;
+ struct stat targetInfo;
while ((entry = m_traverser.nextFile(level, &filter)) != NULL) {
if (entry->isDirectory())
continue;
// append the new relative path from source to target:
target.setLength(ixTargetRelative);
target.append(entry->m_path.str() + ixSourceRelative, -1);
- if (!exists(target) && ! dry)
+ if (!exists(target) && !dry)
makeDirWithParents(target, ixTargetRelative, m_traverser);
targetFile.set(target).append(entry->node(), -1);
const char* targetRelativePath = targetFile.str() + ixTargetRelative
+ 1;
- bool targetExists = exists(targetFile);
+ bool targetExists = exists(targetFile, &targetInfo);
if (!targetExists && mustExist) {
if (m_verboseLevel == V_CHATTER)
fprintf(m_output, "-ignored: %s does not exist\n",
targetRelativePath);
continue;
}
- if (ignoreDate && entry->fileSize() == m_statInfo.st_size) {
+ if (ignoreDate && entry->fileSize() == targetInfo.st_size) {
if (m_verboseLevel >= V_CHATTER)
fprintf(m_output, "_ignored: %s same size\n",
targetRelativePath);
}
// target younger than source?
int diff = int(
- m_statInfo.st_mtime
- - entry->filetimeToTime(entry->modified()));
+ targetInfo.st_mtime
+ - ReFileUtils::filetimeToTime(entry->modified()));
if (!ignoreDate && (diff <= maxFileTimeDiff || diff == 3600)) {
if (m_verboseLevel >= V_CHATTER)
fprintf(m_output, "=ignored: %s same time\n",
}
files++;
sumSizes += entry->fileSize();
- if (m_verboseLevel >= V_NORMAL)
- fprintf(m_output, "%c%s%s\n", targetExists ? '!' : '+',
- targetRelativePath, dry ? " would be copied" : "");
- if (!dry)
- copyFile(entry, targetFile.str());
+ copyFile(dry, entry, targetFile.str(), targetRelativePath,
+ &targetInfo);
}
- if (deleteTarget && ! deleteBefore)
+ if (deleteTarget && !deleteBefore)
deleteSuperfluous(source, target, deleteDate);
treeFiles += m_traverser.files();
treeDirs += m_traverser.directories();
}
double duration = double((clock() - m_start)) / CLOCKS_PER_SEC;
if (m_verboseLevel >= V_SUMMARY) {
- printStatus(m_output, duration, files, sumSizes, treeDirs,
- treeFiles, treeSumSizes);
+ printStatus(m_output, duration, files, sumSizes, treeDirs, treeFiles,
+ treeSumSizes);
}
- if (m_programArgs.getString("editor", buffer) != NULL){
+ if (m_programArgs.getString("editor", buffer) != NULL) {
ReByteArray tempFile = ReFileUtils::tempDir("redirtool.status.");
tempFile.appendInt(time(NULL), "%x").append(".txt");
FILE* fp = fopen(tempFile.str(), "w");
if (fp == NULL)
m_logger->sayF(LOG_ERROR | CAT_FILE, LC_SYNC_1,
- i18n("cannot open status file ($1): $2")).arg(errno).arg(tempFile).end();
+ i18n("cannot open status file ($1): $2")).arg(errno).arg(
+ tempFile).end();
else {
fprintf(fp, i18n("backup finished!\n\n"));
- printStatus(fp, duration, files, sumSizes, treeDirs,
- treeFiles, treeSumSizes);
+ printStatus(fp, duration, files, sumSizes, treeDirs, treeFiles,
+ treeSumSizes);
fclose(fp);
buffer.insert(0, "\"", -1);
buffer.append("\" ").append(tempFile);
int interval, int bufferSize, bool upload) {
ReTCPClient client(m_logger);
if (client.connect(ip, port)) {
- time_t start = time(NULL);
+ clock_t start = clock();
const char* command = upload ? "strlen" : "filldata";
ReByteArray message;
if (upload)
message.appendInt(bufferSize);
time_t lastPrint = start;
int64_t size = 0;
- int duration = 0;
+ double duration = 0;
ReByteArray answer, data;
client.setLogSendReceive(false);
int64_t sizeCurrent = 0;
sizeCurrent = 0;
}
}
- duration = int(time(NULL) - start);
- if (duration == 0)
- duration = 1;
- printf("%2d: %9.3f MiByte %8.3f kiByte %s/sec %s\n", rounds,
+ duration = int(clock() - start) / CLOCKS_PER_SEC;
+ if (duration == 0.0)
+ duration = 0.001;
+ printf("%2d: %9.3f MiByte %8.3f kiByte/sec %s\n", rounds,
size / 1024.0 / 1024, (double) size / duration / 1024,
upload ? "up" : "down");
* You also can use this license: http://www.wtfpl.net
* The latest sources: https://github.com/republib
*/
-#include "base/rebase.hpp"\r
-#include "os/reos.hpp"\r
-\r
-/**\r
- * Returns the name of a subdirectory in the temporary directory.\r
- *\r
- * If the directory does not exist it will be created.\r
- *\r
- * @param node the name of the subdirectory\r
- * @return the full name of the subdirectory\r
- */\r
-ReByteArray ReFileUtils::tempDir(const char* node){\r
- ReByteArray rc;\r
- if (getenv("TMP") != NULL) {\r
- rc = getenv("TMP");\r
- } else if (getenv("TEMP")) {\r
- rc = getenv("TEMP");\r
- } else {\r
-#if defined __linux__\r
- rc = "/tmp/";\r
-#elif defined __WIN32__\r
- rc = "c:\\temp";\r
-#endif\r
- }\r
- if (node != NULL){\r
- rc.ensureLastChar(OS_SEPARATOR_CHAR);\r
- rc.append(node);\r
- _mkdir(rc.str(), ALLPERMS);\r
- }\r
- return rc;\r
-}\r
-/**\r
- * Returns the name of a file in a subdirectory in the temporary directory.\r
- *\r
- * If the directory does not exist it will be created.\r
- *\r
- * @param node the name of the subdirectory\r
- * @param node the name of the subdirectory\r
- * @param the full name of the subdirectory\r
- */\r
-ReByteArray ReFileUtils::tempFile(const char* node, const char* subdir){\r
- ReByteArray rc = tempDir(subdir);\r
- rc.ensureLastChar(OS_SEPARATOR_CHAR);\r
- rc.append(node);\r
- return rc;\r
-}\r
+#include "base/rebase.hpp"
+#include "os/reos.hpp"
+
+enum LOCATION_DIRTOOL {
+ LC_SET_TIMES_1 = LOC_FIRST_OF(LOC_FILEUTILS), // 50101
+};
+
+/**
+ * Converts a filetime to a string.
+ *
+ * @param time the filetime to convert
+ * @param buffer OUT: the buffer for the string
+ * @return <code>buffer.str()</code>, e.g. "2014.01.07 02:59:43"
+ */
+ReByteArray& ReFileUtils::filetimeToString(const ReFileTime_t* time,
+ ReByteArray& buffer) {
+ time_t time1 = filetimeToTime(time);
+ struct tm* time2 = localtime(&time1);
+ buffer.setLength(4 + 2 * 2 + 2 * 2 + 1 + 3 * 2 + 2 * 1);
+ strftime(buffer.buffer(), buffer.length(), "%Y.%m.%d %H:%M:%S", time2);
+ return buffer;
+}
+
+/**
+ * Converts a filetime to a unix time (seconds since the Epoche).
+ *
+ * @param filetime the filetime to convert
+ * @return the count of seconds since 1.1.1970
+ */
+time_t ReFileUtils::filetimeToTime(const ReFileTime_t* filetime) {
+#ifdef __linux__
+ return filetime->tv_sec;
+#elif defined __WIN32__
+ // 64-bit arithmetic:
+ LARGE_INTEGER date, adjust;
+ date.HighPart = filetime->dwHighDateTime;
+ date.LowPart = filetime->dwLowDateTime;
+ // 100-nanoseconds = milliseconds * 10000
+ adjust.QuadPart = 11644473600000 * 10000;
+ // removes the diff between 1970 and 1601
+ date.QuadPart -= adjust.QuadPart;
+ // converts back from 100-nanoseconds to seconds
+ time_t rc = (time_t) (date.QuadPart / 10000000);
+#if defined __WIN32__
+ static int s_diffTime = 0x7fffffff;
+ if (s_diffTime == 0x7fffffff) {
+ s_diffTime = 0;
+ ReByteArray tempFile = ReFileUtils::tempFile("$$redir$$.tmp", NULL);
+ const char* filename = tempFile.str();
+ FILE* fp = fopen(filename, "w");
+ if (fp != NULL) {
+ struct stat info;
+ int rcStat = stat(filename, &info);
+ fclose(fp);
+ if (rcStat == 0) {
+ WIN32_FIND_DATAA data;
+ HANDLE handle = FindFirstFile(filename, &data);
+ if (handle != INVALID_HANDLE_VALUE) {
+ time_t other = filetimeToTime(&data.ftLastWriteTime);
+ s_diffTime = info.st_mtime - other;
+ FindClose(handle);
+ }
+ }
+ }
+ }
+ rc += s_diffTime;
+#endif
+ return rc;
+#endif
+}
+
+/**
+ * Reads the content of a file into a buffer.
+ *
+ * @param filename name of the file to read
+ * @param buffer OUT: the buffer for the content
+ * @return <code>buffer</code> (for chaining)
+ */
+ReByteArray& ReFileUtils::readString(const char* filename,
+ ReByteArray& buffer) {
+ struct stat info;
+ buffer.setLength(0);
+ if (stat(filename, &info) == 0 && !S_ISDIR(info.st_mode)) {
+ FILE* fp = fopen(filename, "rb");
+ if (fp != NULL) {
+ int length = info.st_size;
+ buffer.setLength(length);
+ int readBytes;
+ readBytes = fread((void*) buffer.buffer(), 1, length, fp);
+ buffer.setLength(max(readBytes, 0));
+ fclose(fp);
+ }
+ }
+ return buffer;
+}
+/**
+ * Sets the file time/times.
+ *
+ * @param name the filename
+ * @param modified the time of modification
+ * @param accessed NULL or the time of the last access
+ */
+void ReFileUtils::setTimes(const char* name, ReFileTime_t modified,
+ ReFileTime_t* accessed, ReLogger* logger) {
+#if defined linux
+ struct timeval vals[2];
+ if (accessed == NULL) {
+ vals[0].tv_sec = time(NULL);
+ vals[0].tv_usec = 0;
+ } else {
+ vals[0].tv_sec = accessed->tv_sec;
+ vals[0].tv_usec = accessed->tv_nsec / 1000;
+ }
+ vals[1].tv_sec = modified.tv_sec;
+ vals[1].tv_usec = modified.tv_nsec / 1000;
+ if (utimes(name, vals) == 0 && logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_SET_TIMES_1,
+ "cannot change times ($1): $2").arg(errno).arg(name).end();
+
+#elif defined __WIN32__
+#error "not implemented"
+#endif
+}
+
+/**
+ * Returns the name of a subdirectory in the temporary directory.
+ *
+ * If the directory does not exist it will be created.
+ *
+ * @param node NULL or the name of the subdirectory. If NULL the OS specific
+ * temporary directory will returned
+ * @return the full name of the subdirectory
+ */
+ReByteArray ReFileUtils::tempDir(const char* node) {
+ ReByteArray rc;
+ if (getenv("TMP") != NULL) {
+ rc = getenv("TMP");
+ } else if (getenv("TEMP")) {
+ rc = getenv("TEMP");
+ } else {
+#if defined __linux__
+ rc = "/tmp/";
+#elif defined __WIN32__
+ rc = "c:\\temp";
+#endif
+ }
+ if (node != NULL) {
+ rc.ensureLastChar(OS_SEPARATOR_CHAR);
+ rc.append(node);
+ _mkdir(rc.str(), ALLPERMS);
+ }
+ return rc;
+}
+/**
+ * Returns the name of a file in a subdirectory in the temporary directory.
+ *
+ * If the directory does not exist it will be created.
+ *
+ * @param node the name of the subdirectory
+ * @param node the name of the subdirectory
+ * @param the full name of the subdirectory
+ */
+ReByteArray ReFileUtils::tempFile(const char* node, const char* subdir) {
+ ReByteArray rc = tempDir(subdir);
+ rc.ensureLastChar(OS_SEPARATOR_CHAR);
+ rc.append(node);
+ return rc;
+}
+/**
+ * Converts the unix time (time_t) to the file time.
+ *
+ * @param time the unix time (secondes since 1.1.1970)
+ * @param filetime OUT: the OS specific filetime
+ */
+void ReFileUtils::timeToFiletime(time_t time, ReFileTime_t& filetime) {
+#ifdef __linux__
+ filetime.tv_sec = time;
+ filetime.tv_nsec = 0;
+#elif defined __WIN32__
+ LONGLONG ll = Int32x32To64(time, 10000000) + 116444736000000000;
+ filetime.dwLowDateTime = (DWORD)ll;
+ filetime.dwHighDateTime = ll >> 32;
+#endif
+}
+
+/**
+ * Writes a string into a file.
+ *
+ * @param filename the name of the file to write
+ * @param content the string to write
+ */
+void ReFileUtils::writeString(const char* filename, const char* content) {
+ FILE* fp = fopen(filename, "w");
+ if (fp != NULL) {
+ int length = strlen(content);
+ int written = fwrite(content, 1, length, fp);
+ reUseParam(written);
+ fclose(fp);
+ }
+}