Exemple #1
0
/* parse an expression term. It can be one of:
 * "term"
 * ["term" <parameters>]
 */
w_query_expr *w_query_expr_parse(w_query *query, json_t *exp)
{
  w_string_t *name;
  w_query_expr_parser parser;

  if (json_is_string(exp)) {
    name = w_string_new(json_string_value(exp));
  } else if (json_is_array(exp) && json_array_size(exp) > 0) {
    json_t *first = json_array_get(exp, 0);

    if (!json_is_string(first)) {
      query->errmsg = strdup(
          "first element of an expression must be a string");
      return NULL;
    }
    name = w_string_new(json_string_value(first));
  } else {
    query->errmsg = strdup("expected array or string for an expression");
    return NULL;
  }

  parser = w_ht_val_ptr(w_ht_get(term_hash, w_ht_ptr_val(name)));

  if (!parser) {
    ignore_result(asprintf(&query->errmsg,
        "unknown expression term '%s'",
        name->buf));
    w_string_delref(name);
    return NULL;
  }
  w_string_delref(name);
  return parser(query, exp);
}
Exemple #2
0
w_string_t *w_fstype(const char *path)
{
#ifdef __linux__
  struct statfs sfs;
  const char *name = "unknown";

  if (statfs(path, &sfs) == 0) {
    switch (sfs.f_type) {
#ifdef CIFS_MAGIC_NUMBER
      case CIFS_MAGIC_NUMBER:
        name = "cifs";
        break;
#endif
#ifdef NFS_SUPER_MAGIC
      case NFS_SUPER_MAGIC:
        name = "nfs";
        break;
#endif
#ifdef SMB_SUPER_MAGIC
      case SMB_SUPER_MAGIC:
        name = "smb";
        break;
#endif
      default:
        name = "unknown";
    }
  }

  return w_string_new(name);
#elif STATVFS_HAS_FSTYPE_AS_STRING
  struct statvfs sfs;

  if (statvfs(path, &sfs) == 0) {
#ifdef HAVE_STRUCT_STATVFS_F_FSTYPENAME
    return w_string_new(sfs.f_fstypename);
#endif
#ifdef HAVE_STRUCT_STATVFS_F_BASETYPE
    return w_string_new(sfs.f_basetype);
#endif
  }
#elif HAVE_STATFS
  struct statfs sfs;

  if (statfs(path, &sfs) == 0) {
    return w_string_new(sfs.f_fstypename);
  }
#endif
  return w_string_new("unknown");
}
Exemple #3
0
void
do_prompt (void)
{
        // FIXME figure out some way to abstract this function
        WString *string;

	script_got_prompt ();

	if (prompting)
		return;

	// If we have some text to display, do it
	if (main_view->buffer != NULL) {
		warlock_view_end_line (NULL);
	}

        string = w_string_new ("");

        if (script_running) {
                w_string_append_str (string, "[script:");
		w_string_append_str (string, g_strdup_printf ("%d", script_get_linenum()));
		w_string_append_str (string, "]");
        }

        w_string_append_c (string, '>');


	debug ("prompt: %s\n", string->string->str);

        view_append (main_view, string);
        w_string_free (string, TRUE);
	prompting = TRUE;
}
Exemple #4
0
w_query_expr *w_expr_suffix_parser(w_query *query, json_t *term)
{
  const char *ignore, *suffix;
  char *arg;
  w_string_t *str;
  int i, l;

  if (json_unpack(term, "[s,s]", &ignore, &suffix) != 0) {
    query->errmsg = strdup("must use [\"suffix\", \"suffixstring\"]");
    return NULL;
  }

  arg = strdup(suffix);
  if (!arg) {
    query->errmsg = strdup("out of memory");
    return NULL;
  }

  l = strlen(arg);
  for (i = 0; i < l; i++) {
    arg[i] = tolower(arg[i]);
  }

  str = w_string_new(arg);
  free(arg);
  if (!str) {
    query->errmsg = strdup("out of memory");
    return NULL;
  }

  return w_query_expr_new(eval_suffix, dispose_suffix, str);
}
Exemple #5
0
static bool parse_relative_root(w_root_t *root, w_query *res, json_t *query)
{
  json_t *relative_root;
  w_string_t *path, *canon_path;

  relative_root = json_object_get(query, "relative_root");
  if (!relative_root) {
    return true;
  }

  if (!json_is_string(relative_root)) {
    res->errmsg = strdup("'relative_root' must be a string");
    return false;
  }

  path = w_string_new(json_string_value(relative_root));
  canon_path = w_string_canon_path(path);
  res->relative_root = w_string_path_cat(root->root_path, canon_path);
  res->relative_root_slash = w_string_make_printf("%.*s%c",
        res->relative_root->len, res->relative_root->buf,
        WATCHMAN_DIR_SEP);
  w_string_delref(path);
  w_string_delref(canon_path);

  return true;
}
Exemple #6
0
bool w_capability_supported(const char *name) {
  bool res;
  w_string_t *namestr = w_string_new(name);
  res = w_ht_get(capabilities, w_ht_ptr_val(namestr));
  w_string_delref(namestr);
  return res;
}
Exemple #7
0
bool dispatch_command(struct watchman_client *client, json_t *args)
{
  watchman_command_func func;
  const char *cmd_name;
  w_string_t *cmd;

  if (!json_array_size(args)) {
    send_error_response(client,
        "invalid command (expected an array with some elements!)");
    return false;
  }

  cmd_name = json_string_value(json_array_get(args, 0));
  if (!cmd_name) {
    send_error_response(client,
        "invalid command: expected element 0 to be the command name");
    return false;
  }
  cmd = w_string_new(cmd_name);
  func = (watchman_command_func)w_ht_get(command_funcs, (w_ht_val_t)cmd);
  w_string_delref(cmd);

  if (func) {
    func(client, args);
    return true;
  }
  send_error_response(client, "unknown command %s", cmd_name);

  return false;
}
Exemple #8
0
// Return the normalized (lowercase) filename suffix
w_string_t *w_string_suffix(w_string_t *str)
{
  int end;
  char name_buf[128];
  char *buf;

  /* can't use libc strXXX functions because we may be operating
   * on a slice */
  for (end = str->len - 1; end >= 0; end--) {
    if (str->buf[end] == '.') {
      if (str->len - (end + 1) >= sizeof(name_buf) - 1) {
        // Too long
        return NULL;
      }

      buf = name_buf;
      end++;
      while ((unsigned)end < str->len) {
        *buf = tolower(str->buf[end]);
        end++;
        buf++;
      }
      *buf = '\0';
      return w_string_new(name_buf);
    }

    if (str->buf[end] == '/') {
      // No suffix
      return NULL;
    }
  }

  // Has no suffix
  return NULL;
}
Exemple #9
0
struct w_clockspec *w_clockspec_parse(json_t *value)
{
  const char *str;
  uint64_t start_time;
  int pid;
  uint32_t root_number;
  uint32_t ticks;

