コード例 #1
0
ファイル: check_std_c_path.c プロジェクト: Absolight/mirall
static void check_c_basename_uri(void **state)
{
    char *bname = NULL;

    (void) state; /* unused */

    bname = c_basename("smb://server/share/dir/");
    assert_string_equal(bname, "dir");
    free(bname);
}
コード例 #2
0
ファイル: check_std_c_path.c プロジェクト: Absolight/mirall
static void check_c_basename(void **state)
{
    char *bname;

    (void) state; /* unused */

    bname = c_basename("/usr/lib");
    assert_string_equal(bname, "lib");
    free(bname);

    bname = c_basename("/usr//");
    assert_string_equal(bname, "usr");
    free(bname);

    bname = c_basename("usr");
    assert_string_equal(bname, "usr");
    free(bname);

    bname = c_basename("///");
    assert_string_equal(bname, "/");
    free(bname);

    bname = c_basename("/");
    assert_string_equal(bname, "/");
    free(bname);

    bname = c_basename(".");
    assert_string_equal(bname, ".");
    free(bname);

    bname = c_basename("..");
    assert_string_equal(bname, "..");
    free(bname);

    bname = c_basename("");
    assert_string_equal(bname, ".");
    free(bname);

    bname = c_basename(NULL);
    assert_string_equal(bname, ".");
    free(bname);
}
コード例 #3
0
ファイル: csync_dummy.c プロジェクト: MarkusLitz/csync
static int dummy_stat(const char *uri, csync_vio_file_stat_t *buf) {
  time_t now;

  buf->name = c_basename(uri);
  if (buf->name == NULL) {
    csync_vio_file_stat_destroy(buf);
  }
  buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;

  time(&now);
  buf->mtime = now;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;

  return 0;
}
コード例 #4
0
ファイル: csync_vio_local.c プロジェクト: goesaditya/mirall
int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
  csync_stat_t sb;

  mbchar_t *wuri = c_utf8_to_locale( uri );

  if( _tstat(wuri, &sb) < 0) {
    c_free_locale_string(wuri);
    return -1;
  }

  buf->name = c_basename(uri);

  if (buf->name == NULL) {
    csync_vio_file_stat_destroy(buf);
    c_free_locale_string(wuri);
    return -1;
  }
  buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;

  switch(sb.st_mode & S_IFMT) {
    case S_IFBLK:
      buf->type = CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE;
      break;
    case S_IFCHR:
      buf->type = CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE;
      break;
    case S_IFDIR:
      buf->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
      break;
    case S_IFIFO:
      buf->type = CSYNC_VIO_FILE_TYPE_FIFO;
      break;
    case S_IFREG:
      buf->type = CSYNC_VIO_FILE_TYPE_REGULAR;
      break;
    case S_IFLNK:
      buf->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
      break;
    case S_IFSOCK:
      buf->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
      break;
    default:
      buf->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
      break;
  }
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;

  buf->mode = sb.st_mode;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MODE;

  if (buf->type == CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK) {
    /* FIXME: handle symlink */
    buf->flags = CSYNC_VIO_FILE_FLAGS_SYMLINK;
  } else {
    buf->flags = CSYNC_VIO_FILE_FLAGS_NONE;
  }
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;

  buf->device = sb.st_dev;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DEVICE;

  buf->inode = sb.st_ino;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE;

  buf->atime = sb.st_atime;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;

  buf->mtime = sb.st_mtime;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;

  buf->ctime = sb.st_ctime;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME;

  buf->nlink = sb.st_nlink;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT;

  buf->size = sb.st_size;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;

  c_free_locale_string(wuri);
  return 0;
}
コード例 #5
0
ファイル: csync_exclude.c プロジェクト: gco/csync
int csync_excluded(CSYNC *ctx, const char *path) {
  size_t i;
  const char *p;
  char *bname;
  int rc;
  int match = 0;

  if (! ctx->options.unix_extensions) {
    for (p = path; *p; p++) {
      switch (*p) {
        case '\\':
        case ':':
        case '?':
        case '*':
        case '"':
        case '>':
        case '<':
        case '|':
          return 1;
        default:
          break;
      }
    }
  }

  rc = csync_fnmatch(".csync_journal.db*", path, 0);
  if (rc == 0) {
      return 1;
  }

  bname = c_basename(path);
  if (bname == NULL) {
      return 0;
  }

  rc = csync_fnmatch(".csync_journal.db*", bname, 0);
  if (rc == 0) {
      match = 1;
      goto out;
  }

  if (ctx->excludes == NULL) {
      goto out;
  }

  for (i = 0; match == 0 && i < ctx->excludes->count; i++) {
      rc = csync_fnmatch(ctx->excludes->vector[i], path, 0);
      if (rc == 0) {
          match = 1;
      }

      rc = csync_fnmatch(ctx->excludes->vector[i], bname, 0);
      if (rc == 0) {
          match = 1;
      }
  }

out:
  free(bname);
  return match;
}
コード例 #6
0
ファイル: csync_config.c プロジェクト: alexta901/mirall
int csync_config_parse_file(CSYNC *ctx, const char *config)
{
    unsigned int count = 0;
    char line[1024] = {0};
    char *s;
    FILE *f;

    /* copy default config, if no config exists */
    if (! c_isfile(config)) {
        /* check if there is still one csync.conf left over in $HOME/.csync
        * and copy it over (migration path)
        */
        char *home = NULL;
        char *home_config = NULL;
        char *config_file = NULL;

        /* there is no statedb at the expected place. */
        home = csync_get_user_home_dir();
        if( !c_streq(home, ctx->options.config_dir) ) {
            int rc = -1;

            config_file = c_basename(config);
            if( config_file ) {
                rc = asprintf(&home_config, "%s/%s/%s", home, CSYNC_CONF_DIR, config_file);
                SAFE_FREE(config_file);
            }

            if (rc >= 0) {
                CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "config file %s not found, checking %s",
                            config, home_config);

                /* check the home file and copy to new statedb if existing. */
                if(c_isfile(home_config)) {
                    if (c_copy(home_config, config, 0644) < 0) {
                        /* copy failed, but that is not reason to die. */
                        CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Could not copy config %s => %s",
                                    home_config, config);
                    } else {
                        CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "Copied %s => %s",
                                    home_config, config);
                    }
                }
            }
            SAFE_FREE(home_config);
        }
        SAFE_FREE(home);
        /* Still install the default one if nothing is there. */
        if( ! c_isfile(config)) {
            if (_csync_config_copy_default(config) < 0) {
                return -1;
            }
        }
    }

    f = fopen(config, "r");
    if (f == NULL) {
        return 0;
    }

    CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
            "Reading configuration data from %s",
            config);

    s = fgets(line, sizeof(line), f);
    while (s != NULL) {
        int rc;
        count++;

        rc = csync_config_parse_line(ctx, line, count);
        if (rc < 0) {
            fclose(f);
            return -1;
        }
        s = fgets(line, sizeof(line), f);
    }

    fclose(f);

    return 0;
}
コード例 #7
0
ファイル: csync_smb.c プロジェクト: MarkusLitz/csync
static int _stat(const char *uri, csync_vio_file_stat_t *buf) {
  struct stat sb;

  if (smbc_stat(uri, &sb) < 0) {
    return -1;
  }

  buf->name = c_basename(uri);
  if (buf->name == NULL) {
    csync_vio_file_stat_destroy(buf);
    return -1;
  }
  buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;

  switch(sb.st_mode & S_IFMT) {
    case S_IFBLK:
      buf->type = CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE;
      break;
    case S_IFCHR:
      buf->type = CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE;
      break;
    case S_IFDIR:
      buf->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
      break;
    case S_IFIFO:
      buf->type = CSYNC_VIO_FILE_TYPE_FIFO;
      break;
    case S_IFLNK:
      buf->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
      break;
    case S_IFREG:
      buf->type = CSYNC_VIO_FILE_TYPE_REGULAR;
      break;
    case S_IFSOCK:
      buf->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
    default:
      buf->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
      break;
  }
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;

  buf->mode = sb.st_mode;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;

  if (buf->type == CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK) {
    /* FIXME: handle symlink */
    buf->flags = CSYNC_VIO_FILE_FLAGS_SYMLINK;
  } else {
    buf->flags = CSYNC_VIO_FILE_FLAGS_NONE;
  }
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;

  buf->device = sb.st_dev;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_DEVICE;

  buf->inode = sb.st_ino;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE;

  buf->nlink = sb.st_nlink;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_LINK_COUNT;

  buf->uid = sb.st_uid;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_UID;

  buf->gid = sb.st_gid;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_GID;

  buf->size = sb.st_size;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;

  buf->blksize = sb.st_blksize;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_SIZE;

  buf->blkcount = sb.st_blocks;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_BLOCK_COUNT;

  buf->atime = sb.st_atime;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;

  buf->mtime = sb.st_mtime;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;

  buf->ctime = sb.st_ctime;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME;

  return 0;
}
コード例 #8
0
ファイル: csync_exclude.c プロジェクト: DeepDiver1975/mirall
CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) {
  size_t i = 0;
  const char *p = NULL;
  char *bname = NULL;
  char *dname = NULL;
  char *prev_dname = NULL;
  char *conflict = NULL;
  int rc = -1;
  CSYNC_EXCLUDE_TYPE match = CSYNC_NOT_EXCLUDED;
  CSYNC_EXCLUDE_TYPE type  = CSYNC_NOT_EXCLUDED;

    for (p = path; *p; p++) {
      switch (*p) {
        case '\\':
        case ':':
        case '?':
        case '*':
        case '"':
        case '>':
        case '<':
        case '|':
          return CSYNC_FILE_EXCLUDE_INVALID_CHAR;
        default:
          break;
      }
    }

  /* split up the path */
  dname = c_dirname(path);
  bname = c_basename(path);

  if (bname == NULL || dname == NULL) {
      match = CSYNC_NOT_EXCLUDED;
      SAFE_FREE(bname);
      SAFE_FREE(dname);
      goto out;
  }

  rc = csync_fnmatch(".csync_journal.db*", bname, 0);
  if (rc == 0) {
      match = CSYNC_FILE_SILENTLY_EXCLUDED;
      SAFE_FREE(bname);
      SAFE_FREE(dname);
      goto out;
  }

  rc = csync_fnmatch(".owncloudsync.log*", bname, 0);
  if (rc == 0) {
      match = CSYNC_FILE_SILENTLY_EXCLUDED;
      SAFE_FREE(bname);
      SAFE_FREE(dname);
      goto out;
  }

  /* Always ignore conflict files, not only via the exclude list */
  rc = csync_fnmatch("*_conflict-*", bname, 0);
  if (rc == 0) {
      match = CSYNC_FILE_SILENTLY_EXCLUDED;
      SAFE_FREE(bname);
      SAFE_FREE(dname);
      goto out;
  }

  if (getenv("CSYNC_CONFLICT_FILE_USERNAME")) {
      asprintf(&conflict, "*_conflict_%s-*", getenv("CSYNC_CONFLICT_FILE_USERNAME"));
      rc = csync_fnmatch(conflict, path, 0);
      if (rc == 0) {
          match = CSYNC_FILE_SILENTLY_EXCLUDED;
          SAFE_FREE(conflict);
          SAFE_FREE(bname);
          SAFE_FREE(dname);
          goto out;
      }
      SAFE_FREE(conflict);
  }

  SAFE_FREE(bname);
  SAFE_FREE(dname);

  if (ctx->excludes == NULL) {
      goto out;
  }

  /* Loop over all exclude patterns and evaluate the given path */
  for (i = 0; match == CSYNC_NOT_EXCLUDED && i < ctx->excludes->count; i++) {
      bool match_dirs_only = false;
      char *pattern_stored = c_strdup(ctx->excludes->vector[i]);
      char* pattern = pattern_stored;

      type = CSYNC_FILE_EXCLUDE_LIST;
      if (strlen(pattern) < 1) {
          continue;
      }
      /* Ecludes starting with ']' means it can be cleanup */
      if (pattern[0] == ']') {
          ++pattern;
          if (filetype == CSYNC_FTW_TYPE_FILE) {
              type = CSYNC_FILE_EXCLUDE_AND_REMOVE;
          }
      }
      /* Check if the pattern applies to pathes only. */
      if (pattern[strlen(pattern)-1] == '/') {
          match_dirs_only = true;
          pattern[strlen(pattern)-1] = '\0'; /* Cut off the slash */
      }

      /* check if the pattern contains a / and if, compare to the whole path */
      if (strchr(pattern, '/')) {
          rc = csync_fnmatch(pattern, path, FNM_PATHNAME);
          if( rc == 0 ) {
              match = type;
          }
          /* if the pattern requires a dir, but path is not, its still not excluded. */
          if (match_dirs_only && filetype != CSYNC_FTW_TYPE_DIR) {
              match = CSYNC_NOT_EXCLUDED;
          }
      }

      /* if still not excluded, check each component of the path */
      if (match == CSYNC_NOT_EXCLUDED) {
          int trailing_component = 1;
          dname = c_dirname(path);
          bname = c_basename(path);

          if (bname == NULL || dname == NULL) {
              match = CSYNC_NOT_EXCLUDED;
              goto out;
          }

          /* Check each component of the path */
          do {
              /* Do not check the bname if its a file and the pattern matches dirs only. */
              if ( !(trailing_component == 1 /* it is the trailing component */
                     && match_dirs_only      /* but only directories are matched by the pattern */
                     && filetype == CSYNC_FTW_TYPE_FILE) ) {
                  /* Check the name component against the pattern */
                  rc = csync_fnmatch(pattern, bname, 0);
                  if (rc == 0) {
                      match = type;
                  }
              }
              if (!(c_streq(dname, ".") || c_streq(dname, "/"))) {
                  rc = csync_fnmatch(pattern, dname, 0);
                  if (rc == 0) {
                      match = type;
                  }
              }
              trailing_component = 0;
              prev_dname = dname;
              SAFE_FREE(bname);
              bname = c_basename(prev_dname);
              dname = c_dirname(prev_dname);
              SAFE_FREE(prev_dname);

          } while( match == CSYNC_NOT_EXCLUDED && !c_streq(dname, ".")
                     && !c_streq(dname, "/") );
      }
      SAFE_FREE(pattern_stored);
      SAFE_FREE(bname);
      SAFE_FREE(dname);
  }

out:

  return match;
}
コード例 #9
0
ファイル: csync_owncloud.c プロジェクト: gco/csync
/*
 * file functions
 */
