#include "base/rebase.hpp"
#include "os/reos.hpp"
+enum LOCATION_DIRTOOL {
+ LC_COPY_FILE_1 = LC_DIRTOOLS + 1, // 50101
+ LC_COPY_FILE_2, // 50102
+ LC_COPY_FILE_3, // 50103
+ LC_COPY_FILE_4, // 50104
+ LC_COPY_FILE_5, // 50105
+ LC_COPY_FILE_6, // 50106
+};
const char* ReDirTools::m_version = "2015.01.05";
static const char* s_helpSummary[] = {
* Constructor.
*/
ReDirSync::ReDirSync() :
- ReDirOptions(s_syncUsage, s_syncExamples)
+ ReDirOptions(s_syncUsage, s_syncExamples),
+ m_buffer()
{
+ m_buffer.ensureSize(4u*1024*1024*1024);
+ m_programArgs.addBool("add",
+ i18n("copies only files which does not exist on the target"),
+ 'a', "add", false);
+ m_programArgs.addBool("dry",
+ i18n("does nothing, but says what should be done"),
+ 'd', "dry", false);
+ m_programArgs.addInt("timediff",
+ i18n("filetime difference is considered to be equal\n"
+ "if the difference is less than this value (in seconds)"),
+ 'D', "time-delta", 2);
+ m_programArgs.addBool("ignoredate",
+ i18n("the modification is recognized only by the different size (not time)"),
+ 'i', "ignore-time", false);
+ m_programArgs.addBool("chatter",
+ i18n("comments the action of each file"),
+ 'h', "chatter", false);
m_programArgs.addBool("mustexist",
i18n("files which don't exist on the target will not be copied"),
'm', "must-exist", false);
addStandardFilterOptions();
}
+/**
+ * Copies a file.
+ *
+ * @param entry the source file info
+ * @param target the name of the target file
+ */
+void ReDirSync::copyFile(ReDirStatus_t* entry, const char* target){
+ copyFile(entry->fullName(), entry->filetimeToTime(entry->modified()),
+ entry->fileSize(), target, m_buffer, ReLogger::globalLogger());
+}
+/**
+ * Copies a file.
+ *
+ * @param source the source file name
+ * @param modified 0 or modification time
+ * @param size -1 or filesize
+ * @param target the name of the target file
+ * @param buffer OUT: the reading uses this buffer<br>
+ * Set the capacity to make it more efficient
+ * @param logger NULL or the logger for error messages
+ */
+bool ReDirSync::copyFile(const char* source, time_t modified, int64_t size,
+ const char* target, ReByteBuffer& buffer, ReLogger* logger){
+ bool rc = false;
+ if (size < 0ll){
+ struct stat info;
+ if (stat(source, &info) == 0)
+ size = info.st_size;
+ else if (logger != NULL)
+ logger->sayF(LOG_ERROR, LC_COPY_FILE_1,
+ i18n("could not find: $ (errno: $2)")).arg(source).arg(errno).end();
+ }
+ if (size >= 0){
+ FILE* fpSource = fopen(source, "rb");
+ if (fpSource == NULL){
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR, LC_COPY_FILE_2,
+ i18n("cannot open $1 (errno: $2)"))
+ .arg(source).arg(errno).end();
+ } else {
+ FILE* fpTarget = fopen(target, "w");
+ if (fpTarget == NULL){
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR, LC_COPY_FILE_3,
+ i18n("cannot open $1 (errno: $2)"))
+ .arg(target).arg(errno).end();
+ } else{
+ // Reserve the space:
+ if (fseek(fpTarget, size, SEEK_SET) != size){
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR, LC_COPY_FILE_4,
+ i18n("cannot reserve space for $1 (errno: $2)"))
+ .arg(target).arg(errno).end();
+ } else {
+ fseek(fpTarget, 0, SEEK_SET);
+ while(size > 0){
+ size_t blockSize = buffer.capacity();
+ if (blockSize > size)
+ blockSize = size;
+ if (fread(buffer.buffer(), blockSize, 1, fpSource) != 1){
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR, LC_COPY_FILE_5,
+ i18n("cannot read $1 (errno: $2)"))
+ .arg(source).arg(errno).end();
+ break;
+ }
+ if (fwrite(buffer.buffer(), 1, blockSize, fpSource) != 1){
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR, LC_COPY_FILE_6,
+ i18n("cannot write $1 (errno: $2)"))
+ .arg(target).arg(errno).end();
+ break;
+ }
+ size -= blockSize;
+ }
+ }
+ rc = size == 0ll;
+ fclose(fpTarget);
+ }
+ fclose(fpSource);
+ }
+ }
+ return rc;
+}
/**
* Gets the arguments for the "list" command and execute this.
*
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");
+ bool chatterMode = m_programArgs.getBool("chatter");
+ int maxFileTimeDiff = m_programArgs.getInt("timediff");
+ bool dry = m_programArgs.getBool("dry");
+ bool ignoreDate = m_programArgs.getBool("ignoredate");
+ bool mustExist = m_programArgs.getBool("mustexist");
bool verbose = ! m_programArgs.getBool("quiet");
- bool chatterMode = true;
- bool copyExistingOnly = false;
setFilterFromProgramArgs(filter);
int64_t sumSizes = 0;
int files = 0;
int dirs = 0;
ReByteBuffer source;
ReByteBuffer targetFile;
- int maxFileTimeDiff = 2;
for (int ix = 0; ix < m_programArgs.getArgCount() - 1; ix++){
source.set(m_programArgs.getArg(ix), -1);
target.setLength(lengthTargetBase);
while( (entry = traverser.nextFile(level, &filter)) != NULL){
// append the new relative path from source to target:
target.setLength(ixTargetRelative);
+ const char* targetRelativePath = target.str() + ixTargetRelative;
target.append(entry->m_path.str() + ixSourceRelative, -1);
if (stat(target.str(), &info) != 0)
makeDirWithParents(target, ixTargetRelative);
targetFile.set(target).append(entry->node(), -1);
bool exists = stat(targetFile.str(), &info) == 0;
- if ( (! exists && ! copyExistingOnly)
- || entry->filetimeToTime(entry->modified()) - info.st_mtime
+ if (! exists && ! mustExist){
+ if (chatterMode)
+ printf("-ignored: %s does not exist\n", targetRelativePath);
+ continue;
+ }
+ if (exists && addOnly){
+ if (chatterMode)
+ printf("~ignored: %s exists\n", targetRelativePath);
+ continue;
+ }
+ if (ignoreDate && entry->fileSize() == info.st_size){
+ if (chatterMode)
+ printf("_ignored: %s same size\n", targetRelativePath);
+ continue;
+ }
+ if (! ignoreDate && entry->filetimeToTime(entry->modified()) - info.st_mtime
> maxFileTimeDiff) {
if (chatterMode)
- printf("%s%s same time\n", entry->m_path.str(), entry->node());
+ printf("=ignored: %s same time\n", targetRelativePath);
continue;
} else {
-
- }
-
- if (entry->isDirectory())
- dirs++;
- else{
- files++;
- sumSizes += entry->fileSize();
- }
- if (verbose)
- printf("%s\n", line.str());
- }
+ if (entry->isDirectory())
+ dirs++;
+ else{
+ files++;
+ sumSizes += entry->fileSize();
+ }
+ if (verbose || chatterMode || dry)
+ printf("%c%s%s\n", exists ? '!' : '+', targetRelativePath,
+ dry ? " would be copied" : "");
+ if (! dry)
+ copyFile(entry, target.str());
+ }
+ }
}
if (verbose){
int duration = int(time(NULL) - start);
testAll();
}else
tools.usage("unknown command: ", argv[1]);
- //testOs();
- ReLogger::freeGlobalLogger();
+ ReLogger::freeGlobalLogger();
return 0;
}