  struct w_clockspec *spec;

  spec = calloc(1, sizeof(*spec));
  if (!spec) {
    return NULL;
  }

  if (json_is_integer(value)) {
    spec->tag = w_cs_timestamp;
    spec->timestamp.tv_usec = 0;
    spec->timestamp.tv_sec = json_integer_value(value);
    return spec;
  }

  str = json_string_value(value);
  if (!str) {
    free(spec);
    return NULL;
  }

  if (str[0] == 'n' && str[1] == ':') {
    spec->tag = w_cs_named_cursor;
    // spec owns the ref to the string
    spec->named_cursor.cursor = w_string_new(str);
    return spec;
  }

  if (sscanf(str, "c:%" PRIu64 ":%" PRIu32 ":%d:%" PRIu32,
             &start_time, &pid, &root_number, &ticks) == 4) {
    spec->tag = w_cs_clock;
    spec->clock.start_time = start_time;
    spec->clock.pid = pid;
    spec->clock.root_number = root_number;
    spec->clock.ticks = ticks;
    return spec;
  }

  if (sscanf(str, "c:%d:%" PRIu32, &pid, &ticks) == 2) {
    // old-style clock value (<= 2.8.2) -- by setting clock time and root number
    // to 0 we guarantee that this is treated as a fresh instance
    spec->tag = w_cs_clock;
    spec->clock.start_time = 0;
    spec->clock.pid = pid;
    spec->clock.root_number = root_number;
    spec->clock.ticks = ticks;
    return spec;
  }