static int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) {
    /* get props:
     *   modtime
     *   creattime
     *   size
     */
    int rc = 0;
    csync_vio_file_stat_t *lfs = NULL;
    struct listdir_context  *fetchCtx = NULL;
    char *curi = NULL;
    char *decodedUri = NULL;
    char strbuf[PATH_MAX +1];
    int len = 0;

    DEBUG_WEBDAV("owncloud_stat %s called", uri );

    buf->name = c_basename(uri);

    if (buf->name == NULL) {
        csync_vio_file_stat_destroy(buf);
        errno = ENOMEM;
        return -1;
    }

    /* check if the data in the static 'cache' fs is for the same file.
     * The cache is filled by readdir which is often called directly before
     * stat. If the cache matches, a http call is saved.
     */
    if( _fs.name && strcmp( buf->name, _fs.name ) == 0 ) {
        buf->fields  = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
        buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
        buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
        buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
        buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;

        buf->fields = _fs.fields;
        buf->type   = _fs.type;
        buf->mtime  = _fs.mtime;
        buf->size   = _fs.size;
        buf->mode   = _stat_perms( _fs.type );
    } else {
        /* fetch data via a propfind call. */
        fetchCtx = c_malloc( sizeof( struct listdir_context ));
        if( ! fetchCtx ) {
            errno = ENOMEM;
            return -1;
        }

        curi = _cleanPath( uri );

        DEBUG_WEBDAV("I have no stat cache, call propfind for %s.", curi );
        fetchCtx->list = NULL;
        fetchCtx->target = curi;
        fetchCtx->include_target = 1;
        fetchCtx->currResource = NULL;

        rc = fetch_resource_list( curi, NE_DEPTH_ONE, fetchCtx );
        if( rc != NE_OK ) {
          if( errno != ENOENT ) {
            set_errno_from_session();
          }
          DEBUG_WEBDAV("stat fails with errno %d", errno );

          return -1;
        }

        if( fetchCtx ) {
            struct resource *res = fetchCtx->list;
            while( res ) {
                /* remove trailing slashes */
                len = strlen(res->uri);
                while( len > 0 && res->uri[len-1] == '/' ) --len;
                memset( strbuf, 0, PATH_MAX+1);
                strncpy( strbuf, res->uri, len < PATH_MAX ? len : PATH_MAX );
                decodedUri = ne_path_unescape( curi ); /* allocates memory */
                if( c_streq(strbuf, decodedUri )) {
                    SAFE_FREE( decodedUri );
                    break;
                }
                res = res->next;
                SAFE_FREE( decodedUri );
            }
            DEBUG_WEBDAV("Working on file %s", res ? res->name : "NULL");

            lfs = resourceToFileStat( res );
            if( lfs ) {
                buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
                buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
                buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
                buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
                buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;

                buf->fields = lfs->fields;
                buf->type   = lfs->type;
                buf->mtime  = lfs->mtime;
                buf->size   = lfs->size;
                buf->mode   = _stat_perms( lfs->type );

                csync_vio_file_stat_destroy( lfs );
            }
            SAFE_FREE( fetchCtx );
        }
    }
    DEBUG_WEBDAV("STAT result: %s, type=%d", buf->name ? buf->name:"NULL",
                  buf->type );
    return 0;
}
コード例 #10
0
ファイル: csync_owncloud.c プロジェクト: gco/csync
/*
 * result parsing list.
 * This function is called to parse the result of the propfind request
 * to list directories on the WebDAV server. I takes a single resource
 * and fills a resource struct and stores it to the result list which
 * is stored in the listdir_context.
 */
