Exemplo n.º 1
0
csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
  struct _tdirent *dirent = NULL;

  dhandle_t *handle = NULL;
  csync_vio_file_stat_t *file_stat = NULL;

  handle = (dhandle_t *) dhandle;

  errno = 0;
  dirent = _treaddir(handle->dh);
  if (dirent == NULL) {
    if (errno) {
      goto err;
    } else {
      return NULL;
    }
  }

  file_stat = csync_vio_file_stat_new();
  if (file_stat == NULL) {
    goto err;
  }

  file_stat->name = c_utf8_from_locale(dirent->d_name);
  file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;

  /* Check for availability of d_type, see manpage. */
#ifdef _DIRENT_HAVE_D_TYPE
  switch (dirent->d_type) {
    case DT_FIFO:
    case DT_SOCK:
    case DT_CHR:
    case DT_BLK:
      break;
    case DT_DIR:
    case DT_REG:
      file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
      if (dirent->d_type == DT_DIR) {
        file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
      } else {
        file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR;
      }
      break;
    case DT_UNKNOWN:
      file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
      file_stat->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
    default:
      break;
  }
#endif

  return file_stat;

err:
  SAFE_FREE(file_stat);

  return NULL;
}
Exemplo n.º 2
0
csync_vio_file_stat_t *csync_vio_convert_file_stat(csync_file_stat_t *st) {
  csync_vio_file_stat_t *vfs = NULL;

  if (st == NULL) {
    return NULL;
  }

  vfs = csync_vio_file_stat_new();
  if (vfs == NULL) {
    return NULL;
  }
  vfs->acl = NULL;
  if (st->pathlen > 0) {
    vfs->name = c_strdup(st->path);
  }
  vfs->uid   = st->uid;
  vfs->gid   = st->gid;

  vfs->atime = 0;
  vfs->mtime = st->modtime;
  vfs->ctime = 0;

  vfs->size  = st->size;
  vfs->blksize  = 0;  /* Depricated. */
  vfs->blkcount = 0;

  vfs->mode  = st->mode;
  vfs->device = 0;
  vfs->inode = st->inode;
  vfs->nlink = st->nlink;

  /* fields. */
  vfs->fields = CSYNC_VIO_FILE_STAT_FIELDS_TYPE
      + CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS
      + CSYNC_VIO_FILE_STAT_FIELDS_INODE
      + CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT
      + CSYNC_VIO_FILE_STAT_FIELDS_SIZE
      + CSYNC_VIO_FILE_STAT_FIELDS_MTIME
      + CSYNC_VIO_FILE_STAT_FIELDS_UID
      + CSYNC_VIO_FILE_STAT_FIELDS_GID;

  if (st->type == CSYNC_FTW_TYPE_DIR)
    vfs->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
  else if (st->type == CSYNC_FTW_TYPE_FILE)
    vfs->type = CSYNC_VIO_FILE_TYPE_REGULAR;
  else if (st->type == CSYNC_FTW_TYPE_SLINK)
    vfs->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
  else
    vfs->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;

  return vfs;
}
Exemplo n.º 3
0
static qint64 getSizeWithCsync(const QString& filename)
{
    qint64 result = 0;
    csync_vio_file_stat_t* stat = csync_vio_file_stat_new();
    if (csync_vio_local_stat(filename.toUtf8().data(), stat) != -1
            && (stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_SIZE)) {
        result = stat->size;
    } else {
        qDebug() << "Could not get size time for" << filename << "with csync";
    }
    csync_vio_file_stat_destroy(stat);
    return result;
}
Exemplo n.º 4
0
time_t FileSystem::getModTime(const QString &filename)
{
    csync_vio_file_stat_t* stat = csync_vio_file_stat_new();
    qint64 result = -1;
    if (csync_vio_local_stat(filename.toUtf8().data(), stat) != -1
            && (stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_MTIME)) {
        result = stat->mtime;
    } else {
        qDebug() << "Could not get modification time for" << filename
                 << "with csync, using QFileInfo";
        result = Utility::qDateTimeToTime_t(QFileInfo(filename).lastModified());
    }
    csync_vio_file_stat_destroy(stat);
    return result;
}
Exemplo n.º 5
0
static void check_csync_vio_stat_file(void **state)
{
    CSYNC *csync = *state;
    csync_vio_file_stat_t *fs;
    int rc;

    fs = csync_vio_file_stat_new();
    assert_non_null(fs);

    rc = csync_vio_stat(csync, CSYNC_TEST_FILE, fs);
    assert_int_equal(rc, 0);

    assert_string_equal(fs->name, "file.txt");
    assert_int_equal(fs->type, CSYNC_VIO_FILE_TYPE_REGULAR);

    csync_vio_file_stat_destroy(fs);
}
Exemplo n.º 6
0
static void check_csync_vio_stat_dir(void **state)
{
    CSYNC *csync = *state;
    csync_vio_file_stat_t *fs;
    int rc;

    fs = csync_vio_file_stat_new();
    assert_non_null(fs);

    rc = csync_vio_stat(csync, CSYNC_TEST_DIR, fs);
    assert_int_equal(rc, 0);

    assert_string_equal(fs->name, "csync_test");
    assert_int_equal(fs->type, CSYNC_VIO_FILE_TYPE_DIRECTORY);

    csync_vio_file_stat_destroy(fs);
}
csync_vio_file_stat_t* csync_vio_file_stat_copy(csync_vio_file_stat_t *file_stat) {
    csync_vio_file_stat_t *file_stat_cpy = csync_vio_file_stat_new();
    memcpy(file_stat_cpy, file_stat, sizeof(csync_vio_file_stat_t));
    if (file_stat_cpy->fields & CSYNC_VIO_FILE_STAT_FIELDS_ETAG) {
        file_stat_cpy->etag = c_strdup(file_stat_cpy->etag);
    }
    if (file_stat_cpy->directDownloadCookies) {
        file_stat_cpy->directDownloadCookies = c_strdup(file_stat_cpy->directDownloadCookies);
    }
    if (file_stat_cpy->directDownloadUrl) {
        file_stat_cpy->directDownloadUrl = c_strdup(file_stat_cpy->directDownloadUrl);
    }
    if (file_stat_cpy->checksumHeader) {
        file_stat_cpy->checksumHeader = c_strdup(file_stat_cpy->checksumHeader);
    }
    file_stat_cpy->name = c_strdup(file_stat_cpy->name);
    return file_stat_cpy;
}
Exemplo n.º 8
0
csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {

  dhandle_t *handle = NULL;
  csync_vio_file_stat_t *file_stat = NULL;

  handle = (dhandle_t *) dhandle;

  errno = 0;
  file_stat = csync_vio_file_stat_new();
  if (file_stat == NULL) {
    goto err;
  }
  file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;

  // the win32 functions get the first valid entry with the opendir
  // thus we must not jump to next entry if it was the first find.
  if( handle->firstFind ) {
      handle->firstFind = 0;
  } else {
      if( FindNextFile(handle->hFind, &(handle->ffd)) == 0 ) {
          // might be error, check!
          int dwError = GetLastError();
          if (dwError != ERROR_NO_MORE_FILES) {
              errno = EACCES; // no more files is fine. Otherwise EACCESS
          }
          goto err;
      }
  }
  file_stat->name = c_utf8_from_locale(handle->ffd.cFileName);

  file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
  if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
      file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
  } else {
      file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR;
  }

  return file_stat;