  free(spec);
  return NULL;
}
Exemple #10
0
// Simulate
static void bench_pending(void) {
  // These parameters give us 262140 items to track
  const size_t tree_depth = 7;
  const size_t num_files_per_dir = 8;
  const size_t num_dirs_per_dir = 4;
  w_string_t *root_name = w_string_new("/some/path");
  struct pending_list list;
  const size_t alloc_size = 280000;
  struct timeval start, end;

  list.pending = calloc(alloc_size, sizeof(struct watchman_pending_fs));
  list.avail = list.pending;
  list.end = list.pending + alloc_size;

  // Build a list ordered from the root (top) down to the leaves.
  build_list(&list, root_name, tree_depth, num_files_per_dir, num_dirs_per_dir);
  diag("built list with %u items", list.avail - list.pending);

  // Benchmark insertion in top-down order.
  {
    struct watchman_pending_collection coll;
    struct watchman_pending_fs *item;
    size_t drained = 0;

    w_pending_coll_init(&coll);

    gettimeofday(&start, NULL);
    for (item = list.pending; item < list.avail; item++) {
      w_pending_coll_add(&coll, item->path, item->now, item->flags);
    }
    drained = process_items(&coll);

    gettimeofday(&end, NULL);
    diag("took %.3fs to insert %u items into pending coll",
         w_timeval_diff(start, end), drained);
  }

  // and now in reverse order; this is from the leaves of the filesystem
  // tree up to the root, or bottom-up.  This simulates the workload of
  // a recursive delete of a filesystem tree.
  {
    struct watchman_pending_collection coll;
    struct watchman_pending_fs *item;
    size_t drained = 0;

    w_pending_coll_init(&coll);

    gettimeofday(&start, NULL);
    for (item = list.avail - 1; item >= list.pending; item--) {
      w_pending_coll_add(&coll, item->path, item->now, item->flags);
    }

    drained = process_items(&coll);

    gettimeofday(&end, NULL);
    diag("took %.3fs to reverse insert %u items into pending coll",
         w_timeval_diff(start, end), drained);
  }
}
Exemple #11
0
void w_capability_register(const char *name) {
  if (!capabilities) {
    capabilities = w_ht_new(128, &w_ht_string_funcs);
  }
  w_ht_set(capabilities,
      w_ht_ptr_val(w_string_new(name)),
      true);
}
Exemple #12
0
// Compute the basename of path, return that as a string
w_string_t *w_string_new_basename(const char *path) {
  const char *base;
  base = path + strlen(path);
  while (base > path && base[-1] != WATCHMAN_DIR_SEP) {
    base--;
  }
  return w_string_new(base);
}
Exemple #13
0
void w_register_command(struct watchman_command_handler_def *defs)
{
  if (!command_funcs) {
    command_funcs = w_ht_new(16, &w_ht_string_funcs);
  }
  w_ht_set(command_funcs,
      w_ht_ptr_val(w_string_new(defs->name)),
      w_ht_ptr_val(defs));
}
Exemple #14
0
void
echo (const char *str)
{
        WString *wstr;

        wstr = w_string_new (str);

        w_string_add_tag (wstr, ECHO_TAG, 0, -1);
        view_append (main_view, wstr);
}
Exemple #15
0
void register_commands(struct watchman_command_handler_def *defs)
{
  int i;

  command_funcs = w_ht_new(16, &w_ht_string_funcs);
  for (i = 0; defs[i].name; i++) {
    w_ht_set(command_funcs,
        (w_ht_val_t)w_string_new(defs[i].name),
        (w_ht_val_t)defs[i].func);
  }

  w_query_init_all();
}
Exemple #16
0
w_string_t *w_string_new_wchar(WCHAR *str, int len) {
  char buf[WATCHMAN_NAME_MAX];
  int res;

  if (len == 0) {
    return w_string_new("");
  }

  res = WideCharToMultiByte(CP_UTF8, 0, str, len, buf, sizeof(buf), NULL, NULL);
  if (res == 0) {
    char msgbuf[1024];
    DWORD err = GetLastError();
    FormatMessageA(
      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
      NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
      msgbuf, sizeof(msgbuf)-1, NULL);
    w_log(W_LOG_ERR, "WideCharToMultiByte failed: 0x%x %s\n", err, msgbuf);
    return NULL;
  }

  buf[res] = 0;
  return w_string_new(buf);
}
Exemple #17
0
void w_register_command(struct watchman_command_handler_def *defs)
{
  char capname[128];

  if (!command_funcs) {
    command_funcs = w_ht_new(16, &w_ht_string_funcs);
  }
  w_ht_set(command_funcs,
      w_ht_ptr_val(w_string_new(defs->name)),
      w_ht_ptr_val(defs));

  snprintf(capname, sizeof(capname), "cmd-%s", defs->name);
  w_capability_register(capname);
}
Exemple #18
0
static bool parse_suffixes(w_query *res, json_t *query)
{
  json_t *suffixes;
  size_t i;

  suffixes = json_object_get(query, "suffix");
  if (!suffixes) {
    return true;
  }

  if (!json_is_array(suffixes)) {
    res->errmsg = strdup("'suffix' must be an array of strings");
    return false;
  }

  res->nsuffixes = json_array_size(suffixes);
  res->suffixes = calloc(res->nsuffixes, sizeof(w_string_t*));

  if (!res->suffixes) {
    return false;
  }

  for (i = 0; i < json_array_size(suffixes); i++) {
    json_t *ele = json_array_get(suffixes, i);
    char *low;
    int j;

    if (!json_is_string(ele)) {
      res->errmsg = strdup("'suffix' must be an array of strings");
      return false;
    }

    low = strdup(json_string_value(ele));
    if (!low) {
      res->errmsg = strdup("out of memory");
      return false;
    }

    for (j = 0; low[j]; j++) {
      low[j] = tolower(low[j]);
    }

    res->suffixes[i] = w_string_new(low);

    free(low);
  }

  return true;
}
Exemple #19
0
static bool parse_paths(w_query *res, json_t *query)
{
  json_t *paths;
  size_t i;

  paths = json_object_get(query, "path");
  if (!paths) {
    return true;
  }

  if (!json_is_array(paths)) {
    res->errmsg = strdup("'path' must be an array");
    return false;
  }

  res->npaths = json_array_size(paths);
  res->paths = calloc(res->npaths, sizeof(res->paths[0]));

  if (!res->paths) {
    res->errmsg = strdup("out of memory");
    return false;
  }

  for (i = 0; i < json_array_size(paths); i++) {
    json_t *ele = json_array_get(paths, i);
    const char *name = NULL;
    w_string_t *path;

    res->paths[i].depth = -1;

    if (json_is_string(ele)) {
      name = json_string_value(ele);
    } else if (json_unpack(ele, "{s:s, s:i}",
          "path", &name,
          "depth", &res->paths[i].depth
          ) != 0) {
      res->errmsg = strdup(
          "expected object with 'path' and 'depth' properties"
          );
      return false;
    }

    path = w_string_new(name);
    res->paths[i].name = w_string_canon_path(path);
    w_string_delref(path);
  }

  return true;
}
Exemple #20
0
w_string_t *w_string_path_cat(w_string_t *parent, w_string_t *rhs)
{
  char name_buf[WATCHMAN_NAME_MAX];

  if (rhs->len == 0) {
    w_string_addref(parent);
    return parent;
  }

  snprintf(name_buf, sizeof(name_buf), "%.*s/%.*s",
      parent->len, parent->buf,
      rhs->len, rhs->buf);

  return w_string_new(name_buf);
}
Exemple #21
0
bool w_query_register_expression_parser(
    const char *term,
    w_query_expr_parser parser)
{
  w_string_t *name = w_string_new(term);

  if (!name) {
    return false;
  }

  if (!term_hash) {
    term_hash = w_ht_new(32, &w_ht_string_funcs);
  }

  return w_ht_set(term_hash, w_ht_ptr_val(name), w_ht_ptr_val(parser));
}
Exemple #22
0
/* trigger-del /root triggername
 * Delete a trigger from a root
 */