static void results(void *userdata,
                    const ne_uri *uri,
                    const ne_prop_result_set *set)
{
    struct listdir_context *fetchCtx = userdata;
    struct resource *newres = 0;
    const char *clength, *modtime = NULL;
    const char *resourcetype = NULL;
    const ne_status *status = NULL;
    char *path = ne_path_unescape( uri->path );

    (void) status;
    if( ! fetchCtx ) {
        DEBUG_WEBDAV("No valid fetchContext");
        return;
    }

    DEBUG_WEBDAV("** propfind result found: %s", path );
    if( ! fetchCtx->target ) {
        DEBUG_WEBDAV("error: target must not be zero!" );
        return;
    }

    if (ne_path_compare(fetchCtx->target, uri->path) == 0 && !fetchCtx->include_target) {
        /* This is the target URI */
        DEBUG_WEBDAV( "Skipping target resource.");
        /* Free the private structure. */
        SAFE_FREE( path );
        return;
    }

    /* Fill the resource structure with the data about the file */
    newres = c_malloc(sizeof(struct resource));
    newres->uri =  path; /* no need to strdup because ne_path_unescape already allocates */
    newres->name = c_basename( path );

    modtime      = ne_propset_value( set, &ls_props[0] );
    clength      = ne_propset_value( set, &ls_props[1] );
    resourcetype = ne_propset_value( set, &ls_props[2] );

    newres->type = resr_normal;
    if( clength == NULL && resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
        newres->type = resr_collection;
    }

    if (modtime)
        newres->modtime = ne_httpdate_parse(modtime);

    if (clength) {
        char *p;

        newres->size = DAV_STRTOL(clength, &p, 10);
        if (*p) {
            newres->size = 0;
        }
    }

    /* prepend the new resource to the result list */
    newres->next   = fetchCtx->list;
    fetchCtx->list = newres;
    fetchCtx->result_count = fetchCtx->result_count + 1;
    DEBUG_WEBDAV( "results for URI %s: %d %d", newres->name, (int)newres->size, (int)newres->type );
}
コード例 #11
0
static void propfind_results_recursive(void *userdata,
                    const ne_uri *uri,
                    const ne_prop_result_set *set)
{
    struct resource *newres = 0;
    const char *clength, *modtime, *file_id = NULL;
    const char *resourcetype = NULL;
    const char *md5sum = NULL;
    const ne_status *status = NULL;
    char *path = ne_path_unescape( uri->path );
    char *parentPath;
    char *propfindRootUri = (char*) userdata;
    propfind_recursive_element_t *element = NULL;
    propfind_recursive_element_t *pElement = NULL;
    int depth = 0;

    (void) status;
    (void) propfindRootUri;

    if (!propfind_recursive_cache) {
        c_rbtree_create(&propfind_recursive_cache, _key_cmp, _data_cmp);
    }

    /* Fill the resource structure with the data about the file */
    newres = c_malloc(sizeof(struct resource));
    ZERO_STRUCTP(newres);

    newres->uri =  path; /* no need to strdup because ne_path_unescape already allocates */
    newres->name = c_basename( path );

    modtime      = ne_propset_value( set, &ls_props[0] );
    clength      = ne_propset_value( set, &ls_props[1] );
    resourcetype = ne_propset_value( set, &ls_props[2] );
    md5sum       = ne_propset_value( set, &ls_props[3] );
    file_id      = ne_propset_value( set, &ls_props[4] );

    newres->type = resr_normal;
    if( resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
        newres->type = resr_collection;
        propfind_recursive_cache_folder_count++;
    } else {
        /* DEBUG_WEBDAV("propfind_results_recursive %s [%d]", newres->uri, newres->type); */
        propfind_recursive_cache_file_count++;
    }

    if (modtime) {
        newres->modtime = oc_httpdate_parse(modtime);
    }

    /* DEBUG_WEBDAV("Parsing Modtime: %s -> %llu", modtime, (unsigned long long) newres->modtime ); */
    newres->size = 0;
    if (clength) {
        newres->size = atoll(clength);
        /* DEBUG_WEBDAV("Parsed File size for %s from %s: %lld", newres->name, clength, (long long)newres->size ); */
    }

    if( md5sum ) {
        newres->md5 = csync_normalize_etag(md5sum);
    }

    csync_vio_set_file_id(newres->file_id, file_id);
    /*
    DEBUG_WEBDAV("propfind_results_recursive %s [%s] %s", newres->uri, newres->type == resr_collection ? "collection" : "file", newres->md5);
    */

    /* Create new item in rb tree */
    if (newres->type == resr_collection) {
        DEBUG_WEBDAV("propfind_results_recursive %s is a folder", newres->uri);
        /* Check if in rb tree */
        element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,uri->path));
        /* If not, create a new item and insert it */
        if (!element) {
            element = c_malloc(sizeof(propfind_recursive_element_t));
            element->self = resource_dup(newres);
            element->children = NULL;
            element->parent = NULL;
            c_rbtree_insert(propfind_recursive_cache, element);
            /* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */
        }
    }

    /* Check for parent in tree. If exists: Insert it into the children elements there */
    parentPath = ne_path_parent(uri->path);
    if (parentPath) {
        propfind_recursive_element_t *parentElement = NULL;

        parentElement = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,parentPath));
        free(parentPath);

        if (parentElement) {
            newres->next = parentElement->children;
            parentElement->children = newres;

            /* If the current result is a collection we also need to set its parent */
            if (element)
                element->parent = parentElement;

            pElement = element;
            while (pElement) {
                depth++;
                pElement = pElement->parent;
            }
            if (depth > propfind_recursive_cache_depth) {
                DEBUG_WEBDAV("propfind_results_recursive %s new maximum tree depth %d", newres->uri, depth);
                propfind_recursive_cache_depth = depth;
            }

            /* DEBUG_WEBDAV("results_recursive Added child %s to collection %s", newres->uri, element->self->uri); */
        } else {
            /* DEBUG_WEBDAV("results_recursive No parent %s found for child %s", parentPath, newres->uri); */
            resource_free(newres);
            newres = NULL;
        }
    }

}
コード例 #12
0
ファイル: csync_sftp.c プロジェクト: MarkusLitz/csync
static int _sftp_stat(const char *uri, csync_vio_file_stat_t *buf) {
  sftp_attributes attrs;
  char *path = NULL;
  int rc = -1;

  if (_sftp_connect(uri) < 0) {
    return -1;
  }

  if (c_parse_uri(uri, NULL, NULL, NULL, NULL, NULL, &path) < 0) {
    return -1;
  }

  attrs = sftp_lstat(_sftp_session, path);
  if (attrs == NULL) {
    rc = -1;
    goto out;
  }

  buf->name = c_basename(path);
  if (buf->name == NULL) {
    csync_vio_file_stat_destroy(buf);
    goto out;
  }
  buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;

  switch (attrs->type) {
    case SSH_FILEXFER_TYPE_REGULAR:
      buf->type = CSYNC_VIO_FILE_TYPE_REGULAR;
      break;
    case SSH_FILEXFER_TYPE_DIRECTORY:
      buf->type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
      break;
    case SSH_FILEXFER_TYPE_SYMLINK:
      buf->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
      break;
    case SSH_FILEXFER_TYPE_SPECIAL:
    case SSH_FILEXFER_TYPE_UNKNOWN:
      buf->type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
      break;
  }
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;

  buf->mode = attrs->permissions;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;

  if (buf->type == CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK) {
    /* FIXME: handle symlink */
    buf->flags = CSYNC_VIO_FILE_FLAGS_SYMLINK;
  } else {
    buf->flags = CSYNC_VIO_FILE_FLAGS_NONE;
  }
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FLAGS;

  buf->uid = attrs->uid;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_UID;

  buf->uid = attrs->gid;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_GID;

  buf->size = attrs->size;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;

  buf->atime = attrs->atime;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME;

  buf->mtime = attrs->mtime;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;

  buf->ctime = attrs->createtime;
  buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME;

  rc = 0;
out:
  if (rc < 0) {
    errno = _sftp_portable_to_errno(sftp_get_error(_sftp_session));
  }
  SAFE_FREE(path);
  sftp_attributes_free(attrs);

  return rc;
}
コード例 #13
0
static void propfind_results_recursive_callback(void *userdata,
                    const ne_uri *uri,
                    const ne_prop_result_set *set)
{
    struct resource *newres = 0;

    const ne_status *status = NULL;
    char *path = ne_path_unescape( uri->path );
    char *parentPath;
    propfind_recursive_element_t *element = NULL;
    propfind_recursive_element_t *pElement = NULL;
    int depth = 0;
    csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata;


    (void) status;

    if (!ctx->propfind_recursive_cache) {
        c_rbtree_create(&ctx->propfind_recursive_cache, _key_cmp, _data_cmp);
    }

    /* Fill the resource structure with the data about the file */
    newres = c_malloc(sizeof(struct resource));

    newres->uri =  path; /* no need to strdup because ne_path_unescape already allocates */
    newres->name = c_basename( path );
    fill_webdav_properties_into_resource(newres, set);

    if( newres->type == resr_collection) {
        ctx->propfind_recursive_cache_folder_count++;
    } else {
        ctx->propfind_recursive_cache_file_count++;
    }

    /* Create new item in rb tree */
    if (newres->type == resr_collection) {
        DEBUG_WEBDAV("propfind_results_recursive %s is a folder", newres->uri);
        /* Check if in rb tree */
        element = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache,uri->path));
        /* If not, create a new item and insert it */
        if (!element) {
            element = c_malloc(sizeof(propfind_recursive_element_t));
            element->self = resource_dup(newres);
            element->self->next = 0;
            element->children = NULL;
            element->parent = NULL;
            c_rbtree_insert(ctx->propfind_recursive_cache, element);
            /* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */
        }
    }

    /* Check for parent in tree. If exists: Insert it into the children elements there */
    parentPath = ne_path_parent(uri->path);
    if (parentPath) {
        propfind_recursive_element_t *parentElement = NULL;

        parentElement = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache,parentPath));
        free(parentPath);

        if (parentElement) {
            newres->next = parentElement->children;
            parentElement->children = newres;

            /* If the current result is a collection we also need to set its parent */
            if (element)
                element->parent = parentElement;

            pElement = element;
            while (pElement) {
                depth++;
                pElement = pElement->parent;
            }
            if (depth > ctx->propfind_recursive_cache_depth) {
                DEBUG_WEBDAV("propfind_results_recursive %s new maximum tree depth %d", newres->uri, depth);
                ctx->propfind_recursive_cache_depth = depth;
            }

            /* DEBUG_WEBDAV("results_recursive Added child %s to collection %s", newres->uri, element->self->uri); */
            return;
        }
    }

    resource_free(newres);
    newres = NULL;
}
コード例 #14
0
ファイル: csync_owncloud.c プロジェクト: liusijiang/mirall
/*
 * file functions
 */
