static void check_csync_vio_write(void **state) { CSYNC *csync = *state; csync_vio_method_handle_t *fh; char str[] = "This is a test"; char test[16] = {0}; int rc; fh = csync_vio_creat(csync, CSYNC_TEST_FILE, 0644); assert_non_null(fh); rc = csync_vio_write(csync, fh, str, sizeof(str)); assert_int_equal(rc, sizeof(str)); rc = csync_vio_close(csync, fh); assert_int_equal(rc, 0); fh = csync_vio_open(csync, CSYNC_TEST_FILE, O_RDONLY, 0644); assert_non_null(fh); rc = csync_vio_read(csync, fh, test, 14); assert_int_equal(rc, 14); assert_string_equal(test, "This is a test"); rc = csync_vio_close(csync, fh); assert_int_equal(rc, 0); }
static void check_csync_vio_close_null(void **state) { CSYNC *csync = *state; int rc; rc = csync_vio_close(csync, NULL); assert_int_equal(rc, -1); }
static void check_csync_vio_open_close(void **state) { CSYNC *csync = *state; csync_vio_method_handle_t *fh; int rc; fh = csync_vio_open(csync, CSYNC_TEST_FILE, O_RDONLY, 0644); assert_non_null(fh); rc = csync_vio_close(csync, fh); assert_int_equal(rc, 0); }
static void check_csync_vio_read_0(void **state) { CSYNC *csync = *state; csync_vio_method_handle_t *fh = NULL; char test[16] = {0}; int rc; fh = csync_vio_open(csync, CSYNC_TEST_FILE, O_RDONLY, 0644); assert_non_null(fh); rc = csync_vio_read(csync, fh, test, 0); assert_int_equal(rc, 0); assert_true(test[0] == '\0'); rc = csync_vio_close(csync, fh); assert_int_equal(rc, 0); }
static void check_csync_vio_lseek(void **state) { CSYNC *csync = *state; csync_vio_method_handle_t *fh; char test[16] = {0}; int rc; fh = csync_vio_open(csync, CSYNC_TEST_FILE, O_RDONLY, 0644); assert_non_null(fh); rc = csync_vio_lseek(csync, fh, 10, SEEK_SET); assert_int_equal(rc, 10); rc = csync_vio_read(csync, fh, test, 4); assert_int_equal(rc, 4); assert_string_equal(test, "test"); rc = csync_vio_close(csync, fh); assert_int_equal(rc, 0); }
/* check time difference between the replicas */ time_t csync_timediff(CSYNC *ctx) { time_t timediff = -1; char errbuf[256] = {0}; char *luri = NULL; char *ruri = NULL; csync_vio_handle_t *fp = NULL; csync_vio_file_stat_t *st = NULL; csync_vio_handle_t *dp = NULL; /* try to open remote dir to get auth */ ctx->replica = ctx->remote.type; dp = csync_vio_opendir(ctx, ctx->remote.uri); if (dp == NULL) { /* * To prevent problems especially with pam_csync we shouldn't try to create the * remote directory here. Just fail! */ strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Access dienied to remote uri: %s - %s", ctx->remote.uri, errbuf); return -1; } csync_vio_closedir(ctx, dp); if (asprintf(&luri, "%s/.csync_timediff.ctmp", ctx->local.uri) < 0) { goto out; } if (asprintf(&ruri, "%s/.csync_timediff.ctmp", ctx->remote.uri) < 0) { goto out; } /* create temporary file on local */ ctx->replica = ctx->local.type; fp = csync_vio_creat(ctx, luri, 0644); if (fp == NULL) { strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Unable to create temporary file: %s - %s", luri, errbuf); goto out; } csync_vio_close(ctx, fp); /* Get the modification time */ st = csync_vio_file_stat_new(); if (csync_vio_stat(ctx, luri, st) < 0) { strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Synchronisation is not possible! %s - %s", luri, errbuf); goto out; } timediff = st->mtime; csync_vio_file_stat_destroy(st); st = NULL; /* create temporary file on remote replica */ ctx->replica = ctx->remote.type; fp = csync_vio_creat(ctx, ruri, 0644); if (fp == NULL) { strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Unable to create temporary file: %s - %s", ruri, errbuf); goto out; } csync_vio_close(ctx, fp); /* Get the modification time */ st = csync_vio_file_stat_new(); if (csync_vio_stat(ctx, ruri, st) < 0) { strerror_r(errno, errbuf, sizeof(errbuf)); CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Synchronisation is not possible! %s - %s", ruri, errbuf); goto out; } /* calc time difference */ timediff = llabs(timediff - st->mtime); CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Time difference: %ld seconds", timediff); out: csync_vio_file_stat_destroy(st); ctx->replica = ctx->local.type; csync_vio_unlink(ctx, luri); SAFE_FREE(luri); ctx->replica = ctx->remote.type; csync_vio_unlink(ctx, ruri); SAFE_FREE(ruri); return timediff; }
static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) { enum csync_replica_e srep = -1; enum csync_replica_e drep = -1; enum csync_replica_e rep_bak = -1; char *suri = NULL; char *duri = NULL; char *turi = NULL; char *tdir = NULL; csync_vio_handle_t *sfp = NULL; csync_vio_handle_t *dfp = NULL; csync_vio_file_stat_t *tstat = NULL; char errbuf[256] = {0}; char buf[MAX_XFER_BUF_SIZE] = {0}; ssize_t bread = 0; ssize_t bwritten = 0; struct timeval times[2]; int rc = -1; int count = 0; int flags = 0; rep_bak = ctx->replica; switch (ctx->current) { case LOCAL_REPLICA: srep = ctx->local.type; drep = ctx->remote.type; if (asprintf(&suri, "%s/%s", ctx->local.uri, st->path) < 0) { rc = -1; goto out; } if (asprintf(&duri, "%s/%s", ctx->remote.uri, st->path) < 0) { rc = -1; goto out; } break; case REMOTE_REPLCIA: srep = ctx->remote.type; drep = ctx->local.type; if (asprintf(&suri, "%s/%s", ctx->remote.uri, st->path) < 0) { rc = -1; goto out; } if (asprintf(&duri, "%s/%s", ctx->local.uri, st->path) < 0) { rc = -1; goto out; } break; default: break; } /* Open the source file */ ctx->replica = srep; flags = O_RDONLY|O_NOFOLLOW; /* O_NOATIME can only be set by the owner of the file or the superuser */ if (st->uid == ctx->pwd.uid || ctx->pwd.euid == 0) { flags |= O_NOATIME; } sfp = csync_vio_open(ctx, suri, flags, 0); if (sfp == NULL) { if (errno == ENOMEM) { rc = -1; } else { rc = 1; } CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: open(O_RDONLY), error: %s", suri, strerror_r(errno, errbuf, sizeof(errbuf))); goto out; } /* create the temporary file name */ if (asprintf(&turi, "%s.XXXXXX", duri) < 0) { rc = -1; goto out; } /* We just want a random file name here, open checks if the file exists. */ if (c_tmpname(turi) < 0) { rc = -1; goto out; } /* Create the destination file */ ctx->replica = drep; while ((dfp = csync_vio_open(ctx, turi, O_CREAT|O_EXCL|O_WRONLY|O_NOCTTY, C_FILE_MODE)) == NULL) { switch (errno) { case EEXIST: if (count++ > 10) { CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: open(O_CREAT), error: max count exceeded", duri); rc = 1; goto out; } if (c_tmpname(turi) < 0) { rc = -1; goto out; } break; case ENOENT: /* get the directory name */ tdir = c_dirname(turi); if (tdir == NULL) { rc = -1; goto out; } if (csync_vio_mkdirs(ctx, tdir, C_DIR_MODE) < 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "dir: %s, command: mkdirs, error: %s", tdir, strerror_r(errno, errbuf, sizeof(errbuf))); } break; case ENOMEM: rc = -1; CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: open(O_CREAT), error: %s", turi, strerror_r(errno, errbuf, sizeof(errbuf))); goto out; break; default: CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: open(O_CREAT), error: %s", turi, strerror_r(errno, errbuf, sizeof(errbuf))); rc = 1; goto out; break; } } /* copy file */ for (;;) { ctx->replica = srep; bread = csync_vio_read(ctx, sfp, buf, MAX_XFER_BUF_SIZE); if (bread < 0) { /* read error */ CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: read, error: %s", suri, strerror_r(errno, errbuf, sizeof(errbuf))); rc = 1; goto out; } else if (bread == 0) { /* done */ break; } ctx->replica = drep; bwritten = csync_vio_write(ctx, dfp, buf, bread); if (bwritten < 0 || bread != bwritten) { CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: write, error: bread = %zu, bwritten = %zu - %s", duri, bread, bwritten, strerror_r(errno, errbuf, sizeof(errbuf))); rc = 1; goto out; } } ctx->replica = srep; if (csync_vio_close(ctx, sfp) < 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: close, error: %s", suri, strerror_r(errno, errbuf, sizeof(errbuf))); } sfp = NULL; ctx->replica = drep; if (csync_vio_close(ctx, dfp) < 0) { dfp = NULL; switch (errno) { /* stop if no space left or quota exceeded */ case ENOSPC: case EDQUOT: CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: close, error: %s", turi, strerror_r(errno, errbuf, sizeof(errbuf))); rc = -1; goto out; break; default: CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: close, error: %s", turi, strerror_r(errno, errbuf, sizeof(errbuf))); break; } } dfp = NULL; /* * Check filesize */ ctx->replica = drep; tstat = csync_vio_file_stat_new(); if (tstat == NULL) { CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: stat, error: %s", turi, strerror_r(errno, errbuf, sizeof(errbuf))); rc = -1; goto out; } if (csync_vio_stat(ctx, turi, tstat) < 0) { switch (errno) { case ENOMEM: rc = -1; break; default: rc = 1; break; } CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: stat, error: %s", turi, strerror_r(errno, errbuf, sizeof(errbuf))); goto out; } if (st->size != tstat->size) { CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, error: incorrect filesize (size: %jd should be %jd)", turi, tstat->size, st->size); rc = 1; goto out; } /* override original file */ ctx->replica = drep; if (csync_vio_rename(ctx, turi, duri) < 0) { switch (errno) { case ENOMEM: rc = -1; break; default: rc = 1; break; } CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: rename, error: %s", duri, strerror_r(errno, errbuf, sizeof(errbuf))); goto out; } /* set mode only if it is not the default mode */ if ((st->mode & 07777) != C_FILE_MODE) { if (csync_vio_chmod(ctx, duri, st->mode) < 0) { switch (errno) { case ENOMEM: rc = -1; break; default: rc = 1; break; } CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file: %s, command: chmod, error: %s", duri, strerror_r(errno, errbuf, sizeof(errbuf))); goto out; } } /* set owner and group if possible */ if (ctx->pwd.euid == 0) { csync_vio_chown(ctx, duri, st->uid, st->gid); } /* sync time */ times[0].tv_sec = times[1].tv_sec = st->modtime; times[0].tv_usec = times[1].tv_usec = 0; ctx->replica = drep; csync_vio_utimes(ctx, duri, times); /* set instruction for the statedb merger */ st->instruction = CSYNC_INSTRUCTION_UPDATED; CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "PUSHED file: %s", duri); rc = 0; out: ctx->replica = srep; csync_vio_close(ctx, sfp); ctx->replica = drep; csync_vio_close(ctx, dfp); csync_vio_file_stat_destroy(tstat); /* set instruction for the statedb merger */ if (rc != 0) { st->instruction = CSYNC_INSTRUCTION_ERROR; csync_vio_unlink(ctx, turi); } SAFE_FREE(suri); SAFE_FREE(duri); SAFE_FREE(turi); SAFE_FREE(tdir); ctx->replica = rep_bak; return rc; }