static void cmd_trigger_delete(struct watchman_client *client, json_t *args)
{
  w_root_t *root;
  json_t *resp;
  const char *name;
  w_string_t *tname;
  bool res;

  root = resolve_root_or_err(client, args, 1, false);
  if (!root) {
    return;
  }

  if (json_array_size(args) != 3) {
    send_error_response(client, "wrong number of arguments");
    w_root_delref(root);
    return;
  }
  name = json_string_value(json_array_get(args, 2));
  if (!name) {
    send_error_response(client, "expected 2nd parameter to be trigger name");
    w_root_delref(root);
    return;
  }
  tname = w_string_new(name);

  w_root_lock(root);
  res = w_ht_del(root->commands, w_ht_ptr_val(tname));
  w_root_unlock(root);

  if (res) {
    w_state_save();
  }

  w_string_delref(tname);

  resp = make_response();
  set_prop(resp, "deleted", json_boolean(res));
  set_prop(resp, "trigger", json_string_nocheck(name));
  send_and_dispose_response(client, resp);
  w_root_delref(root);
}
Exemple #23
0
bool w_query_register_expression_parser(
    const char *term,
    w_query_expr_parser parser)
{
  char capname[128];
  w_string_t *name = w_string_new(term);

  if (!name) {
    return false;
  }

  snprintf(capname, sizeof(capname), "term-%s", term);
  w_capability_register(capname);

  if (!term_hash) {
    term_hash = w_ht_new(32, &w_ht_string_funcs);
  }

  return w_ht_set(term_hash, w_ht_ptr_val(name), w_ht_ptr_val(parser));
}
Exemple #24
0
static struct watchman_command_handler_def *lookup(
    json_t *args, char **errmsg, int mode)
{
  struct watchman_command_handler_def *def;
  const char *cmd_name;
  w_string_t *cmd;

  if (!json_array_size(args)) {
    ignore_result(asprintf(errmsg,
        "invalid command (expected an array with some elements!)"));
    return false;
  }

  cmd_name = json_string_value(json_array_get(args, 0));
  if (!cmd_name) {
    ignore_result(asprintf(errmsg,
        "invalid command: expected element 0 to be the command name"));
    return false;
  }
  cmd = w_string_new(cmd_name);
  def = w_ht_val_ptr(w_ht_get(command_funcs, w_ht_ptr_val(cmd)));
  w_string_delref(cmd);

  if (def) {
    if (mode && ((def->flags & mode) == 0)) {
      ignore_result(asprintf(errmsg,
          "command %s not available in this mode", cmd_name));
      return NULL;
    }
    return def;
  }

  if (mode) {
    ignore_result(asprintf(errmsg, "unknown command %s", cmd_name));
  }

  return NULL;
}
Exemple #25
0
/* unsubscribe /root subname
 * Cancels a subscription */