int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) {
    /* get props:
     *   modtime
     *   creattime
     *   size
     */
    csync_vio_file_stat_t *lfs = NULL;
    struct listdir_context  *fetchCtx = NULL;
    char *decodedUri = NULL;
    int len = 0;
    errno = 0;

    DEBUG_WEBDAV("owncloud_stat %s called", uri );

    buf->name = c_basename(uri);

    if (buf->name == NULL) {
        errno = ENOMEM;
        return -1;
    }

    if( _stat_cache.name && strcmp( buf->name, _stat_cache.name ) == 0 ) {
        buf->fields  = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
        buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
        buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
        buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
        buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;
        buf->fields  = _stat_cache.fields;
        buf->type    = _stat_cache.type;
        buf->mtime   = _stat_cache.mtime;
        buf->size    = _stat_cache.size;
        buf->mode    = _stat_perms( _stat_cache.type );
        buf->etag     = NULL;
        if( _stat_cache.etag ) {
            buf->etag    = c_strdup( _stat_cache.etag );
            buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;
        }
        csync_vio_file_stat_set_file_id( buf, _stat_cache.file_id );
        return 0;
    }
    DEBUG_WEBDAV("owncloud_stat => Could not find in stat cache %s", uri);

    /* fetch data via a propfind call. */
    /* fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE); */
    fetchCtx = fetch_resource_list_attempts( uri, NE_DEPTH_ONE);
    DEBUG_WEBDAV("=> Errno after fetch resource list for %s: %d", uri, errno);
    if (!fetchCtx) {
        return -1;
    }

    if( fetchCtx ) {
        struct resource *res = fetchCtx->list;
        while( res ) {
            /* remove trailing slashes */
            len = strlen(res->uri);
            while( len > 0 && res->uri[len-1] == '/' ) --len;
            decodedUri = ne_path_unescape( fetchCtx->target ); /* allocates memory */

            /* Only do the comparaison of the part of the string without the trailing
               slashes, and make sure decodedUri is not too large */
            if( strncmp(res->uri, decodedUri, len ) == 0 && decodedUri[len] == '\0') {
                SAFE_FREE( decodedUri );
                break;
            }
            res = res->next;
            SAFE_FREE( decodedUri );
        }
        if( res ) {
            DEBUG_WEBDAV("Working on file %s", res->name );
        } else {
            DEBUG_WEBDAV("ERROR: Result struct not valid!");
        }

        lfs = resourceToFileStat( res );
        if( lfs ) {
            buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
            buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE;
            buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
            buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
            buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;
            buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG;

            buf->fields = lfs->fields;
            buf->type   = lfs->type;
            buf->mtime  = lfs->mtime;
            buf->size   = lfs->size;
            buf->mode   = _stat_perms( lfs->type );
            buf->etag    = NULL;
            if( lfs->etag ) {
                buf->etag    = c_strdup( lfs->etag );
            }
            csync_vio_file_stat_set_file_id( buf, lfs->file_id );

            /* fill the static stat buf as input for the stat function */
            csync_vio_file_stat_destroy( lfs );
        }

        free_fetchCtx( fetchCtx );
    }
    DEBUG_WEBDAV("STAT result from propfind: %s, mtime: %llu", buf->name ? buf->name:"NULL",
                    (unsigned long long) buf->mtime );

    return 0;
}
コード例 #15
0
ファイル: csync_owncloud.c プロジェクト: liusijiang/mirall
/*
 * result parsing list.
 * This function is called to parse the result of the propfind request
 * to list directories on the WebDAV server. I takes a single resource
 * and fills a resource struct and stores it to the result list which
 * is stored in the listdir_context.
 */
