示例#1
0
文件: map.c 项目: tylerneylon/ccache
List *find_with_hash(Map map, void *needle, int h) {
  int n = map->buckets->count;
  int index = ((unsigned int)h) % n;
  List *bucket = (List *)array__item_ptr(map->buckets, index);
  return bucket_find(bucket, needle, map->eq);
}
示例#2
0
int test_file(FILE *fp, int argc, char **argv) {
    char buf[65535 + 1];
    char *pos;
    unsigned int strategy = 0;  /* what bucketing strategy we're 
                                          using */
    void *ptr = NULL;
    unsigned int bucketsize = 0;
    struct params params = {0};
    struct chash *hash = NULL;
    char name[256];

    if (!parse_params(argc, argv, &params)) {
        fprintf(stderr, "failed to parse params\n");
        return 0;
    }

    while (fgets((char *) buf, 65535, fp)) {
        str_rtrim(buf);
        pos = (char *) str_ltrim(buf);

        if (!str_casecmp(pos, "new")) {

            /* creating a new bucket */
            unsigned int size = -1;

            if (ptr) {
                chash_delete(hash);
                free(ptr);
            }

            /* read parameters */
            if ((fscanf(fp, "%255s %u %u", name, &strategy, &size) == 3)
              && (size <= 65535) 
              && (bucketsize = size)
              && (ptr = malloc(size))
              && (hash = chash_ptr_new(1, 2.0, 
                /* some fn pointer casting dodginess */
                (unsigned int (*)(const void *)) str_len, 
                (int (*)(const void *, const void *)) str_cmp))
              && (bucket_new(ptr, bucketsize, strategy))) {
                /* succeeded, do nothing */
                if (params.verbose) {
                    printf("%s: new bucket with size %u strategy %u\n", name, 
                      size, strategy);
                }
            } else {
                fprintf(stderr, "%s: failed to create bucket\n", name);
                return 0;
            }
        } else if (!str_casecmp(pos, "add")) {
            /* adding a term to the bucket */
            void *ret;
            unsigned int veclen,
                         succeed,
                         len;
            int toobig;

            if (!ptr) { return 0; }

            /* read parameters */
            if ((fscanf(fp, "%65535s %u %u", buf, &veclen, &succeed) == 3) 
              && (veclen <= 65535)) {

                len = str_len(buf);
                if ((((ret = bucket_alloc(ptr, bucketsize, strategy, buf, len, 
                        veclen, &toobig, NULL))
                      && succeed)
                    || (!ret && !succeed))) {
                    /* do nothing */
                    if (params.verbose) {
                        printf("%s: added term '%s'\n", name, buf);
                    }
                } else if (succeed) {
                    fprintf(stderr, "%s: failed to add '%s' to bucket\n", 
                      name, buf);
                    return 0;
                } else if (!succeed) {
                    fprintf(stderr, "%s: add '%s' succeeded but shouldn't "
                      "have\n", name, buf);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: failed to add\n", name);
                return 0;
            }
        } else if (!str_casecmp(pos, "ls")) {
            /* matching stuff in the bucket */
            unsigned int numterms,
                         i,
                         len,
                         veclen,
                         veclen2,
                         state;
            void *addr;
            struct chash *tmphash;
            const char *term;
            void **tmpptr,
                  *tmp;

            if (!ptr) { return 0; }

            if (!(tmphash = chash_ptr_new(1, 2.0, 
              /* some fn pointer casting dodginess */
              (unsigned int (*)(const void *)) str_len, 
              (int (*)(const void *, const void *)) str_cmp))) {
                fprintf(stderr, "%s: failed to init hashtable\n", name);
                return 0;
            }

            /* first, fill hashtable with all terms from bucket */
            state = 0;
            while ((term 
              = bucket_next_term(ptr, bucketsize, strategy,
                  &state, &len, &addr, &veclen))) {

                if (!((term = str_ndup(term, len)) 
                  && (chash_ptr_ptr_insert(tmphash, term, (void*) term) 
                      == CHASH_OK))) {

                    fprintf(stderr, "%s: failed to init hashtable\n", name);
                    return 0;
                }
            }

            /* now, take terms from file, comparing them with hashtable 
             * entries */
            if (fscanf(fp, "%u", &numterms)) {
                for (i = 0; i < numterms; i++) {
                    if (fscanf(fp, "%65535s %u ", buf, &veclen)) {
                        if (params.verbose) {
                            printf("%s: ls checking %s\n", name, buf);
                        }
                        
                        if ((addr = bucket_find(ptr, bucketsize, strategy,
                            buf, str_len(buf), &veclen2, NULL))
                          /* remove it from hashtable */
                          && chash_ptr_ptr_find(tmphash, buf, &tmpptr) 
                            == CHASH_OK
                          && chash_ptr_ptr_remove(tmphash, *tmpptr, &tmp) 
                            == CHASH_OK
                          && (free(tmp), 1)
                          && (veclen <= 65535)
                          && (veclen2 == veclen)
                          && fread(buf, veclen, 1, fp)
                          && ((buf[veclen] = '\0'), 1)
                          && (!params.verbose 
                            || printf("%s: ls check read '%s'\n", name, buf))
                          && !memcmp(buf, addr, veclen)) {
                            /* do nothing */
                        } else {
                            unsigned int j;

                            fprintf(stderr, "%s: ls failed cmp '%s' with '", 
                              name, buf);
                            for (j = 0; j < veclen; j++) {
                                putc(((char *) addr)[j], stderr);
                            }
                            fprintf(stderr, "'\n");
                            return 0;
                        }
                    } else {
                        fprintf(stderr, "%s: ls failed\n", name);
                        return 0;
                    }
                }

                if (chash_size(tmphash)) {
                    fprintf(stderr, "%s: ls failed\n", name);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: ls failed\n", name);
                return 0;
            }

            chash_delete(tmphash);

            if (params.verbose) {
                printf("%s: matched all (%u) entries\n", name, numterms);
            }
        } else if (!str_casecmp(pos, "set")) {
            /* setting the vector for a term in the bucket */
            unsigned int veclen,
                        reallen;
            void *addr;

            if (!ptr) { return 0; }

            /* read parameters */
            if ((fscanf(fp, "%65535s %u ", buf, &veclen) == 2) 
              && (veclen <= 65535)) {

                addr = bucket_find(ptr, bucketsize, strategy, buf, 
                  str_len(buf), &reallen, NULL);

                if (addr && (reallen == veclen) 
                  && fread(addr, 1, veclen, fp)) {
                    /* do nothing */
                    if (params.verbose) {
                        unsigned int j;

                        printf("%s: set term '%s' to '", name, buf);
                        for (j = 0; j < reallen; j++) {
                            putc(((char *) addr)[j], stdout);
                        }
                        printf("'\n");
                    }
                } else {
                    fprintf(stderr, "%s: failed to set!\n", name);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: failed to set\n", name);
                return 0;
            }
        } else if (!str_casecmp(pos, "realloc")) {
            /* reallocating a term in the bucket */
            unsigned int veclen,
                         succeed;
            int toobig;

            if (!ptr) { return 0; }

            /* read parameters */
            if ((fscanf(fp, "%65535s %u %u", buf, &veclen, &succeed) == 3) 
              && (veclen <= 65535)) {

                if (!bucket_realloc(ptr, bucketsize, strategy, buf, 
                  str_len(buf), veclen, &toobig)) {
                    fprintf(stderr, "%s: failed to realloc!\n", name);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: failed to realloc\n", name);
                return 0;
            }

            if (params.verbose) {
                printf("%s: realloc'd term '%s'\n", name, buf);
            }
        } else if (!str_casecmp(pos, "rm")) {
            /* removing something from the bucket */
            unsigned int succeed;

            if (!ptr) { return 0; }

            if (fscanf(fp, "%65535s %u", buf, &succeed) == 2) {
                if (succeed) {

                    if (!(bucket_remove(ptr, bucketsize, strategy, buf, 
                      str_len(buf)))) {
                        fprintf(stderr, "%s: failed to rm '%s'\n", name, 
                          buf);
                        return 0;
                    } else if (params.verbose) {
                        printf("%s: rm term '%s'\n", name, buf);
                    }
                } else if (succeed) {
                    fprintf(stderr, "%s: failed to rm\n", name);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: failed to rm\n", name);
                return 0;
            }
        } else if (!str_casecmp(pos, "print")) {
            /* printing out the bucket contents */
            unsigned int state = 0,
                         len,
                         veclen;
            const char *term;
            char format[100];
            void *addr;

            if (!ptr) { 
                printf("can't print, no bucket\n");
            } else {
                do {
                    term 
                      = bucket_next_term(ptr, bucketsize, strategy, &state, 
                        &len, &addr, &veclen);
                } while (term 
                  && memcpy(buf, term, len)
                  && ((buf[len] = '\0') || 1)
                  && snprintf(format, 100, "%%.%us (%%u): '%%.%us' (%%u) "
                    "(off %%u)\n", len, veclen) 
                  && printf(format, term, len, (char*) addr, veclen, 
                    ((char *) addr) - (char *) ptr));

                if (!state) {
                    printf("(empty)\n");
                }

                printf("%u entries, %u data, %u string, %u overhead, %u free\n", 
                  bucket_entries(ptr, bucketsize, strategy), 
                  bucket_utilised(ptr, bucketsize, strategy), 
                  bucket_string(ptr, bucketsize, strategy), 
                  bucket_overhead(ptr, bucketsize, strategy),
                  bucket_unused(ptr, bucketsize, strategy));
            }
        } else if (!str_casecmp(pos, "match")) {
            unsigned int veclen,
                         veclen2;
            void *addr;

            if (fscanf(fp, "%65535s %u ", buf, &veclen)) {
                if ((addr = bucket_find(ptr, bucketsize, strategy,
                    buf, str_len(buf), &veclen2, NULL))
                  && (veclen <= 65535)
                  && (veclen2 >= veclen)
                  && (!params.verbose 
                    || printf("%s: match on '%s' ", name, buf))
                  && fread(buf, veclen, 1, fp)
                  && !memcmp(buf, addr, veclen)) {
                    if (params.verbose) {
                        printf("content succeeded\n");
                    }
                } else {
                    fprintf(stderr, "%s: match failed (%s vs %s)\n", name, buf,
                      (char *) addr);
                    return 0;
                }
            } else {
                fprintf(stderr, "%s: match failed\n", name);
                return 0;
            }
        } else if ((*pos != '#') && str_len(pos)) {
            fprintf(stderr, "%s: unknown command '%s'\n", name, pos);
            return 0;
        }
    }

    if (ptr) {
        chash_delete(hash);
        free(ptr);
    }

    return 1;
}
示例#3
0
文件: bucket.c 项目: jgarzik/tabled
bool access_list(struct client *cli, const char *bucket, const char *key,
		 const char *user)
{
	struct macl {
		char		perm[128];		/* perm(s) granted */
		char		grantee[64];		/* grantee user */
	};

	GHashTable *param;
	enum errcode err = InternalError;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB *acls = tdbrep.tdb.acls;
	int alloc_len;
	char owner[64];
	GList *res;
	struct db_acl_key *acl_key;
	struct db_acl_ent *acl;
	DB_TXN *txn = NULL;
	DBC *cur = NULL;
	GList *content;
	DBT pkey, pval;
	struct macl *mp;
	char guser[64];
	GList *p;
	char *s;
	int str_len;
	int rc;
	bool rcb;

	/* verify READ access for ACL */
	if (!user || !has_access(user, bucket, key, "READ_ACP")) {
		err = AccessDenied;
		goto err_out;
	}

	/* parse URI query string */
	param = hreq_query(&cli->req);
	if (!param)
		goto err_out;

	res = NULL;

	alloc_len = sizeof(struct db_acl_key) + strlen(key) + 1;
	acl_key = alloca(alloc_len);
	memset(acl_key, 0, alloc_len);

	strncpy(acl_key->bucket, bucket, sizeof(acl_key->bucket));
	strcpy(acl_key->key, key);

	/* open transaction, search cursor */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto err_out_param;
	}

	rc = bucket_find(txn, bucket, &owner[0], sizeof(owner));
	if (rc) {
		if (rc == DB_NOTFOUND)
			err = InvalidBucketName;
		else
			dbenv->err(dbenv, rc, "bucket_find");
		goto err_out_rb;
	}

	rc = acls->cursor(acls, txn, &cur, 0);
	if (rc) {
		acls->err(acls, rc, "acls->cursor");
		goto err_out_rb;
	}

	memset(&pkey, 0, sizeof(pkey));
	pkey.data = acl_key;
	pkey.size = alloc_len;

	for (;; free(acl)) {

		memset(&pval, 0, sizeof(pval));
		pval.flags = DB_DBT_MALLOC;

		rc = cur->get(cur, &pkey, &pval, DB_NEXT);
		if (rc)
			break;

		acl = pval.data;

		/* This is a workaround, see FIXME about DB_NEXT. */
		if (strncmp(acl->bucket, bucket, sizeof(acl->bucket)))
			continue;
		if (strcmp(acl->key, key))
			continue;

		if ((mp = malloc(sizeof(struct macl))) == NULL) {
			free(acl);
			cur->close(cur);
			goto err_out_rb;
		}

		memcpy(mp->grantee, acl->grantee, sizeof(mp->grantee));
		mp->grantee[sizeof(mp->grantee)-1] = 0;

		memcpy(mp->perm, acl->perm, sizeof(mp->perm));

		/* lop off the trailing comma */
		mp->perm[sizeof(mp->perm)-1] = 0;
		str_len = strlen(mp->perm);
		if (str_len && mp->perm[str_len-1] == ',')
			mp->perm[--str_len] = 0;

		res = g_list_append(res, mp);
	}

	if (rc != DB_NOTFOUND)
		acls->err(acls, rc, "access_list iteration");

	/* close cursor, transaction */
	rc = cur->close(cur);
	if (rc)
		acls->err(acls, rc, "acls->cursor close");
	rc = txn->commit(txn, 0);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");

	/* dump collected acls -- no more exception handling */

	s = g_markup_printf_escaped(
		"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
		"<AccessControlPolicy "
		     "xmlns=\"http://indy.yyz.us/doc/2006-03-01/\">\r\n"
		"  <Owner>\r\n"
		"    <ID>%s</ID>\r\n"
		"    <DisplayName>%s</DisplayName>\r\n"
		"  </Owner>\r\n",
		owner, owner);
	content = g_list_append(NULL, s);

	s = g_markup_printf_escaped(
		"  <AccessControlList>\r\n");
	content = g_list_append(content, s);

	for (p = res; p != NULL; p = p->next) {
		mp = p->data;

		if (!strcmp(DB_ACL_ANON, mp->grantee)) {
			strcpy(guser, "anonymous");
		} else {
			strncpy(guser, mp->grantee, sizeof(guser));
			guser[sizeof(guser)-1] = 0;
		}

		s = g_markup_printf_escaped(
			"    <Grant>\r\n"
			"      <Grantee xmlns:xsi=\"http://www.w3.org/2001/"
			"XMLSchema-instance\" xsi:type=\"CanonicalUser\">\r\n"
			"        <ID>%s</ID>\r\n"
			"        <DisplayName>%s</DisplayName>\r\n"
			"      </Grantee>\r\n",
			guser, guser);
		content = g_list_append(content, s);

		/*
		 * FIXME This parsing is totally lame, we should replace
		 * strings with a bit mask once we make sure this works.
		 */
		if (!strcmp(mp->perm, "READ,WRITE,READ_ACP,WRITE_ACP")) {
			s = g_markup_printf_escaped(
			   "      <Permission>FULL_CONTROL</Permission>\r\n");
		} else {
			s = g_markup_printf_escaped(
			   "      <Permission>%s</Permission>\r\n",
			   mp->perm);
		}
		content = g_list_append(content, s);

		s = g_markup_printf_escaped("    </Grant>\r\n");
		content = g_list_append(content, s);

		free(mp);
	}

	s = g_markup_printf_escaped("  </AccessControlList>\r\n");
	content = g_list_append(content, s);

	s = g_markup_printf_escaped("</AccessControlPolicy>\r\n");
	content = g_list_append(content, s);

	g_list_free(res);

	rcb = cli_resp_xml(cli, 200, content);
	g_list_free(content);
	return rcb;

err_out_rb:
	rc = txn->abort(txn);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
	for (p = res; p != NULL; p = p->next)
		free(p->data);
	g_list_free(res);
err_out_param:
	g_hash_table_destroy(param);
err_out:
	return cli_err(cli, err);
}
示例#4
0
文件: bucket.c 项目: jgarzik/tabled
bool bucket_add(struct client *cli, const char *user, const char *bucket)
{
	char *hdr, timestr[64];
	enum errcode err = InternalError;
	int rc;
	struct db_bucket_ent ent;
	bool setacl;			/* is ok to put pre-existing bucket */
	enum ReqACLC canacl;
	DB *buckets = tdbrep.tdb.buckets;
	DB *acls = tdbrep.tdb.acls;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB_TXN *txn = NULL;
	DBT key, val;

	if (!user)
		return cli_err(cli, AccessDenied);

	/* prepare parameters */
	setacl = false;
	if (cli->req.uri.query_len) {
		switch (hreq_is_query(&cli->req)) {
		case URIQ_ACL:
			setacl = true;
			break;
		default:
			err = InvalidURI;
			goto err_par;
		}
	}

	if ((rc = hreq_acl_canned(&cli->req)) == ACLCNUM) {
		err = InvalidArgument;
		goto err_par;
	}
	canacl = (rc == -1)? ACLC_PRIV: rc;

	/* begin trans */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto err_db;
	}

	memset(&key, 0, sizeof(key));
	memset(&val, 0, sizeof(val));
	memset(&ent, 0, sizeof(ent));
	strncpy(ent.name, bucket, sizeof(ent.name));
	strncpy(ent.owner, user, sizeof(ent.owner));
	ent.time_create = GUINT64_TO_LE(time(NULL));

	key.data = &ent.name;
	key.size = strlen(ent.name) + 1;

	val.data = &ent;
	val.size = sizeof(ent);

	if (setacl) {
		/* check if the bucket exists, else insert it */
		rc = bucket_find(txn, bucket, NULL, 0);
		if (rc) {
			if (rc != DB_NOTFOUND) {
				buckets->err(buckets, rc, "buckets->find");
				goto err_out;
			}

			rc = buckets->put(buckets, txn, &key, &val,
							DB_NOOVERWRITE);
			if (rc) {
				buckets->err(buckets, rc, "buckets->put");
				goto err_out;
			}
		} else {
			if (!has_access(user, bucket, NULL, "WRITE_ACP")) {
				err = AccessDenied;
				goto err_out;
			}
			if (!object_del_acls(txn, bucket, ""))
				goto err_out;
		}

	} else {
		/* attempt to insert new bucket */
		rc = buckets->put(buckets, txn, &key, &val, DB_NOOVERWRITE);
		if (rc) {
			if (rc == DB_KEYEXIST)
				err = BucketAlreadyExists;
			else
				buckets->err(buckets, rc, "buckets->put");
			goto err_out;
		}
	}

	/* insert bucket ACL */
	rc = add_access_canned(txn, bucket, "", user, canacl);
	if (rc) {
		acls->err(acls, rc, "acls->put");
		goto err_out;
	}

	/* commit -- no more exception emulation with goto. */
	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		return cli_err(cli, InternalError);
	}

	if (asprintf(&hdr,
"HTTP/%d.%d 200 x\r\n"
"Content-Length: 0\r\n"
"Date: %s\r\n"
"Location: /%s\r\n"
"Server: " PACKAGE_STRING "\r\n"
"\r\n",
		     cli->req.major,
		     cli->req.minor,
		     hutil_time2str(timestr, sizeof(timestr), time(NULL)),
		     bucket) < 0)
		return cli_err(cli, InternalError);

	rc = atcp_writeq(&cli->wst, hdr, strlen(hdr), atcp_cb_free, hdr);
	if (rc) {
		free(hdr);
		return true;
	}

	return atcp_write_start(&cli->wst);

err_out:
	rc = txn->abort(txn);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
err_db:
err_par:
	return cli_err(cli, err);
}
示例#5
0
unsigned int hashmap_find( hashmap_t *hashmap, hashmap_key_t key, hashmap_value_t * const value )
{
	bucket_t *bucket = hashmap_bucket_get( hashmap, key );
	return bucket_find( bucket, key, value );
}