void cmd_unsubscribe(struct watchman_client *client, json_t *args)
{
  w_root_t *root;
  const char *name;
  w_string_t *sname;
  bool deleted;
  json_t *resp;

  root = resolve_root_or_err(client, args, 1, false);
  if (!root) {
    return;
  }

  name = json_string_value(json_array_get(args, 2));
  if (!name) {
    send_error_response(client,
        "expected 2nd parameter to be subscription name");
    w_root_delref(root);
    return;
  }

  sname = w_string_new(name);

  pthread_mutex_lock(&w_client_lock);
  deleted = w_ht_del(client->subscriptions, w_ht_ptr_val(sname));
  pthread_mutex_unlock(&w_client_lock);

  w_string_delref(sname);

  resp = make_response();
  set_prop(resp, "unsubscribe", json_string_nocheck(name));
  set_prop(resp, "deleted", json_boolean(deleted));

  send_and_dispose_response(client, resp);
  w_root_delref(root);
}
Exemple #26
0
struct watchman_trigger_command *w_build_trigger_from_def(
  w_root_t *root, json_t *trig, char **errmsg)
{
  struct watchman_trigger_command *cmd;
  json_t *ele, *query;
  json_int_t jint;
  const char *name = NULL;

  cmd = calloc(1, sizeof(*cmd));
  if (!cmd) {
    *errmsg = strdup("no memory");
    return NULL;
  }

  cmd->definition = trig;
  json_incref(cmd->definition);

  query = json_pack("{s:O}", "expression",
      json_object_get(cmd->definition, "expression"));
  cmd->query = w_query_parse(query, errmsg);
  json_decref(query);

  if (!cmd->query) {
    w_trigger_command_free(cmd);
    return NULL;
  }

  json_unpack(trig, "{s:s}", "name", &name);
  if (!name) {
    *errmsg = strdup("invalid or missing name");
    w_trigger_command_free(cmd);
    return NULL;
  }

  cmd->triggername = w_string_new(name);
  cmd->command = json_object_get(trig, "command");
  if (cmd->command) {
    json_incref(cmd->command);
  }
  if (!cmd->command || !json_is_array(cmd->command) ||
      !json_array_size(cmd->command)) {
    *errmsg = strdup("invalid command array");
    w_trigger_command_free(cmd);
    return NULL;
  }

  json_unpack(trig, "{s:b}", "append_files", &cmd->append_files);

  ele = json_object_get(trig, "stdin");
  if (!ele) {
    cmd->stdin_style = input_dev_null;
  } else if (json_is_array(ele)) {
    cmd->stdin_style = input_json;
    if (!parse_field_list(ele, &cmd->field_list, errmsg)) {
      w_trigger_command_free(cmd);
      return NULL;
    }
  } else if (json_is_string(ele)) {
    const char *str = json_string_value(ele);
    if (!strcmp(str, "/dev/null")) {
      cmd->stdin_style = input_dev_null;
    } else if (!strcmp(str, "NAME_PER_LINE")) {
      cmd->stdin_style = input_name_list;
    } else {
      ignore_result(asprintf(errmsg, "invalid stdin value %s", str));
      w_trigger_command_free(cmd);
      return NULL;
    }
  } else {
    *errmsg = strdup("invalid value for stdin");
    w_trigger_command_free(cmd);
    return NULL;
  }

  jint = 0; // unlimited unless specified
  json_unpack(trig, "{s:I}", "max_files_stdin", &jint);
  if (jint < 0) {
    *errmsg = strdup("max_files_stdin must be >= 0");
    w_trigger_command_free(cmd);
    return NULL;
  }
  cmd->max_files_stdin = jint;

  json_unpack(trig, "{s:s}", "stdout", &cmd->stdout_name);
  json_unpack(trig, "{s:s}", "stderr", &cmd->stderr_name);

  if (!parse_redirection(&cmd->stdout_name, &cmd->stdout_flags,
        "stdout", errmsg)) {
    w_trigger_command_free(cmd);
    return NULL;
  }

  if (!parse_redirection(&cmd->stderr_name, &cmd->stderr_flags,
        "stderr", errmsg)) {
    w_trigger_command_free(cmd);
    return NULL;
  }

  // Copy current environment
  cmd->envht = w_envp_make_ht();

  // Set some standard vars
  w_envp_set(cmd->envht, "WATCHMAN_ROOT", root->root_path);
  w_envp_set_cstring(cmd->envht, "WATCHMAN_SOCK", get_sock_name());
  w_envp_set(cmd->envht, "WATCHMAN_TRIGGER", cmd->triggername);

  return cmd;
}
Exemple #27
0
// ["dirname", "foo"] -> ["dirname", "foo", ["depth", "ge", 0]]
static w_query_expr *dirname_parser_inner(w_query *query, json_t *term,
        bool caseless)
{
    const char *which = caseless ? "idirname" : "dirname";
    struct dirname_data *data;
    json_t *name;
    struct w_query_int_compare depth_comp;

    if (!json_is_array(term)) {
        ignore_result(asprintf(&query->errmsg, "Expected array for '%s' term",
                               which));
        return NULL;
    }

    if (json_array_size(term) < 2) {
        ignore_result(asprintf(&query->errmsg,
                               "Invalid number of arguments for '%s' term",
                               which));
        return NULL;
    }

    if (json_array_size(term) > 3) {
        ignore_result(asprintf(&query->errmsg,
                               "Invalid number of arguments for '%s' term",
                               which));
        return NULL;
    }

    name = json_array_get(term, 1);
    if (!json_is_string(name)) {
        ignore_result(asprintf(&query->errmsg,
                               "Argument 2 to '%s' must be a string", which));
        return NULL;
    }

    if (json_array_size(term) == 3) {
        json_t *depth;

        depth = json_array_get(term, 2);
        if (!json_is_array(depth)) {
            ignore_result(asprintf(&query->errmsg,
                                   "Invalid number of arguments for '%s' term",
                                   which));
            return NULL;
        }

        if (!parse_int_compare(depth, &depth_comp, &query->errmsg)) {
            return NULL;
        }

        if (strcmp("depth", json_string_value(json_array_get(depth, 0)))) {
            ignore_result(asprintf(&query->errmsg,
                                   "Third parameter to '%s' should be a relational depth term",
                                   which));
            return NULL;
        }
    } else {
        depth_comp.operand = 0;
        depth_comp.op = W_QUERY_ICMP_GE;
    }

    data = calloc(1, sizeof(*data));
    if (!data) {
        ignore_result(asprintf(&query->errmsg, "out of memory"));
        return NULL;
    }
    data->dirname = w_string_new(json_string_value(name));
    data->startswith =
        caseless ?  w_string_startswith_caseless : w_string_startswith;
    data->depth = depth_comp;

    return w_query_expr_new(eval_dirname, dispose_dirname, data);
}
Exemple #28
0
/* subscribe /root subname {query}
 * Subscribes the client connection to the specified root. */
