Beispiel #1
0
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);
}
Beispiel #2
0
static void check_csync_vio_write_null(void **state)
{
    CSYNC *csync = *state;
    char test[16] = {0};
    int rc;

    rc = csync_vio_write(csync, NULL, test, 10);
    assert_int_equal(rc, -1);
}
Beispiel #3
0
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;
}