err:
  SAFE_FREE(file_stat);

  return NULL;
}
Exemplo n.º 9
0
/* File tree walker */
int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
    unsigned int depth) {
  char *filename = NULL;
  char *d_name = NULL;
  csync_vio_handle_t *dh = NULL;
  csync_vio_file_stat_t *dirent = NULL;
  csync_vio_file_stat_t *fs = NULL;
  csync_file_stat_t *previous_fs = NULL;
  int read_from_db = 0;
  int rc = 0;
  int res = 0;

  bool do_read_from_db = (ctx->current == REMOTE_REPLICA && ctx->remote.read_from_db);

  if (uri[0] == '\0') {
    errno = ENOENT;
    ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
    goto error;
  }

  read_from_db = ctx->remote.read_from_db;

  // if the etag of this dir is still the same, its content is restored from the
  // database.
  if( do_read_from_db ) {
      if( ! fill_tree_from_db(ctx, uri) ) {
        errno = ENOENT;
        ctx->status_code = CSYNC_STATUS_OPENDIR_ERROR;
        goto error;
      }
      goto done;
  }

  if ((dh = csync_vio_opendir(ctx, uri)) == NULL) {
      int asp = 0;
      /* permission denied */
      ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_OPENDIR_ERROR);
      if (errno == EACCES) {
          return 0;
      } else if(errno == ENOENT) {
          asp = asprintf( &ctx->error_string, "%s", uri);
          if (asp < 0) {
              CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "asprintf failed!");
          }
      } else {
          CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "opendir failed for %s - errno %d", uri, errno);
      }
      goto error;
  }

  while ((dirent = csync_vio_readdir(ctx, dh))) {
    const char *path = NULL;
    size_t ulen = 0;
    int flen;
    int flag;

    d_name = dirent->name;
    if (d_name == NULL) {
      ctx->status_code = CSYNC_STATUS_READDIR_ERROR;
      goto error;
    }

    /* skip "." and ".." */
    if (d_name[0] == '.' && (d_name[1] == '\0'
          || (d_name[1] == '.' && d_name[2] == '\0'))) {
      csync_vio_file_stat_destroy(dirent);
      dirent = NULL;
      continue;
    }

    flen = asprintf(&filename, "%s/%s", uri, d_name);
    if (flen < 0) {
      csync_vio_file_stat_destroy(dirent);
      dirent = NULL;
      ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
      goto error;
    }

    /* Create relative path */
    switch (ctx->current) {
      case LOCAL_REPLICA:
        ulen = strlen(ctx->local.uri) + 1;
        break;
      case REMOTE_REPLICA:
        ulen = strlen(ctx->remote.uri) + 1;
        break;
      default:
        break;
    }

    if (((size_t)flen) < ulen) {
      csync_vio_file_stat_destroy(dirent);
      dirent = NULL;
      ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
      goto error;
    }

    path = filename + ulen;

    /* skip ".csync_journal.db" and ".csync_journal.db.ctmp" */
    if (c_streq(path, ".csync_journal.db")
            || c_streq(path, ".csync_journal.db.ctmp")
            || c_streq(path, ".csync_journal.db.ctmp-journal")
            || c_streq(path, ".csync-progressdatabase")) {
        csync_vio_file_stat_destroy(dirent);
        dirent = NULL;
        SAFE_FREE(filename);
        continue;
    }

    /* Only for the local replica we have to stat(), for the remote one we have all data already */
    if (ctx->replica == LOCAL_REPLICA) {
        fs = csync_vio_file_stat_new();
        res = csync_vio_stat(ctx, filename, fs);
    } else {
        fs = dirent;
        res = 0;
    }

    if( res == 0) {
      switch (fs->type) {
        case CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK:
          flag = CSYNC_FTW_FLAG_SLINK;
          break;
        case CSYNC_VIO_FILE_TYPE_DIRECTORY:
          flag = CSYNC_FTW_FLAG_DIR;
          break;
        case CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE:
        case CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE:
        case CSYNC_VIO_FILE_TYPE_SOCKET:
          flag = CSYNC_FTW_FLAG_SPEC;
          break;
        case CSYNC_VIO_FILE_TYPE_FIFO:
          flag = CSYNC_FTW_FLAG_SPEC;
          break;
        default:
          flag = CSYNC_FTW_FLAG_FILE;
          break;
      };
    } else {
      flag = CSYNC_FTW_FLAG_NSTAT;
    }

    if( ctx->current == LOCAL_REPLICA ) {
        char *etag = NULL;
        int len = strlen( path );
        uint64_t h = c_jhash64((uint8_t *) path, len, 0);
        etag = csync_statedb_get_etag( ctx, h );

        if( etag ) {
            SAFE_FREE(fs->etag);
            fs->etag = etag;
            fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;

            if( c_streq(etag, "")) {
                CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Uniq ID from Database is EMPTY: %s", path);
            } else {
                CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Uniq ID from Database: %s -> %s", path, fs->etag ? fs->etag : "<NULL>" );
            }
        }
    }

    previous_fs = ctx->current_fs;

    /* Call walker function for each file */
    rc = fn(ctx, filename, fs, flag);
    /* this function may update ctx->current and ctx->read_from_db */

    if (ctx->current_fs && previous_fs && ctx->current_fs->child_modified) {
        previous_fs->child_modified = ctx->current_fs->child_modified;
    }

    /* Only for the local replica we have to destroy stat(), for the remote one it is a pointer to dirent */
    if (ctx->replica == LOCAL_REPLICA) {
        csync_vio_file_stat_destroy(fs);
    }

    if (rc < 0) {
      if (CSYNC_STATUS_IS_OK(ctx->status_code)) {
          ctx->status_code = CSYNC_STATUS_UPDATE_ERROR;
      }

      ctx->current_fs = previous_fs;
      goto error;
    }

    if (flag == CSYNC_FTW_FLAG_DIR && depth
        && (!ctx->current_fs || ctx->current_fs->instruction != CSYNC_INSTRUCTION_IGNORE)) {
      rc = csync_ftw(ctx, filename, fn, depth - 1);
      if (rc < 0) {
        ctx->current_fs = previous_fs;
        goto error;
      }

      if (ctx->current_fs && !ctx->current_fs->child_modified
          && ctx->current_fs->instruction == CSYNC_INSTRUCTION_EVAL) {
        ctx->current_fs->instruction = CSYNC_INSTRUCTION_NONE;
        ctx->current_fs->should_update_etag = true;
      }
    }

    if (flag == CSYNC_FTW_FLAG_DIR && ctx->current_fs
        && (ctx->current_fs->instruction == CSYNC_INSTRUCTION_EVAL ||
            ctx->current_fs->instruction == CSYNC_INSTRUCTION_NEW ||
            ctx->current_fs->instruction == CSYNC_INSTRUCTION_EVAL_RENAME)) {
        ctx->current_fs->should_update_etag = true;
    }

    ctx->current_fs = previous_fs;
    ctx->remote.read_from_db = read_from_db;
    SAFE_FREE(filename);
    csync_vio_file_stat_destroy(dirent);
    dirent = NULL;
  }

  csync_vio_closedir(ctx, dh);
  CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, " <= Closing walk for %s with read_from_db %d", uri, read_from_db);