static void results(void *userdata,
                    const ne_uri *uri,
                    const ne_prop_result_set *set)
{
    struct listdir_context *fetchCtx = userdata;
    struct resource *newres = 0;
    const char *clength, *modtime = NULL;
    const char *resourcetype = NULL;
    const char *md5sum = NULL;
    const char *file_id = NULL;
    const ne_status *status = NULL;
    char *path = ne_path_unescape( uri->path );

    (void) status;
    if( ! fetchCtx ) {
        DEBUG_WEBDAV("No valid fetchContext");
        return;
    }

    if( ! fetchCtx->target ) {
        DEBUG_WEBDAV("error: target must not be zero!" );
        return;
    }

    /* Fill the resource structure with the data about the file */
    newres = c_malloc(sizeof(struct resource));
    ZERO_STRUCTP(newres);
    newres->uri =  path; /* no need to strdup because ne_path_unescape already allocates */
    newres->name = c_basename( path );

    modtime      = ne_propset_value( set, &ls_props[0] );
    clength      = ne_propset_value( set, &ls_props[1] );
    resourcetype = ne_propset_value( set, &ls_props[2] );
    md5sum       = ne_propset_value( set, &ls_props[3] );
    file_id      = ne_propset_value( set, &ls_props[4] );

    newres->type = resr_normal;
    if( clength == NULL && resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
        newres->type = resr_collection;
    }

    if (modtime) {
        newres->modtime = oc_httpdate_parse(modtime);
    }

    /* DEBUG_WEBDAV("Parsing Modtime: %s -> %llu", modtime, (unsigned long long) newres->modtime ); */
    newres->size = 0;
    if (clength) {
        newres->size = atoll(clength);
        /* DEBUG_WEBDAV("Parsed File size for %s from %s: %lld", newres->name, clength, (long long)newres->size ); */
    }

    if( md5sum ) {
        newres->md5 = csync_normalize_etag(md5sum);
    }

    csync_vio_set_file_id(newres->file_id, file_id);

    /* prepend the new resource to the result list */
    newres->next   = fetchCtx->list;
    fetchCtx->list = newres;
    fetchCtx->result_count = fetchCtx->result_count + 1;
    /* DEBUG_WEBDAV( "results for URI %s: %d %d", newres->name, (int)newres->size, (int)newres->type ); */
}