Exemplo n.º 1
0
void qdb_close(qdb_handle_t h) {
    if (!h)
        return;
    if (h->vmname)
        free(h->vmname);
    free_path_list(h->watch_list);
    if (h->connected) {
#ifdef WIN32
        FlushFileBuffers(h->write_pipe);
        CloseHandle(h->write_pipe);
        CloseHandle(h->read_pipe);
#else
        shutdown(h->fd, SHUT_RDWR);
        close(h->fd);
#endif
    }
    free(h);
}
Exemplo n.º 2
0
/*
 * Free a plugin instance, i.e. release our private storage
 */
static bRC freePlugin(bpContext *ctx)
{
   plugin_ctx *p_ctx = (plugin_ctx *)ctx->pContext;
   if (!p_ctx) {
      return bRC_Error;
   }

   Dmsg(ctx, dbglvl, "cephfs-fd: entering freePlugin\n");

   if (p_ctx->path_list) {
      free_path_list(p_ctx->path_list);
      p_ctx->path_list = NULL;
   }

   if (p_ctx->dir_stack) {
      p_ctx->dir_stack->destroy();
      delete p_ctx->dir_stack;
   }

   if (p_ctx->cmount) {
      ceph_shutdown(p_ctx->cmount);
      p_ctx->cmount = NULL;
   }

   free_pool_memory(p_ctx->xattr_list);
   free_pool_memory(p_ctx->link_target);
   free_pool_memory(p_ctx->next_filename);
   free_pool_memory(p_ctx->cwd);

   if (p_ctx->conffile) {
      free(p_ctx->conffile);
   }

   if (p_ctx->plugin_options) {
      free(p_ctx->plugin_options);
   }

   free(p_ctx);
   p_ctx = NULL;

   Dmsg(ctx, dbglvl, "cephfs-fd: leaving freePlugin\n");

   return bRC_OK;
}
Exemplo n.º 3
0
/* map an "abstract" path: Don't do full path resolution. */
char *custom_map_abstract_path(
	ruletree_object_offset_t rule_list_offs,
	const char *binary_name,
	const char *virtual_orig_path,
	const char *func_name,
	int fn_class,
	const char **new_exec_policy_p)
{
	char			*mapping_result = NULL;
	path_mapping_context_t	ctx;
	struct path_entry_list	abs_virtual_source_path_list;
	int			min_path_len;
	ruletree_object_offset_t	rule_offs;

	if (!virtual_orig_path || (*virtual_orig_path != '/')) {
		SB_LOG(SB_LOGLEVEL_DEBUG,
			"%s: path '%s' is relative => return(NULL)",
			__func__, virtual_orig_path);
		return(NULL);
	}

	/* fill ctx */
	clear_path_mapping_context(&ctx);
	ctx.pmc_binary_name = binary_name;
	ctx.pmc_func_name = func_name;
	ctx.pmc_fn_class = fn_class;
	ctx.pmc_virtual_orig_path = virtual_orig_path;
	ctx.pmc_dont_resolve_final_symlink = 0;
	ctx.pmc_sb2ctx = get_sb2context();

	split_path_to_path_list(virtual_orig_path,
		&abs_virtual_source_path_list);

	if (is_clean_path(&abs_virtual_source_path_list) != 0) {
		SB_LOG(SB_LOGLEVEL_DEBUG,
			"%s: path '%s' is not a clean path => return(NULL)",
			__func__, virtual_orig_path);
		free_path_list(&abs_virtual_source_path_list);
		return(NULL);
	}

	rule_offs = ruletree_get_mapping_requirements(
		rule_list_offs, &ctx, &abs_virtual_source_path_list,
		&min_path_len, NULL/*call_translate_for_all_p*/,
		SB2_INTERFACE_CLASS_EXEC);
	SB_LOG(SB_LOGLEVEL_DEBUG, "%s: rule_offs = %u", __func__, rule_offs);

	if (rule_offs) {
		char   		*fallback_to_lua = NULL;
		const char	*new_exec_policy = NULL;
		int		flags;

		ctx.pmc_ruletree_offset = rule_offs;
		mapping_result = ruletree_translate_path(
			&ctx, SB_LOGLEVEL_DEBUG, virtual_orig_path, &flags,
			&new_exec_policy, &fallback_to_lua);
		if (new_exec_policy_p) *new_exec_policy_p = new_exec_policy;
		SB_LOG(SB_LOGLEVEL_DEBUG, "%s: mapping_result = %s", __func__,
			(mapping_result ? mapping_result : "NULL"));
	}
	free_path_list(&abs_virtual_source_path_list);

	return(mapping_result);
}
Exemplo n.º 4
0
char *qdb_read(qdb_handle_t h, char *path, unsigned int *value_len) {
    struct qdb_hdr hdr;
    char *value;
    uint32_t got_data;
    rw_ret_t ret;

    if (!h)
        return NULL;
    if (!verify_path(path))
        return NULL;

    hdr.type = QDB_CMD_READ;
    /* already verified string length */
#ifdef WIN32
    StringCbCopyA(hdr.path, sizeof(hdr.path), path);
#else
    strcpy(hdr.path, path);
#endif
    hdr.data_len = 0;
    if (!send_command_to_daemon(h, &hdr, NULL))
        /* some fatal error perhaps? */
        return NULL;
    if (!get_response(h, &hdr))
        return NULL;
    /* TODO: make this distinguishable from other errors */
    if (hdr.type == QDB_RESP_ERROR_NOENT) {
        errno = ENOENT;
        return NULL;
    }
    if (hdr.type == QDB_RESP_ERROR) {
        /* TODO? */
        assert(hdr.data_len == 0);
        return NULL;
    }
    assert(hdr.type == QDB_RESP_READ);
    /* +1 for terminating \0 */
    value = malloc(hdr.data_len+1);
    if (!value)
        return NULL;
    got_data = 0;
    while (got_data < hdr.data_len) {
#ifdef WIN32
        ret = hdr.data_len - got_data; // this function always reads the requested size
        if (!QioReadBuffer(h->read_pipe, value+got_data, hdr.data_len-got_data)) {
#else
        ret = read(h->fd, value+got_data, hdr.data_len-got_data);
        if (ret <= 0) {
#endif
            free(value);
            return NULL;
        }
        got_data += ret;
    }
    value[got_data] = '\0';

    if (value_len)
        *value_len = got_data;

    return value;
}

char **qdb_list(qdb_handle_t h, char *path, unsigned int *list_len) {
    struct qdb_hdr hdr;
    struct path_list *plist = NULL;
    struct path_list *plist_tmp;
    int count = 0;
    char **ret;

    if (!h)
        return NULL;
    if (!verify_path(path))
        return NULL;

    hdr.type = QDB_CMD_LIST;
    /* already verified string length */
#ifdef WIN32
    StringCbCopyA(hdr.path, sizeof(hdr.path), path);
#else
    strcpy(hdr.path, path);
#endif
    hdr.data_len = 0;
    if (!send_command_to_daemon(h, &hdr, NULL))
        /* some fatal error perhaps? */
        return NULL;

    /* receive entries (QDB_RESP_LIST messages) and add them to plist at the
     * beginning. This means that list will be in reverse order. */
    while (1) {
        if (!get_response(h, &hdr)) {
            free_path_list(plist);
            return NULL;
        }
        /* TODO: QDB_RESP_ERROR ? (current daemon do not send such response to
         * list */
        assert(hdr.type == QDB_RESP_LIST);
        if (!hdr.path[0])
            /* end of list */
            break;

        plist_tmp = malloc(sizeof(*plist_tmp));
        if (!plist_tmp) {
            /* OOM */
            free_path_list(plist);
            return NULL;
        }

        plist_tmp->path = strdup(hdr.path);
        if (!plist_tmp->path) {
            /* OOM */
            free_path_list(plist);
            return NULL;
        }
        plist_tmp->next = plist;
        plist = plist_tmp;
        count++;
    }
    ret = malloc((count+1) * sizeof(char*));
    if (!ret) {
        /* OOM */
        free_path_list(plist);
        return NULL;
    }

    /* End of table marker */
    ret[count] = NULL;

    if (list_len)
        *list_len = count;

    /* write responses to array, in reverse order so entries will be back
     * sorted */
    while (plist && count) {
        ret[--count] = plist->path;
        plist_tmp = plist;
        plist = plist->next;
        free(plist_tmp);
    }
    return ret;
}

char **qdb_multiread(qdb_handle_t h, char *path,
        unsigned int **values_len, unsigned int *list_len) {
    struct qdb_hdr hdr;
    int count = 0;
    char *value;
    uint32_t got_data;
    char **ret = NULL, **ret2;
    rw_ret_t read_ret;
    unsigned int *len_ret = NULL, *len_ret2;

    if (!h)
        return NULL;
    if (!verify_path(path))
        return NULL;

    hdr.type = QDB_CMD_MULTIREAD;
    /* already verified string length */
#ifdef WIN32
    StringCbCopyA(hdr.path, sizeof(hdr.path), path);
#else
    strcpy(hdr.path, path);
#endif
    hdr.data_len = 0;
    if (!send_command_to_daemon(h, &hdr, NULL))
        /* some fatal error perhaps? */
        return NULL;

    /* initial arrays */
    ret = malloc(2*sizeof(char*));
    if (!ret) {
        return NULL;
    }

    if (values_len) {
        len_ret = malloc(sizeof(unsigned int));
        if (!len_ret) {
            free(ret);
            return NULL;
        }
    }

    /* receive entries (QDB_RESP_MULTIREAD messages) */
    while (1) {
        if (!get_response(h, &hdr)) {
            free(ret);
            free(len_ret);
            return NULL;
        }
        assert(hdr.type == QDB_RESP_MULTIREAD);
        if (!hdr.path[0])
            /* end of list */
            break;

        /* +1 for terminating \0 */
        value = malloc(hdr.data_len+1);
        if (!value) {
            free(ret);
            free(len_ret);
            return NULL;
        }
        got_data = 0;
        while (got_data < hdr.data_len) {
#ifdef WIN32
            read_ret = hdr.data_len - got_data; // this function always reads the requested size
            if (!QioReadBuffer(h->read_pipe, value+got_data, hdr.data_len-got_data)) {
#else
            read_ret = read(h->fd, value+got_data, hdr.data_len-got_data);
            if (read_ret <= 0) {
#endif
                free(value);
                free(ret);
                free(len_ret);
                return NULL;
            }
            got_data += read_ret;
        }
        value[got_data] = '\0';

        /* (path+value)*count + NULL,NULL
         * Note that count is still unchanged */
        ret2 = realloc(ret, 2*(count+2)*sizeof(char*));
        if (!ret2) {
            free(ret);
            free(value);
            free(len_ret);
            return NULL;
        }
        ret = ret2;

        if (values_len) {
            len_ret2 = realloc(len_ret, (count+2)*sizeof(unsigned int));
            if (!len_ret2) {
                free(len_ret);
                free(value);
                free(ret);
                return NULL;
            }
            len_ret = len_ret2;
        }

        /* first path */
        ret[2*count] = strdup(hdr.path);
        /* then data */
        ret[2*count+1] = value;
        /* and data len if requested */
        if (values_len)
            len_ret[count] = hdr.data_len;
        count++;
    }

    /* End of table marker */
    ret[2*count] = NULL;
    ret[2*count+1] = NULL;

    if (values_len)
        *values_len = len_ret;
    if (list_len)
        *list_len = count;

    return ret;
}

/** Write single value to QubesDB, will override existing entry.
 */
int qdb_write(qdb_handle_t h, char *path, char *value, unsigned int value_len) {
    struct qdb_hdr hdr;

    if (!h)
        return 0;
    /* daemon will verify data anyway, but check here to return meaningful
     * error message */
    if (!verify_path(path))
        return 0;
    if (!value || value_len > QDB_MAX_DATA)
        return 0;

    hdr.type = QDB_CMD_WRITE;
    /* already verified string length */
#ifdef WIN32
    StringCbCopyA(hdr.path, sizeof(hdr.path), path);
#else
    strcpy(hdr.path, path);
#endif
    hdr.data_len = value_len;
    if (!send_command_to_daemon(h, &hdr, value))
        /* some fatal error perhaps? */
        return 0;
    if (!get_response(h, &hdr))
        return 0;
    if (hdr.type == QDB_RESP_ERROR) {
        /* TODO? */
        assert(hdr.data_len == 0);
        return 0;
    }
    assert(hdr.type == QDB_RESP_OK);
    assert(hdr.data_len == 0);
    return 1;
}

/** Common function for simple commands - only path as argument and no return data.
 * @param h Connection handle
 * @param path Entry path
 * @param cmd Command (hdr.type content)
 * @return 1 on success, 0 on failure
 */
static int qdb__simple_cmd(qdb_handle_t h, char *path, int cmd) {
    struct qdb_hdr hdr;

    if (!h)
        return 0;
    if (!verify_path(path))
        return 0;

    hdr.type = cmd;
    /* already verified string length */
#ifdef WIN32
    StringCbCopyA(hdr.path, sizeof(hdr.path), path);
#else
    strcpy(hdr.path, path);
#endif
    hdr.data_len = 0;

    if (!send_command_to_daemon(h, &hdr, NULL))
        /* some fatal error perhaps? */
        return 0;

    if (!get_response(h, &hdr))
        return 0;
    /* TODO: ignore NOENT for now */
    if (hdr.type == QDB_RESP_ERROR_NOENT) {
        return 1;
    }
    if (hdr.type == QDB_RESP_ERROR) {
        /* TODO? */
        assert(hdr.data_len == 0);
        return 0;
    }
    assert(hdr.type == QDB_RESP_OK);
    assert(hdr.data_len == 0);
    return 1;
}

int qdb_watch(qdb_handle_t h, char *path) {
    return qdb__simple_cmd(h, path, QDB_CMD_WATCH);
}

int qdb_unwatch(qdb_handle_t h, char *path) {
    return qdb__simple_cmd(h, path, QDB_CMD_UNWATCH);
}

int qdb_rm(qdb_handle_t h, char *path) {
    return qdb__simple_cmd(h, path, QDB_CMD_RM);
}

#ifdef WIN32
HANDLE
#else
int
#endif
qdb_watch_fd(qdb_handle_t h) {
#ifdef WIN32
    /* TODO: begin overlapped read operation and return event handle */
    /* TODO: for overlapped read, pipe should be opened in overlapped mode */
    return INVALID_HANDLE_VALUE;
#else
    if (!h->connected) {
        if (!connect_to_daemon(h)) {
            /* reconnect failed */
            errno = EPIPE;
            return -1;
        }
        /* FIXME: register watches again */
    }
    return h->fd;
#endif
}

char *qdb_read_watch(qdb_handle_t h) {
    struct qdb_hdr hdr;
    struct path_list *w;
    char *ret = NULL;
    int len;

    if (!h)
        return 0;

    /** already received event */
    if (h->watch_list) {
        w = h->watch_list;
        h->watch_list = w->next;
        ret = w->path;
        free(w);
    } else {
#ifdef WIN32
        len = sizeof(hdr);
        if (!QioReadBuffer(h->read_pipe, &hdr, sizeof(hdr))) {
#else
        if ((len=read(h->fd, &hdr, sizeof(hdr))) < sizeof(hdr)) {
#endif
            if (len==0)
                errno = EPIPE;
            return NULL;
        }
        /* only MULTIREAD is handled with multiple qdb_* calls, so if this
         * isn't WATCH we missed something */
        assert(hdr.type == QDB_RESP_WATCH);
        ret = strdup(hdr.path);
    }
    return ret;
}

#ifdef WIN32
void qdb_free(void *p) {
    free(p);
}