done:
  csync_vio_file_stat_destroy(dirent);
  SAFE_FREE(filename);
  return rc;
error:
  ctx->remote.read_from_db = read_from_db;
  if (dh != NULL) {
    csync_vio_closedir(ctx, dh);
  }
  SAFE_FREE(filename);
  return -1;
}
Exemplo n.º 10
0
/* create a file stat, caller must free memory */
static csync_vio_file_stat_t* create_fstat(const char *name,
                                           ino_t inode,
                                           nlink_t nlink,
                                           time_t mtime)
{
    csync_vio_file_stat_t *fs = NULL;
    time_t t;

    fs = csync_vio_file_stat_new();
    if (fs == NULL) {
        return NULL;
    }

    if (name && *name) {
        fs->name = c_strdup(name);
    } else {
        fs->name = c_strdup("file.txt");
    }

    if (fs->name == NULL) {
        csync_vio_file_stat_destroy(fs);
        return NULL;
    }

    fs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;

    fs->type = CSYNC_VIO_FILE_TYPE_REGULAR;
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;

    fs->mode = 0644;
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;

    if (inode == 0) {
        fs->inode = 619070;
    } else {
        fs->inode = inode;
    }
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE;

    fs->device = 0;

    fs->size = 157459;
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;

    if (nlink == 0) {
        fs->nlink = 1;
    } else {
        fs->nlink = nlink;
    }
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT;

    fs->uid = 1000;
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_UID;

    fs->gid = 1000;
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_GID;

    fs->blkcount = 312;
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_COUNT;

    fs->blksize = 4096;
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_SIZE;

    if (mtime == 0) {
        fs->atime = fs->ctime = fs->mtime = time(&t);
    } else {
        fs->atime = fs->ctime = fs->mtime = mtime;
    }
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME;
    fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;

    return fs;
}
Exemplo n.º 11
0
csync_vio_file_stat_t *csync_vio_local_readdir(csync_vio_handle_t *dhandle) {

  dhandle_t *handle = NULL;
  csync_vio_file_stat_t *file_stat = NULL;
  ULARGE_INTEGER FileIndex;
  DWORD rem;

  handle = (dhandle_t *) dhandle;

  errno = 0;
  file_stat = csync_vio_file_stat_new();
  if (file_stat == NULL) {
      errno = ENOMEM;
      goto err;
  }
  file_stat->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;

  // the win32 functions get the first valid entry with the opendir
  // thus we must not jump to next entry if it was the first find.
  if( handle->firstFind ) {
      handle->firstFind = 0;
  } else {
      if( FindNextFile(handle->hFind, &(handle->ffd)) == 0 ) {
          // might be error, check!
          int dwError = GetLastError();
          if (dwError != ERROR_NO_MORE_FILES) {
              errno = EACCES; // no more files is fine. Otherwise EACCESS
          }
          goto err;
      }
  }
  file_stat->name = c_utf8_from_locale(handle->ffd.cFileName);

  file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
  if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT
            && handle->ffd.dwReserved0 & IO_REPARSE_TAG_SYMLINK) {
        file_stat->flags = CSYNC_VIO_FILE_FLAGS_SYMLINK;
        file_stat->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
    } else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE
                || handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE
                || handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
        file_stat->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
    } else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        file_stat->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
    } else {
        file_stat->type = CSYNC_VIO_FILE_TYPE_REGULAR;
    }

    file_stat->flags = CSYNC_VIO_FILE_FLAGS_NONE;
    /* Check for the hidden flag */
    if( handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) {
        file_stat->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN;
    }

    file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;
    file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;

    file_stat->size = (handle->ffd.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + handle->ffd.nFileSizeLow;
    file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;

    file_stat->atime = FileTimeToUnixTime(&handle->ffd.ftLastAccessTime, &rem);
    file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;

    file_stat->mtime = FileTimeToUnixTime(&handle->ffd.ftLastWriteTime, &rem);
      /* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Local File MTime: %llu", (unsigned long long) buf->mtime ); */
    file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;

    file_stat->ctime = FileTimeToUnixTime(&handle->ffd.ftCreationTime, &rem);
    file_stat->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME;

    return file_stat;

err:
  SAFE_FREE(file_stat);

  return NULL;
}
Exemplo n.º 12
0
/* File tree walker */
int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
    unsigned int depth) {
  char errbuf[256] = {0};
  char *filename = NULL;
  char *d_name = NULL;
  csync_vio_handle_t *dh = NULL;
  csync_vio_file_stat_t *dirent = NULL;
  csync_vio_file_stat_t *fs = NULL;
  int rc = 0;

  if (uri[0] == '\0') {
    errno = ENOENT;
    goto error;
  }

  if ((dh = csync_vio_opendir(ctx, uri)) == NULL) {
    /* permission denied */
    if (errno == EACCES) {
      return 0;
    } else {
      CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
          "opendir failed for %s - %s",
          uri,
          strerror_r(errno, errbuf, sizeof(errbuf)));
      goto error;
    }
  }

  while ((dirent = csync_vio_readdir(ctx, dh))) {
    const char *path = NULL;
    int flag;

    d_name = dirent->name;
    if (d_name == NULL) {
      goto error;
    }

    /* skip "." and ".." */
    if (d_name[0] == '.' && (d_name[1] == '\0'
          || (d_name[1] == '.' && d_name[2] == '\0'))) {
      csync_vio_file_stat_destroy(dirent);
      dirent = NULL;
      continue;
    }

    if (asprintf(&filename, "%s/%s", uri, d_name) < 0) {
      csync_vio_file_stat_destroy(dirent);
      dirent = NULL;
      goto error;
    }

    /* Create relative path for checking the exclude list */
    switch (ctx->current) {
      case LOCAL_REPLICA:
        path = filename + strlen(ctx->local.uri) + 1;
        break;
      case REMOTE_REPLCIA:
        path = filename + strlen(ctx->remote.uri) + 1;
        break;
      default:
        break;
    }

    /* Check if file is excluded */
    if (csync_excluded(ctx, path)) {
      CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded", path);
      csync_vio_file_stat_destroy(dirent);
      dirent = NULL;
      continue;
    }

    fs = csync_vio_file_stat_new();
    if (csync_vio_stat(ctx, filename, fs) == 0) {
      switch (fs->type) {
        case CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK:
          flag = CSYNC_FTW_FLAG_SLINK;
          break;
        case CSYNC_VIO_FILE_TYPE_DIRECTORY:
          flag = CSYNC_FTW_FLAG_DIR;
          break;
        case CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE:
        case CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE:
        case CSYNC_VIO_FILE_TYPE_SOCKET:
          flag = CSYNC_FTW_FLAG_SPEC;
          break;
        case CSYNC_VIO_FILE_TYPE_FIFO:
          flag = CSYNC_FTW_FLAG_SPEC;
          break;
        default:
          flag = CSYNC_FTW_FLAG_FILE;
          break;
      };
    } else {
      flag = CSYNC_FTW_FLAG_NSTAT;
    }

    CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "walk: %s", filename);

    /* Call walker function for each file */
    rc = fn(ctx, filename, fs, flag);
    csync_vio_file_stat_destroy(fs);

    if (rc < 0) {
      csync_vio_closedir(ctx, dh);
      goto done;
    }

    if (flag == CSYNC_FTW_FLAG_DIR && depth) {
      rc = csync_ftw(ctx, filename, fn, depth - 1);
      if (rc < 0) {
        csync_vio_closedir(ctx, dh);
        goto done;
      }
    }
    SAFE_FREE(filename);
    csync_vio_file_stat_destroy(dirent);
    dirent = NULL;
  }
  csync_vio_closedir(ctx, dh);