void cmd_subscribe(struct watchman_client *client, json_t *args)
{
  w_root_t *root;
  struct watchman_client_subscription *sub;
  json_t *resp;
  const char *name;
  json_t *jfield_list;
  w_query *query;
  json_t *query_spec;
  struct w_query_field_list field_list;
  char *errmsg;

  if (json_array_size(args) != 4) {
    send_error_response(client, "wrong number of arguments for subscribe");
    return;
  }

  root = resolve_root_or_err(client, args, 1, true);
  if (!root) {
    return;
  }

  name = json_string_value(json_array_get(args, 2));
  if (!name) {
    send_error_response(client,
        "expected 2nd parameter to be subscription name");
    goto done;
  }

  query_spec = json_array_get(args, 3);

  jfield_list = json_object_get(query_spec, "fields");
  if (!parse_field_list(jfield_list, &field_list, &errmsg)) {
    send_error_response(client, "invalid field list: %s", errmsg);
    free(errmsg);
    goto done;
  }

  query = w_query_parse(query_spec, &errmsg);
  if (!query) {
    send_error_response(client, "failed to parse query: %s", errmsg);
    free(errmsg);
    goto done;
  }

  sub = calloc(1, sizeof(*sub));
  if (!sub) {
    send_error_response(client, "no memory!");
    goto done;
  }

  sub->name = w_string_new(name);
  sub->query = query;
  memcpy(&sub->field_list, &field_list, sizeof(field_list));
  sub->root = root;

  pthread_mutex_lock(&w_client_lock);
  w_ht_replace(client->subscriptions, w_ht_ptr_val(sub->name),
      w_ht_ptr_val(sub));
  pthread_mutex_unlock(&w_client_lock);

  resp = make_response();
  annotate_with_clock(root, resp);
  set_prop(resp, "subscribe", json_string(name));
  send_and_dispose_response(client, resp);

  resp = build_subscription_results(sub, root);
  if (resp) {
    send_and_dispose_response(client, resp);
  }
done:
  w_root_delref(root);
}
Exemple #29
0
// Given a json array, concat the elements using a delimiter
w_string_t *w_string_implode(json_t *arr, const char *delim)
{
  uint32_t delim_len = u32_strlen(delim);
  uint32_t len = 0;
  uint32_t i;
  w_string_t *s;
  char *buf;

  if (json_array_size(arr) == 0) {
    return w_string_new("");
  }

  if (json_array_size(arr) == 1) {
    return w_string_new(json_string_value(json_array_get(arr, 0)));
  }

  len = ((uint32_t)json_array_size(arr) - 1) * delim_len;

  for (i = 0; i < json_array_size(arr); i++) {
    const char *str;

    str = json_string_value(json_array_get(arr, i));
    len += u32_strlen(str);
  }

  s = malloc(sizeof(*s) + len + 1);
  if (!s) {
    perror("no memory available");
    abort();
  }

  s->refcnt = 1;
  s->slice = NULL;
  buf = (char*)(s + 1);
  s->buf = buf;

  for (i = 0; i < json_array_size(arr); i++) {
    const char *str;
    uint32_t l;

    str = json_string_value(json_array_get(arr, i));
    l = u32_strlen(str);

    memcpy(buf, str, l);

    // Final string doesn't want delimiter after it
    if (i == json_array_size(arr) - 1) {
      buf += l;
      break;
    }

    memcpy(buf + l, delim, delim_len);
    buf += l + delim_len;
  }
  *buf = '\0';

  s->len = (uint32_t)(buf - s->buf);
  s->hval = w_hash_bytes(s->buf, s->len, 0);

  return s;
}
Exemple #30
0
w_string_t *w_fstype(const char *path)
{
#ifdef __linux__
  struct statfs sfs;
  const char *name = "unknown";

  if (statfs(path, &sfs) == 0) {
    switch (sfs.f_type) {
#ifdef CIFS_MAGIC_NUMBER
      case CIFS_MAGIC_NUMBER:
        name = "cifs";
        break;
#endif
#ifdef NFS_SUPER_MAGIC
      case NFS_SUPER_MAGIC:
        name = "nfs";
        break;
#endif
#ifdef SMB_SUPER_MAGIC
      case SMB_SUPER_MAGIC:
        name = "smb";
        break;
#endif
      default:
        name = "unknown";
    }
  }

  return w_string_new(name);
#elif STATVFS_HAS_FSTYPE_AS_STRING
  struct statvfs sfs;

  if (statvfs(path, &sfs) == 0) {
#ifdef HAVE_STRUCT_STATVFS_F_FSTYPENAME
    return w_string_new(sfs.f_fstypename);
#endif
#ifdef HAVE_STRUCT_STATVFS_F_BASETYPE
    return w_string_new(sfs.f_basetype);
#endif
  }
#elif HAVE_STATFS
  struct statfs sfs;

  if (statfs(path, &sfs) == 0) {
    return w_string_new(sfs.f_fstypename);
  }
#endif
#ifdef _WIN32
  WCHAR *wpath = w_utf8_to_win_unc(path, -1);
  w_string_t *fstype_name = NULL;
  if (wpath) {
    WCHAR fstype[MAX_PATH+1];
    HANDLE h = CreateFileW(wpath, GENERIC_READ,
        FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (h) {
      if (GetVolumeInformationByHandleW(h, NULL, 0, 0, 0, 0, fstype,
            MAX_PATH+1)) {
        fstype_name = w_string_new_wchar(fstype, -1);
      }
      CloseHandle(h);
    }
    free(wpath);
  }
  if (fstype_name) {
    return fstype_name;
  }
  return w_string_new("unknown");
#else
  unused_parameter(path);
  return w_string_new("unknown");
#endif
}