From: Jaroslav Kysela Date: Wed, 30 Aug 2017 18:43:06 +0000 (+0200) Subject: api: add missnig api_raw.c X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=454bf0600ca262c8a1631c167f9a30a0cb69466c;p=thirdparty%2Ftvheadend.git api: add missnig api_raw.c --- diff --git a/src/api/api_raw.c b/src/api/api_raw.c new file mode 100644 index 000000000..ca6e9858c --- /dev/null +++ b/src/api/api_raw.c @@ -0,0 +1,252 @@ +/* + * API - idnode raw load/save related API calls + * + * Copyright (C) 2017 Jaroslav Kysela + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "tvheadend.h" +#include "access.h" +#include "idnode.h" +#include "htsmsg.h" +#include "api.h" + +static int +api_idnode_raw_export_by_class0 + ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp ) +{ + int i; + const idclass_t *idc; + idnode_set_t *is; + idnode_t *in; + htsmsg_t *l, *e; + char filename[PATH_MAX]; + + /* Find class */ + idc = opaque; + assert(idc); + + l = htsmsg_create_list(); + if ((is = idnode_find_all(idc, NULL))) { + for (i = 0; i < is->is_count; i++) { + in = is->is_array[i]; + + if (idnode_perm(in, perm, NULL)) + continue; + + e = idnode_savefn(in, filename, sizeof(filename)); + + if (e) + htsmsg_add_msg(l, NULL, e); + + idnode_perm_unset(in); + } + free(is->is_array); + free(is); + } + + *resp = htsmsg_create_map(); + htsmsg_add_msg(*resp, "entries", l); + + return 0; +} + +static int +api_idnode_raw_export + ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp ) +{ + int err = 0, count = 0; + idnode_t *in; + htsmsg_t *uuids, *l = NULL, *m; + htsmsg_field_t *f; + const char *uuid = NULL, *class; + char filename[PATH_MAX]; + + /* Class based */ + if ((class = htsmsg_get_str(args, "class"))) { + const idclass_t *idc; + pthread_mutex_lock(&global_lock); + idc = idclass_find(class); + if (idc) + err = api_idnode_raw_export_by_class0(perm, (void*)idc, NULL, args, resp); + else + err = EINVAL; + pthread_mutex_unlock(&global_lock); + return err; + } + + /* UUIDs */ + if (!(f = htsmsg_field_find(args, "uuid"))) + return EINVAL; + if (!(uuids = htsmsg_field_get_list(f))) + if (!(uuid = htsmsg_field_get_str(f))) + return EINVAL; + + pthread_mutex_lock(&global_lock); + + /* Multiple */ + if (uuids) { + const idnodes_rb_t *domain = NULL; + l = htsmsg_create_list(); + HTSMSG_FOREACH(f, uuids) { + if (!(uuid = htsmsg_field_get_str(f))) continue; + if (!(in = idnode_find(uuid, NULL, domain))) continue; + domain = in->in_domain; + if (idnode_perm(in, perm, NULL)) { + err = EPERM; + continue; + } + m = idnode_savefn(in, filename, sizeof(filename)); + if (m) + htsmsg_add_msg(l, NULL, m); + count++; + idnode_perm_unset(in); + } + + if (count) + err = 0; + + /* Single */ + } else { + l = htsmsg_create_list(); + if ((in = idnode_find(uuid, NULL, NULL)) != NULL) { + if (idnode_perm(in, perm, NULL)) { + err = EPERM; + } else { + m = idnode_savefn(in, filename, sizeof(filename)); + if (m) + htsmsg_add_msg(l, NULL, m); + idnode_perm_unset(in); + } + } + } + + if (l && err == 0) { + *resp = htsmsg_create_map(); + htsmsg_add_msg(*resp, "entries", l); + } else { + htsmsg_destroy(l); + } + + pthread_mutex_unlock(&global_lock); + + return err; +} + +static int +api_idnode_raw_import + ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp ) +{ + int err = EINVAL; + idnode_t *in; + htsmsg_t *msg, *conf; + htsmsg_field_t *f; + const char *uuid; + int count = 0; + const idnodes_rb_t *domain = NULL; + + if (!(f = htsmsg_field_find(args, "node"))) + return EINVAL; + if (!(msg = htsmsg_field_get_list(f))) + if (!(msg = htsmsg_field_get_map(f))) + return EINVAL; + + pthread_mutex_lock(&global_lock); + + /* Single or Foreach */ + if (!msg->hm_islist) { + + if (!(uuid = htsmsg_get_str(msg, "uuid"))) { + + /* Foreach */ + f = htsmsg_field_find(msg, "uuid"); + if (!f || !(conf = htsmsg_field_get_list(f))) + goto exit; + HTSMSG_FOREACH(f, conf) { + if (!(uuid = htsmsg_field_get_str(f))) + continue; + if (!(in = idnode_find(uuid, NULL, domain))) + continue; + domain = in->in_domain; + if (idnode_perm(in, perm, msg)) { + err = EPERM; + continue; + } + count++; + idnode_update(in, msg); + idnode_perm_unset(in); + } + if (count) + err = 0; + + } else { + + if (!(in = idnode_find(uuid, NULL, NULL))) + goto exit; + if (idnode_perm(in, perm, msg)) { + err = EPERM; + goto exit; + } + idnode_update(in, msg); + idnode_perm_unset(in); + err = 0; + + } + + /* Multiple */ + } else { + + HTSMSG_FOREACH(f, msg) { + if (!(conf = htsmsg_field_get_map(f))) + continue; + if (!(uuid = htsmsg_get_str(conf, "uuid"))) + continue; + if (!(in = idnode_find(uuid, NULL, domain))) + continue; + domain = in->in_domain; + if (idnode_perm(in, perm, conf)) { + err = EPERM; + continue; + } + count++; + idnode_update(in, conf); + idnode_perm_unset(in); + } + if (count) + err = 0; + + } + + // TODO: return updated UUIDs? + +exit: + pthread_mutex_unlock(&global_lock); + + return err; +} + +void api_idnode_raw_init ( void ) +{ + /* + * note: permissions are verified using idnode_perm() calls + */ + static api_hook_t ah[] = { + { "raw/export", ACCESS_ANONYMOUS, api_idnode_raw_export, NULL }, + { "raw/import", ACCESS_ANONYMOUS, api_idnode_raw_import, NULL }, + { NULL }, + }; + + api_register_all(ah); +}