static void check_csync_vio_chown(void **state) { CSYNC *csync = *state; int rc; rc = csync_vio_chown(csync, CSYNC_TEST_FILE, getuid(), getgid()); assert_int_equal(rc, 0); }
static int _csync_sync_dir(CSYNC *ctx, csync_file_stat_t *st) { enum csync_replica_e dest = -1; enum csync_replica_e replica_bak; char errbuf[256] = {0}; char *uri = NULL; struct timeval times[2]; int rc = -1; replica_bak = ctx->replica; switch (ctx->current) { case LOCAL_REPLICA: dest = ctx->remote.type; if (asprintf(&uri, "%s/%s", ctx->remote.uri, st->path) < 0) { return -1; } break; case REMOTE_REPLCIA: dest = ctx->local.type; if (asprintf(&uri, "%s/%s", ctx->local.uri, st->path) < 0) { return -1; } break; default: break; } ctx->replica = dest; /* chmod is if it is not the default mode */ if ((st->mode & 07777) != C_DIR_MODE) { if (csync_vio_chmod(ctx, uri, st->mode) < 0) { switch (errno) { case ENOMEM: rc = -1; break; default: rc = 1; break; } CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "dir: %s, command: chmod, error: %s", uri, strerror_r(errno, errbuf, sizeof(errbuf))); goto out; } } /* set owner and group if possible */ if (ctx->pwd.euid == 0) { csync_vio_chown(ctx, uri, st->uid, st->gid); } times[0].tv_sec = times[1].tv_sec = st->modtime; times[0].tv_usec = times[1].tv_usec = 0; csync_vio_utimes(ctx, uri, times); /* set instruction for the statedb merger */ st->instruction = CSYNC_INSTRUCTION_UPDATED; CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "SYNCED dir: %s", uri); ctx->replica = replica_bak; rc = 0; out: SAFE_FREE(uri); /* set instruction for the statedb merger */ if (rc != 0) { st->instruction = CSYNC_INSTRUCTION_ERROR; } return rc; }
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; }