done:
  csync_vio_file_stat_destroy(dirent);
  SAFE_FREE(filename);
  return rc;
error:
  SAFE_FREE(filename);
  return -1;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
static const char* owncloud_get_etag( const char *path )
{
    ne_request *req    = NULL;
    const char *header = NULL;
    char *uri          = _cleanPath(path);
    char *cbuf   = NULL;
    csync_vio_file_stat_t *fs = NULL;
    bool doHeadRequest = false;

    if (_id_cache.uri && c_streq(path, _id_cache.uri)) {
        header = _id_cache.id;
    }

    doHeadRequest= false; /* ownCloud server doesn't have good support for HEAD yet */

    if( !header && doHeadRequest ) {
        int neon_stat;
        /* Perform an HEAD request to the resource. HEAD delivers the
         * ETag header back. */
        req = ne_request_create(dav_session.ctx, "HEAD", uri);
        neon_stat = ne_request_dispatch(req);
        set_errno_from_neon_errcode( neon_stat );

        header = ne_get_response_header(req, "etag");
    }
    /* If the request went wrong or the server did not respond correctly
     * (that can happen for collections) a stat call is done which translates
     * into a PROPFIND request.
     */
    if( ! header ) {
        /* ... and do a stat call. */
        fs = csync_vio_file_stat_new();
        if(fs == NULL) {
            DEBUG_WEBDAV( "owncloud_get_etag: memory fault.");
            errno = ENOMEM;
            return NULL;
        }
        if( owncloud_stat( path, fs ) == 0 ) {
            header = fs->etag;
        }
    }

    /* In case the result is surrounded by "" cut them away. */
    if( header ) {
        cbuf = csync_normalize_etag(header);
    }

    /* fix server problem: If we end up with an empty string, set something strange... */
    if( c_streq(cbuf, "") || c_streq(cbuf, "\"\"") ) {
        SAFE_FREE(cbuf);
        cbuf = c_strdup("empty_etag");
    }

    DEBUG_WEBDAV("Get file ID for %s: %s", path, cbuf ? cbuf:"<null>");
    if( fs ) csync_vio_file_stat_destroy(fs);
    if( req ) ne_request_destroy(req);
    SAFE_FREE(uri);


    return cbuf;
}