Skip to content
Snippets Groups Projects
Commit d3da32ec authored by Amin Ben Ramdhane's avatar Amin Ben Ramdhane
Browse files

opkgd: initial release

the methods that will be generated :
    'softwaremanagement' @14751784
    	"environment":{}
    	"install":{"path":"String","environment":"String"}
    	"remove":{"name":"String","environment":"String"}
    	"du_install":{"url":"String","uuid":"String","username":"String","password":"String","environment":"String"}
    	"du_update":{"uuid":"String","url":"String","version":"String","username":"String","password":"String"}
    	"du_uninstall":{"name":"String","environment":"String"}
    	"du_list":{"index":"Integer"}
    	"eu_list":{}
parent b0715a81
Branches
No related tags found
No related merge requests found
Makefile 0 → 100644
PROG = opkgd
OBJS =opkg.o common.o
PROG_CFLAGS = $(CFLAGS) -fstrict-aliasing -Wall -Wextra
PROG_LDFLAGS = $(LDFLAGS)
PROG_LDFLAGS += -luci -lubus -lubox -ljson-c -lblobmsg_json -luuid
%.o: %.c
$(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $<
all: opkgd
opkgd: $(OBJS)
$(CC) $(PROG_LDFLAGS) -o $@ $^
clean:
rm -f *.o $(PROG)
common.c 0 → 100644
/*
* common.c: OPKG deamon
*
* Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
*
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "common.h"
static struct uci_context *uci_ctx_opkg = NULL;
int opkg_uci_init(void)
{
uci_ctx_opkg = uci_alloc_context();
if (!uci_ctx_opkg) {
return -1;
}
uci_add_delta_path(uci_ctx_opkg, uci_ctx_opkg->savedir);
uci_set_savedir(uci_ctx_opkg, OPKG_SAVEDIR_PATH);
uci_set_confdir(uci_ctx_opkg, OPKG_CONFDIR_PATH);
return 0;
}
int opkg_uci_fini(void)
{
if (uci_ctx_opkg) {
uci_free_context(uci_ctx_opkg);
}
return 0;
}
static bool opkg_uci_validate_section(const char *str)
{
if (!*str)
return false;
for (; *str; str++) {
unsigned char c = *str;
if (isalnum(c) || c == '_')
continue;
return false;
}
return true;
}
static int opkg_uci_init_ptr(struct uci_ptr *ptr, char *package, char *section, char *option, char *value)
{
memset(ptr, 0, sizeof(struct uci_ptr));
/* value */
if (value) {
ptr->value = value;
}
ptr->package = package;
if (!ptr->package)
goto error;
ptr->section = section;
if (!ptr->section) {
ptr->target = UCI_TYPE_PACKAGE;
goto lastval;
}
ptr->option = option;
if (!ptr->option) {
ptr->target = UCI_TYPE_SECTION;
goto lastval;
} else {
ptr->target = UCI_TYPE_OPTION;
}
lastval:
if (ptr->section && !opkg_uci_validate_section(ptr->section))
ptr->flags |= UCI_LOOKUP_EXTENDED;
return 0;
error:
return -1;
}
struct uci_section *opkg_uci_walk_section(char *package, char *section_type, struct uci_section *prev_section)
{
struct uci_ptr ptr;
struct uci_element *e;
struct uci_section *next_section;
if (section_type == NULL) {
if (prev_section) {
e = &prev_section->e;
if (e->list.next == &prev_section->package->sections)
return NULL;
e = container_of(e->list.next, struct uci_element, list);
next_section = uci_to_section(e);
return next_section;
}
else {
if (opkg_uci_init_ptr(&ptr, package, NULL, NULL, NULL)) {
return NULL;
}
if (uci_lookup_ptr(uci_ctx_opkg, &ptr, NULL, true) != UCI_OK) {
return NULL;
}
if (ptr.p->sections.next == &ptr.p->sections)
return NULL;
e = container_of(ptr.p->sections.next, struct uci_element, list);
next_section = uci_to_section(e);
return next_section;
}
}
else {
struct uci_list *ul = NULL, *shead = NULL;
if (prev_section) {
ul = &prev_section->e.list;
shead = &prev_section->package->sections;
}
else {
if (opkg_uci_init_ptr(&ptr, package, NULL, NULL, NULL)) {
return NULL;
}
if (uci_lookup_ptr(uci_ctx_opkg, &ptr, NULL, true) != UCI_OK) {
return NULL;
}
ul = &ptr.p->sections;
shead = &ptr.p->sections;
}
while (ul->next != shead) {
e = container_of(ul->next, struct uci_element, list);
next_section = uci_to_section(e);
if (strcmp(next_section->type, section_type) == 0)
return next_section;
ul = ul->next;
}
return NULL;
}
return NULL;
}
void opkg_uci_print_list(struct uci_list *uh, char **val, char *delimiter)
{
struct uci_element *e;
static char buffer[512];
char *buf = buffer;
*buf = '\0';
uci_foreach_element(uh, e) {
if (*buf) {
strcat(buf, delimiter);
strcat(buf, e->name);
}
else
strcpy(buf, e->name);
}
*val = buf;
}
struct uci_element *opkg_uci_lookup_list(struct uci_list *list, const char *name)
{
struct uci_element *e;
uci_foreach_element(list, e) {
if (!strcmp(e->name, name))
return e;
}
return NULL;
}
int opkg_uci_lookup_ptr_by_section(struct uci_ptr *ptr, struct uci_section *section, char *option, char *value)
{
struct uci_element *e;
memset(ptr, 0, sizeof(struct uci_ptr));
ptr->package = section->package->e.name;
ptr->section = section->e.name;
ptr->option = option;
ptr->value = value;
ptr->flags |= UCI_LOOKUP_DONE;
ptr->p = section->package;
ptr->s = section;
if (ptr->option) {
e = opkg_uci_lookup_list(&ptr->s->options, ptr->option);
if (!e)
return UCI_OK;
ptr->o = uci_to_option(e);
ptr->last = e;
ptr->target = UCI_TYPE_OPTION;
}
else {
ptr->last = &ptr->s->e;
ptr->target = UCI_TYPE_SECTION;
}
ptr->flags |= UCI_LOOKUP_COMPLETE;
return UCI_OK;
}
char *opkg_uci_get_value_by_section(struct uci_section *section, char *option)
{
struct uci_ptr ptr;
char *val = "";
if (opkg_uci_lookup_ptr_by_section(&ptr, section, option, NULL) != UCI_OK)
return val;
if (!ptr.o)
return val;
if(ptr.o->type == UCI_TYPE_LIST) {
opkg_uci_print_list(&ptr.o->v.list, &val, " ");
return val;
}
if (ptr.o->v.string)
return ptr.o->v.string;
else
return val;
}
char *opkg_uci_set_value_by_section(struct uci_section *section, char *option, char *value)
{
struct uci_ptr ptr;
int ret = UCI_OK;
if (section == NULL)
return "";
if (opkg_uci_lookup_ptr_by_section(&ptr, section, option, value) != UCI_OK)
return "";
uci_set(uci_ctx_opkg, &ptr);
if (ret == UCI_OK)
ret = uci_save(uci_ctx_opkg, ptr.p);
if (ptr.o && ptr.o->v.string)
return ptr.o->v.string;
return "";
}
struct uci_section *opkg_uci_add_section(char *package, char *section_type)
{
struct uci_ptr ptr;
struct uci_section *s = NULL;
if (opkg_uci_init_ptr(&ptr, package, NULL, NULL, NULL))
return NULL;
if (uci_lookup_ptr(uci_ctx_opkg, &ptr, NULL, true) != UCI_OK)
return NULL;
int ret = uci_add_section(uci_ctx_opkg, ptr.p, section_type, &s);
if (ret != UCI_OK)
return NULL;
return s;
}
int opkg_uci_delete_by_section(struct uci_section *section, char *option, char *value)
{
struct uci_ptr ptr = {0};
if (section == NULL)
return -1;
if (opkg_uci_lookup_ptr_by_section(&ptr, section, option, value) != UCI_OK)
return -1;
if (uci_delete(uci_ctx_opkg, &ptr) != UCI_OK)
return -1;
return 0;
}
void remove_newline(char *buf)
{
int len;
len = strlen(buf) - 1;
if (buf[len] == '\n')
buf[len] = 0;
}
char *get_package_name(char *full_name)
{
static char name[32] = "";
strncpy(name, full_name, sizeof(name));
char *dot = strchr(name, '.');
if (dot)
*dot = '\0';
return name;
}
int isfileexist(const char *filepath)
{
if( access( filepath, F_OK ) != -1 )
return 1;
else
return 0;
}
int islxcrunning(char *lxc_name)
{
char command[256], state[16];
FILE *in;
if (isfileexist(LXC_INFO)) {
snprintf(command, sizeof(command), "lxc-info -n %s | grep State | tr -d ' ' | awk -F':' '{print$2}'", lxc_name);
if ((in = popen(command, "r"))) {
fgets(state, sizeof(state), in);
pclose(in);
remove_newline(state);
}
if (strcmp(state, "RUNNING") == 0)
return 1;
else
return 0;
}
return 0;
}
char *convert_url(char *url, char *username, char *password)
{
static char buf[256] = "";
if (strncmp(url, "http://", 7) == 0)
snprintf(buf, sizeof(buf), "http://%s:%s@%s", username, password, url+7);
else if (strncmp(url, "ftp://", 6) == 0)
snprintf(buf, sizeof(buf), "ftp://%s:%s@%s", username, password, url+6);
return buf;
}
char *generate_uuid(void)
{
uuid_t binuuid;
uuid_generate_random(binuuid);
char *uuid = malloc(37);
uuid_unparse(binuuid, uuid);
return uuid;
}
char *generate_duid(bool sysnchronise, int number)
{
char buf[36] = "0123456789abcdefghijklmnopqrstuvwxyz", euid[64] = "", euid_num[8] = "";
int i;
srand(time(NULL));
if (sysnchronise) {
for (i = 0; i < 59; i++)
euid[i] = buf[rand() % 35];
euid[59] = '\0';
sprintf(euid_num, "%04d", number);
strcat(euid, euid_num);
} else {
for (i = 0; i < 62; i++)
euid[i] = buf[rand() % 35];
euid[63] = '\0';
}
return strdup(euid);
}
int synchronize_deployment_units_with_map_du_file(void)
{
struct uci_section *s = NULL, *stmp = NULL;
char path[256], line[256], name[64], version[64], command[256];
FILE *log;
DIR *dir;
struct dirent *ent;
int found, incr = 0;
opkg_uci_foreach_section_safe("map_du", "deployment", stmp, s) {
char *map_du_name = opkg_uci_get_value_by_section(s, "name");
char *map_du_env = opkg_uci_get_value_by_section(s, "environment");
if (strcmp(map_du_env, "OpenWRT_Linux") == 0)
snprintf(path, sizeof(path), "%s/%s.control", OPKG_INFO_PATH, map_du_name);
else
snprintf(path, sizeof(path), "%s/%s/rootfs/%s/%s.control", LXC_PATH, map_du_env, OPKG_INFO_PATH, map_du_name);
if (!isfileexist(path))
opkg_uci_delete_by_section(s, NULL, NULL);
}
if ((log = popen("opkg list", "r"))) {
while(fgets(line, sizeof(line), log) != NULL) {
found = 0;
if (sscanf(line, "%63s - %63s", name, version)) {
opkg_uci_foreach_section("map_du", "deployment", s) {
char *map_name = opkg_uci_get_value_by_section(s, "name");
char *map_env = opkg_uci_get_value_by_section(s, "environment");
if ((strcmp(map_name, name) == 0) && (strcmp(map_env, "OpenWRT_Linux") == 0)) {
found = 1;
break;
}
}
if (found)
continue;
struct uci_section *new_s = opkg_uci_add_section("map_du", "deployment");
char *uuid = generate_uuid();
char *duid = generate_duid(true, incr);
incr++;
opkg_uci_set_value_by_section(new_s, "name", name);
opkg_uci_set_value_by_section(new_s, "version", version);
opkg_uci_set_value_by_section(new_s, "uuid", uuid);
opkg_uci_set_value_by_section(new_s, "duid", duid);
opkg_uci_set_value_by_section(new_s, "environment", "OpenWRT_Linux");
FREE(uuid);
FREE(duid);
}
}
pclose(log);
}
if (isfileexist(LXC_PATH)) {
sysfs_foreach_file(LXC_PATH, dir, ent) {
if ((strstr(ent->d_name, ".")) || (!islxcrunning(ent->d_name)))
continue;
snprintf(command, sizeof(command), "lxc-attach -n %s -- opkg list", ent->d_name);
if ((log = popen(command, "r"))) {
while(fgets(line, sizeof(line), log) != NULL) {
found = 0;
if (sscanf(line, "%63s - %63s", name, version)) {
opkg_uci_foreach_section("map_du", "deployment", s) {
char *map_name = opkg_uci_get_value_by_section(s, "name");
char *map_env = opkg_uci_get_value_by_section(s, "environment");
if ((strcmp(map_name, name) == 0) && (strcmp(map_env, ent->d_name) == 0)) {
found = 1;
break;
}
}
if (found)
continue;
struct uci_section *new_s = opkg_uci_add_section("map_du", "deployment");
char *uuid = generate_uuid();
char *duid = generate_duid(true, incr);
incr++;
opkg_uci_set_value_by_section(new_s, "name", name);
opkg_uci_set_value_by_section(new_s, "version", version);
opkg_uci_set_value_by_section(new_s, "uuid", uuid);
opkg_uci_set_value_by_section(new_s, "duid", duid);
opkg_uci_set_value_by_section(new_s, "environment", ent->d_name);
FREE(uuid);
FREE(duid);
}
}
pclose(log);
}
}
if (dir) closedir(dir);
}
return 0;
}
void opkg_add_data_to_list(struct list_head *dup_list, char *cmd, int pid, unsigned int vsize)
{
struct process_res *proc;
proc = calloc(1, sizeof(struct process_res));
list_add_tail(&proc->list, dup_list);
proc->cmd = strdup(cmd);
proc->pid = pid;
proc->vsize= vsize;
}
static void opkg_delete_data_from_list(struct process_res *proc)
{
list_del(&proc->list);
FREE(proc->cmd);
FREE(proc);
}
void opkg_free_data_from_list(struct list_head *dup_list)
{
struct process_res *proc;
while (dup_list->next != dup_list) {
proc = list_entry(dup_list->next, struct process_res, list);
opkg_delete_data_from_list(proc);
}
}
common.h 0 → 100644
/*
* common.h: OPKG deamon
*
* Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
*
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef __COMMON_H
#define __COMMON_H
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <dirent.h>
#include <uuid/uuid.h>
#include <ctype.h>
#include <unistd.h>
#include <uci.h>
#include <libubox/list.h>
#define OPKG_SAVEDIR_PATH "/etc/opkg"
#define OPKG_CONFDIR_PATH "/etc/opkg"
#define OPKG_INFO_PATH "/usr/lib/opkg/info"
#define DEPLOYMENT_UNIT_PATH "/etc/opkg/map_du"
#define PROC_PATH "/proc"
#define LXC_PATH "/srv/lxc"
#define LXC_INFO "/usr/bin/lxc-info"
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
#define sysfs_foreach_file(path,dir,ent) \
if ((dir = opendir(path)) == NULL) return 0; \
while ((ent = readdir (dir)) != NULL) \
#ifndef FREE
#define FREE(x) do { if(x) {free(x); x = NULL;} } while (0)
#endif
struct process_res
{
struct list_head list;
char *cmd;
int pid;
unsigned int vsize;
};
int opkg_uci_init(void);
int opkg_uci_fini(void);
struct uci_section *opkg_uci_walk_section(char *package, char *section_type, struct uci_section *prev_section);
struct uci_section *opkg_uci_add_section(char *package, char *section_type);
int opkg_uci_delete_by_section(struct uci_section *section, char *option, char *value);
char *opkg_uci_get_value_by_section(struct uci_section *section, char *option);
char *opkg_uci_set_value_by_section(struct uci_section *section, char *option, char *value);
char *get_package_name(char *full_name);
int isfileexist(const char *filepath);
int synchronize_deployment_units_with_map_du_file(void);
char *convert_url(char *url, char *username, char *password);
char *generate_uuid(void);
char *generate_duid(bool sysnchronise, int number);
void remove_newline(char *buf);
int islxcrunning(char *lxc_name);
void opkg_add_data_to_list(struct list_head *dup_list, char *cmd, int pid, unsigned int vsize);
void opkg_free_data_from_list(struct list_head *dup_list);
#define opkg_uci_foreach_section(package, section_type, section) \
for (section = opkg_uci_walk_section(package, section_type, NULL); \
section != NULL; \
section = opkg_uci_walk_section(package, section_type, section))
#define opkg_uci_foreach_section_safe(package, section_type, _tmp, section) \
for(section = opkg_uci_walk_section(package, section_type, NULL), \
_tmp = (section) ? opkg_uci_walk_section(package, section_type, section) : NULL; \
section != NULL; \
section = _tmp, _tmp = (section) ? opkg_uci_walk_section(package, section_type, section) : NULL)
#endif //__COMMON_H
opkg.c 0 → 100644
/*
* main.c: OPKG deamon
*
* Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
*
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <stdio.h>
#include <unistd.h>
#include <libubox/blobmsg.h>
#include <libubox/uloop.h>
#include <libubus.h>
#include "common.h"
static int opkg_software_environment(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
void *a, *t;
DIR *dir;
struct dirent *ent;
FILE *in;
char buf[64], vendor[64], version[64], command[256];
char allocateddiskspace[10], availablediskspace[10], allocated_memory[10], available_memory[10];
struct blob_buf bb;
memset(&bb,0,sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
a = blobmsg_open_array(&bb, "environment");
t = blobmsg_open_table(&bb, "");
blobmsg_add_string(&bb, "name", "OpenWRT_Linux");
blobmsg_add_string(&bb, "status", "Up");
blobmsg_add_string(&bb, "type", "Linux");
if ((in = popen("uname -o", "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(vendor, buf, sizeof(vendor));
}
blobmsg_add_string(&bb, "vendor", vendor);
if ((in = popen("uname -r", "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(version, buf, sizeof(version));
}
blobmsg_add_string(&bb, "version", version);
if ((in = popen("free | grep Mem | awk '{print$2}'", "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(allocateddiskspace, buf, sizeof(allocateddiskspace));
}
blobmsg_add_u32(&bb, "allocateddiskspace", atoi(allocateddiskspace));
if ((in = popen("free | grep Mem | awk '{print$4}'", "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(availablediskspace, buf, sizeof(availablediskspace));
}
blobmsg_add_u32(&bb, "availablediskspace", atoi(availablediskspace));
if ((in = popen("df | grep overlayfs | awk '{print$2}'", "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(allocated_memory, buf, sizeof(allocated_memory));
}
blobmsg_add_u32(&bb, "allocatedmemory", atoi(allocated_memory));
if ((in = popen("df | grep overlayfs | awk '{print$4}'", "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(available_memory, buf, sizeof(available_memory));
}
blobmsg_add_u32(&bb, "availablememory", atoi(available_memory));
blobmsg_close_table(&bb, t);
if (isfileexist(LXC_PATH)) {
sysfs_foreach_file(LXC_PATH, dir, ent) {
if (strstr(ent->d_name, "."))
continue;
t = blobmsg_open_table(&bb, "");
blobmsg_add_string(&bb, "name", ent->d_name);
if (islxcrunning(ent->d_name))
blobmsg_add_string(&bb, "status", "Up");
else
blobmsg_add_string(&bb, "status", "Disabled");
blobmsg_add_string(&bb, "type", "Linux Container");
if (islxcrunning(ent->d_name))
blobmsg_add_string(&bb, "vendor", "");
else {
snprintf(command, sizeof(command), "lxc-attach -n %s -- uname -o", ent->d_name);
if ((in = popen(command, "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(vendor, buf, sizeof(vendor));
}
blobmsg_add_string(&bb, "vendor", vendor);
}
if (islxcrunning(ent->d_name))
blobmsg_add_string(&bb, "version", "");
else {
snprintf(command, sizeof(command), "lxc-attach -n %s -- uname -r", ent->d_name);
if ((in = popen(command, "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(version, buf, sizeof(version));
}
blobmsg_add_string(&bb, "version", version);
}
if (islxcrunning(ent->d_name))
blobmsg_add_u32(&bb, "allocateddiskspace", 0);
else {
snprintf(command, sizeof(command), "lxc-attach -n %s -- free | grep Mem | awk '{print$2}'", ent->d_name);
if ((in = popen(command, "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(allocateddiskspace, buf, sizeof(allocateddiskspace));
}
blobmsg_add_u32(&bb, "allocateddiskspace", atoi(allocateddiskspace));
}
if (islxcrunning(ent->d_name))
blobmsg_add_u32(&bb, "availablediskspace", 0);
else {
snprintf(command, sizeof(command), "lxc-attach -n %s -- free | grep Mem | awk '{print$4}'", ent->d_name);
if ((in = popen(command, "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(availablediskspace, buf, sizeof(availablediskspace));
}
blobmsg_add_u32(&bb, "availablediskspace", atoi(availablediskspace));
}
if (islxcrunning(ent->d_name))
blobmsg_add_u32(&bb, "allocatedmemory", 0);
else {
snprintf(command, sizeof(command), "lxc-attach -n %s -- df | grep overlayfs | awk '{print$2}'", ent->d_name);
if ((in = popen(command, "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(allocated_memory, buf, sizeof(allocated_memory));
}
blobmsg_add_u32(&bb, "allocatedmemory", atoi(allocated_memory));
}
if (islxcrunning(ent->d_name))
blobmsg_add_u32(&bb, "availablememory", 0);
else {
snprintf(command, sizeof(command), "lxc-attach -n %s -- df | grep overlayfs | awk '{print$4}'", ent->d_name);
if ((in = popen(command, "r"))) {
fgets(buf, sizeof(buf), in);
pclose(in);
remove_newline(buf);
strncpy(available_memory, buf, sizeof(available_memory));
}
blobmsg_add_u32(&bb, "availablememory", atoi(available_memory));
}
blobmsg_close_table(&bb, t);
}
if (dir) closedir(dir);
}
blobmsg_close_array(&bb, a);
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
return 0;
}
enum {
INSTALL_PATH,
INSTALL_ENV,
__INSTALL_MAX
};
static const struct blobmsg_policy install_policy[__INSTALL_MAX] = {
[INSTALL_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
[INSTALL_ENV] = { .name = "environment", .type = BLOBMSG_TYPE_STRING },
};
static int opkg_install(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__INSTALL_MAX] = {NULL};
char line[512], command[512], package_path[256];
struct blob_buf bb;
struct dirent *ent;
DIR *dir;
FILE *log;
int found;
if(blobmsg_parse(install_policy, __INSTALL_MAX, tb, blob_data(msg), blob_len(msg)))
return UBUS_STATUS_UNKNOWN_ERROR;
if (tb[INSTALL_PATH]) {
strncpy(package_path, blobmsg_get_string(tb[INSTALL_PATH]), sizeof(package_path));
if (!isfileexist(package_path))
return UBUS_STATUS_INVALID_ARGUMENT;
} else {
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (tb[INSTALL_ENV]) {
found = 0;
if (strcmp(blobmsg_get_string(tb[INSTALL_ENV]), "OpenWRT_Linux") != 0) {
if (isfileexist(LXC_PATH)) {
sysfs_foreach_file(LXC_PATH, dir, ent) {
if (strcmp(blobmsg_get_string(tb[INSTALL_ENV]), ent->d_name) == 0) {
found = 1;
break;
}
}
if (dir) closedir(dir);
if (!found)
return UBUS_STATUS_INVALID_ARGUMENT;
} else
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (found) {
if (islxcrunning(blobmsg_get_string(tb[INSTALL_ENV])))
snprintf(command, sizeof(command), "lxc-attach -n %s -- opkg install %s 2>/dev/null", blobmsg_get_string(tb[INSTALL_ENV]), package_path);
else
return UBUS_STATUS_INVALID_ARGUMENT;
} else
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", package_path);
} else {
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", package_path);
}
memset(&bb,0,sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
if ((log = popen(command, "r"))) {
while (fgets(line, sizeof(line), log) != NULL) {
if (strstr(line, "Configuring")) {
blobmsg_add_u8(&bb,"status", true);
break;
} else if (strstr(line, "Unknown package")) {
blobmsg_add_u8(&bb,"status", false);
blobmsg_add_string(&bb, "error", "Cannot install package");
break;
} else if (strstr(line, "up to date")) {
blobmsg_add_u8(&bb,"status", false);
blobmsg_add_string(&bb, "error", "This package is already installed with the same version");
break;
} else if (strstr(line, "Not downgrading package")) {
blobmsg_add_u8(&bb,"status", false);
blobmsg_add_string(&bb, "error", "Cannot downgrade package");
break;
} else {
blobmsg_add_u8(&bb,"status", false);
blobmsg_add_string(&bb, "error", "dependencies package");
break;
}
}
pclose(log);
}
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
return 0;
}
enum {
REMOVE_NAME,
REMOVE_ENV,
__REMOVE_MAX
};
static const struct blobmsg_policy remove_policy[__REMOVE_MAX] = {
[REMOVE_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
[REMOVE_ENV] = { .name = "environment", .type = BLOBMSG_TYPE_STRING },
};
static int opkg_remove(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__REMOVE_MAX] = {NULL};
struct blob_buf bb;
char line[512], command[256];
struct dirent *ent;
DIR *dir;
FILE *log;
int found;
if(blobmsg_parse(remove_policy, __REMOVE_MAX, tb, blob_data(msg), blob_len(msg)))
return UBUS_STATUS_UNKNOWN_ERROR;
if (!tb[REMOVE_NAME])
return UBUS_STATUS_INVALID_ARGUMENT;
if (tb[REMOVE_ENV]) {
found = 0;
if (strcmp(blobmsg_get_string(tb[REMOVE_ENV]), "OpenWRT_Linux") != 0) {
if (isfileexist(LXC_PATH)) {
sysfs_foreach_file(LXC_PATH, dir, ent) {
if (strcmp(blobmsg_get_string(tb[REMOVE_ENV]), ent->d_name) == 0) {
found = 1;
break;
}
}
if (dir) closedir(dir);
if (!found)
return UBUS_STATUS_INVALID_ARGUMENT;
} else
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (found) {
if (islxcrunning(blobmsg_get_string(tb[REMOVE_ENV])))
snprintf(command, sizeof(command), "lxc-attach -n %s -- opkg install %s 2>/dev/null", blobmsg_get_string(tb[REMOVE_ENV]), blobmsg_get_string(tb[REMOVE_NAME]));
else
return UBUS_STATUS_INVALID_ARGUMENT;
} else
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", blobmsg_get_string(tb[REMOVE_NAME]));
} else {
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", blobmsg_get_string(tb[REMOVE_NAME]));
}
memset(&bb,0,sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
if ((log = popen(command, "r"))) {
while(fgets(line, sizeof(line), log) != NULL) {
if (strstr(line, "Removing package")) {
blobmsg_add_u8(&bb,"status", true);
break;
} else if (strstr(line, "No packages removed")) {
blobmsg_add_u8(&bb,"status", false);
blobmsg_add_string(&bb, "error", "Cannot remove package");
break;
}
}
pclose(log);
}
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
return 0;
}
enum {
DU_INSTALL_URL,
DU_INSTALL_UUID,
DU_INSTALL_USERNAME,
DU_INSTALL_PASSWORD,
DU_INSTALL_ENV,
__DU_INSTALL_MAX
};
static const struct blobmsg_policy du_install_policy[__DU_INSTALL_MAX] = {
[DU_INSTALL_URL] = { .name = "url", .type = BLOBMSG_TYPE_STRING },
[DU_INSTALL_UUID] = { .name = "uuid", .type = BLOBMSG_TYPE_STRING },
[DU_INSTALL_USERNAME] = { .name = "username", .type = BLOBMSG_TYPE_STRING },
[DU_INSTALL_PASSWORD] = { .name = "password", .type = BLOBMSG_TYPE_STRING },
[DU_INSTALL_ENV] = { .name = "environment", .type = BLOBMSG_TYPE_STRING },
};
static int opkg_du_install(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__DU_INSTALL_MAX] = {NULL};
char line[512], command[512], name[64], version[64];
DIR *dir;
struct dirent *ent;
struct blob_buf bb;
int i = 0, found;
FILE *log;
if(blobmsg_parse(du_install_policy, __DU_INSTALL_MAX, tb, blob_data(msg), blob_len(msg)))
return UBUS_STATUS_UNKNOWN_ERROR;
if (!tb[DU_INSTALL_URL])
return UBUS_STATUS_INVALID_ARGUMENT;
if (tb[DU_INSTALL_ENV]) {
found = 0;
if (strcmp(blobmsg_get_string(tb[DU_INSTALL_ENV]), "OpenWRT_Linux") != 0) {
if (isfileexist(LXC_PATH)) {
sysfs_foreach_file(LXC_PATH, dir, ent) {
if (strcmp(blobmsg_get_string(tb[DU_INSTALL_ENV]), ent->d_name) == 0) {
found = 1;
break;
}
}
if (dir) closedir(dir);
if (!found)
return UBUS_STATUS_INVALID_ARGUMENT;
} else
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (found) {
if (islxcrunning(blobmsg_get_string(tb[DU_INSTALL_ENV]))) {
if (tb[DU_INSTALL_USERNAME] &&
*(blobmsg_get_string(tb[DU_INSTALL_USERNAME])) != '\0' &&
tb[DU_INSTALL_PASSWORD] &&
*(blobmsg_get_string(tb[DU_INSTALL_PASSWORD])) != '\0') {
char *url = convert_url(blobmsg_get_string(tb[DU_INSTALL_URL]), blobmsg_get_string(tb[DU_INSTALL_USERNAME]), blobmsg_get_string(tb[DU_INSTALL_PASSWORD]));
snprintf(command, sizeof(command), "lxc-attach -n %s -- opkg install %s 2>/dev/null", blobmsg_get_string(tb[DU_INSTALL_ENV]), url);
} else
snprintf(command, sizeof(command), "lxc-attach -n %s -- opkg install %s 2>/dev/null", blobmsg_get_string(tb[DU_INSTALL_ENV]), blobmsg_get_string(tb[DU_INSTALL_URL]));
} else
return UBUS_STATUS_INVALID_ARGUMENT;
} else {
if (tb[DU_INSTALL_USERNAME] &&
*(blobmsg_get_string(tb[DU_INSTALL_USERNAME])) != '\0' &&
tb[DU_INSTALL_PASSWORD] &&
*(blobmsg_get_string(tb[DU_INSTALL_PASSWORD])) != '\0') {
char *url = convert_url(blobmsg_get_string(tb[DU_INSTALL_URL]), blobmsg_get_string(tb[DU_INSTALL_USERNAME]), blobmsg_get_string(tb[DU_INSTALL_PASSWORD]));
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", url);
} else
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", blobmsg_get_string(tb[DU_INSTALL_URL]));
}
} else {
if (tb[DU_INSTALL_USERNAME] &&
*(blobmsg_get_string(tb[DU_INSTALL_USERNAME])) != '\0' &&
tb[DU_INSTALL_PASSWORD] &&
*(blobmsg_get_string(tb[DU_INSTALL_PASSWORD])) != '\0') {
char *url = convert_url(blobmsg_get_string(tb[DU_INSTALL_URL]), blobmsg_get_string(tb[DU_INSTALL_USERNAME]), blobmsg_get_string(tb[DU_INSTALL_PASSWORD]));
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", url);
} else
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", blobmsg_get_string(tb[DU_INSTALL_URL]));
}
synchronize_deployment_units_with_map_du_file();
memset(&bb,0,sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
if ((log = popen(command, "r"))) {
while(fgets(line, sizeof(line), log) != NULL) {
if (strstr(line, "Downloading"))
i++;
if (strstr(line, "Installing") || strstr(line, "installed")) {
sscanf(line, "Installing %63s (%63[^)] to root...", name, version);
i++;
}
if (strstr(line, "Configuring"))
i++;
}
pclose(log);
}
if (i == 1) {
blobmsg_add_u8(&bb,"status", false);
blobmsg_add_string(&bb,"error", "Download");
} else if (i == 2) {
blobmsg_add_u8(&bb,"status", false);
blobmsg_add_string(&bb,"error", "Install");
} else {
blobmsg_add_u8(&bb,"status", true);
blobmsg_add_string(&bb,"name", name);
blobmsg_add_string(&bb,"version", version);
struct uci_section *new_s = opkg_uci_add_section("map_du", "deployment");
opkg_uci_set_value_by_section(new_s, "name", name);
opkg_uci_set_value_by_section(new_s, "version", version);
opkg_uci_set_value_by_section(new_s, "url", blobmsg_get_string(tb[DU_INSTALL_URL]));
if (tb[DU_INSTALL_USERNAME] && *(blobmsg_get_string(tb[DU_INSTALL_USERNAME])) != '\0')
opkg_uci_set_value_by_section(new_s, "username", blobmsg_get_string(tb[DU_INSTALL_USERNAME]));
if (tb[DU_INSTALL_PASSWORD] && *(blobmsg_get_string(tb[DU_INSTALL_PASSWORD])) != '\0')
opkg_uci_set_value_by_section(new_s, "password", blobmsg_get_string(tb[DU_INSTALL_PASSWORD]));
if (tb[DU_INSTALL_ENV]) {
opkg_uci_set_value_by_section(new_s, "environment", blobmsg_get_string(tb[DU_INSTALL_ENV]));
blobmsg_add_string(&bb,"environment", blobmsg_get_string(tb[DU_INSTALL_ENV]));
} else {
opkg_uci_set_value_by_section(new_s, "environment", "OpenWRT_Linux");
blobmsg_add_string(&bb,"environment", "OpenWRT_Linux");
}
if (tb[DU_INSTALL_UUID] && *(blobmsg_get_string(tb[DU_INSTALL_UUID])) != '\0') {
//use the given UUID
opkg_uci_set_value_by_section(new_s, "uuid", blobmsg_get_string(tb[DU_INSTALL_UUID]));
blobmsg_add_string(&bb,"uuid", blobmsg_get_string(tb[DU_INSTALL_UUID]));
} else {
//generate a UUID
char *uuid = generate_uuid();
opkg_uci_set_value_by_section(new_s, "uuid", uuid);
blobmsg_add_string(&bb,"uuid", uuid);
FREE(uuid);
}
//generate a DUID
char *duid = generate_duid(false, 0);
opkg_uci_set_value_by_section(new_s, "duid", duid);
FREE(duid);
}
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
return 0;
}
enum {
DU_UPDATE_UUID,
DU_UPDATE_URL,
DU_UPDATE_VERSION,
DU_UPDATE_USERNAME,
DU_UPDATE_PASSWORD,
__DU_UPDATE_MAX
};
static const struct blobmsg_policy du_update_policy[__DU_UPDATE_MAX] = {
[DU_UPDATE_UUID] = { .name = "uuid", .type = BLOBMSG_TYPE_STRING },
[DU_UPDATE_URL] = { .name = "url", .type = BLOBMSG_TYPE_STRING },
[DU_UPDATE_VERSION] = { .name = "version", .type = BLOBMSG_TYPE_STRING },
[DU_UPDATE_USERNAME] = { .name = "username", .type = BLOBMSG_TYPE_STRING },
[DU_UPDATE_PASSWORD] = { .name = "password", .type = BLOBMSG_TYPE_STRING },
};
static int opkg_du_update(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__DU_UPDATE_MAX] = {NULL};
char line[512], command[512], name[64], version[64];
char *map_env = NULL, *map_uuid = NULL;
struct blob_buf bb;
struct uci_section *s = NULL;
DIR *dir;
struct dirent *ent;
int i = 0, found;
FILE *log;
if(blobmsg_parse(du_update_policy, __DU_UPDATE_MAX, tb, blob_data(msg), blob_len(msg)))
return UBUS_STATUS_UNKNOWN_ERROR;
if (!tb[DU_UPDATE_URL])
return UBUS_STATUS_INVALID_ARGUMENT;
synchronize_deployment_units_with_map_du_file();
opkg_uci_foreach_section("map_du", "deployment", s) {
map_uuid = opkg_uci_get_value_by_section(s, "uuid");
if (strcmp(map_uuid, blobmsg_get_string(tb[DU_UPDATE_UUID])) == 0) {
map_env = opkg_uci_get_value_by_section(s, "environment");
opkg_uci_set_value_by_section(s, "url", blobmsg_get_string(tb[DU_UPDATE_URL]));
if (tb[DU_UPDATE_USERNAME] && *(blobmsg_get_string(tb[DU_UPDATE_USERNAME])) != '\0')
opkg_uci_set_value_by_section(s, "username", blobmsg_get_string(tb[DU_UPDATE_USERNAME]));
if (tb[DU_UPDATE_PASSWORD] && *(blobmsg_get_string(tb[DU_UPDATE_PASSWORD])) != '\0')
opkg_uci_set_value_by_section(s, "password", blobmsg_get_string(tb[DU_UPDATE_PASSWORD]));
break;
}
}
if (map_env) {
found = 0;
if (strcmp(map_env, "OpenWRT_Linux") != 0) {
if (isfileexist(LXC_PATH)) {
sysfs_foreach_file(LXC_PATH, dir, ent) {
if (strcmp(map_env, ent->d_name) == 0) {
found = 1;
break;
}
}
if (dir) closedir(dir);
if (!found)
return UBUS_STATUS_INVALID_ARGUMENT;
} else
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (found) {
if (islxcrunning(map_env)) {
if (tb[DU_UPDATE_USERNAME] &&
*(blobmsg_get_string(tb[DU_UPDATE_USERNAME])) != '\0' &&
tb[DU_UPDATE_PASSWORD] &&
*(blobmsg_get_string(tb[DU_UPDATE_PASSWORD])) != '\0') {
char *url = convert_url(blobmsg_get_string(tb[DU_UPDATE_URL]), blobmsg_get_string(tb[DU_UPDATE_USERNAME]), blobmsg_get_string(tb[DU_UPDATE_PASSWORD]));
snprintf(command, sizeof(command), "lxc-attach -n %s -- opkg install %s 2>/dev/null", map_env, url);
} else
snprintf(command, sizeof(command), "lxc-attach -n %s -- opkg install %s 2>/dev/null", map_env, blobmsg_get_string(tb[DU_UPDATE_URL]));
} else
return UBUS_STATUS_INVALID_ARGUMENT;
} else {
if (tb[DU_UPDATE_USERNAME] &&
*(blobmsg_get_string(tb[DU_UPDATE_USERNAME])) != '\0' &&
tb[DU_UPDATE_PASSWORD] &&
*(blobmsg_get_string(tb[DU_UPDATE_PASSWORD])) != '\0') {
char *url = convert_url(blobmsg_get_string(tb[DU_UPDATE_URL]), blobmsg_get_string(tb[DU_UPDATE_USERNAME]), blobmsg_get_string(tb[DU_UPDATE_PASSWORD]));
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", url);
} else
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", blobmsg_get_string(tb[DU_UPDATE_URL]));
}
} else {
if (tb[DU_UPDATE_USERNAME] &&
*(blobmsg_get_string(tb[DU_UPDATE_USERNAME])) != '\0' &&
tb[DU_UPDATE_PASSWORD] &&
*(blobmsg_get_string(tb[DU_UPDATE_PASSWORD])) != '\0') {
char *url = convert_url(blobmsg_get_string(tb[DU_UPDATE_URL]), blobmsg_get_string(tb[DU_UPDATE_USERNAME]), blobmsg_get_string(tb[DU_UPDATE_PASSWORD]));
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", url);
} else
snprintf(command, sizeof(command), "opkg install %s 2>/dev/null", blobmsg_get_string(tb[DU_UPDATE_URL]));
}
memset(&bb,0,sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
if ((log = popen(command, "r"))) {
while(fgets(line, sizeof(line), log) != NULL) {
if (strstr(line, "Downloading"))
i++;
if (strstr(line, "Upgrading")) {
sscanf(line, "Upgrading %63s on root from %*s to %63s...", name, version);
i++;
}
if (strstr(line, "Configuring"))
i++;
}
pclose(log);
}
if (i != 3) {
blobmsg_add_u8(&bb,"status", false);
} else {
blobmsg_add_u8(&bb,"status", true);
blobmsg_add_string(&bb,"name", name);
//delete "..." from version string
char *p = strstr(version, "...");
if (p) *p = '\0';
blobmsg_add_string(&bb,"version", version);
blobmsg_add_string(&bb,"uuid", blobmsg_get_string(tb[DU_UPDATE_UUID]));
if (map_env)
blobmsg_add_string(&bb,"environment", map_env);
else
blobmsg_add_string(&bb,"environment", "OpenWRT_Linux");
//update version in map_du file
opkg_uci_foreach_section("map_du", "deployment", s) {
map_uuid = opkg_uci_get_value_by_section(s, "uuid");
if (strcmp(map_uuid, blobmsg_get_string(tb[DU_UPDATE_UUID])) == 0) {
opkg_uci_set_value_by_section(s, "version", version);
break;
}
}
}
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
return 0;
}
enum {
DU_UNINSTALL_NAME,
DU_UNINSTALL_ENV,
__DU_UNINSTALL_MAX
};
static const struct blobmsg_policy du_uninstall_policy[__DU_UNINSTALL_MAX] = {
[DU_UNINSTALL_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
[DU_UNINSTALL_ENV] = { .name = "environment", .type = BLOBMSG_TYPE_STRING },
};
static int opkg_du_uninstall(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__DU_UNINSTALL_MAX] = {NULL};
char line[512], command[512];
DIR *dir;
struct dirent *ent;
struct blob_buf bb;
int found;
FILE *log;
if(blobmsg_parse(du_uninstall_policy, __DU_UNINSTALL_MAX, tb, blob_data(msg), blob_len(msg)))
return UBUS_STATUS_UNKNOWN_ERROR;
if (!tb[DU_UNINSTALL_NAME])
return UBUS_STATUS_INVALID_ARGUMENT;
if (tb[DU_UNINSTALL_ENV]) {
found = 0;
if (strcmp(blobmsg_get_string(tb[DU_UNINSTALL_ENV]), "OpenWRT_Linux") != 0) {
if (isfileexist(LXC_PATH)) {
sysfs_foreach_file(LXC_PATH, dir, ent) {
if (strcmp(blobmsg_get_string(tb[DU_UNINSTALL_ENV]), ent->d_name) == 0) {
found = 1;
break;
}
}
if (dir) closedir(dir);
if (!found)
return UBUS_STATUS_INVALID_ARGUMENT;
} else
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (found) {
if (islxcrunning(blobmsg_get_string(tb[DU_UNINSTALL_ENV])))
snprintf(command, sizeof(command), "lxc-attach -n %s -- opkg remove %s 2>/dev/null", blobmsg_get_string(tb[DU_UNINSTALL_ENV]), blobmsg_get_string(tb[DU_UNINSTALL_NAME]));
else
return UBUS_STATUS_INVALID_ARGUMENT;
} else
snprintf(command, sizeof(command), "opkg remove %s 2>/dev/null", blobmsg_get_string(tb[DU_UNINSTALL_NAME]));
} else {
snprintf(command, sizeof(command), "opkg remove %s 2>/dev/null", blobmsg_get_string(tb[DU_UNINSTALL_NAME]));
}
memset(&bb,0,sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
if ((log = popen(command, "r"))) {
while(fgets(line, sizeof(line), log) != NULL) {
if (strstr(line, "Removing package")) {
blobmsg_add_u8(&bb,"status", true);
break;
} else if (strstr(line, "No packages removed")) {
blobmsg_add_u8(&bb,"status", false);
break;
}
}
pclose(log);
}
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
return 0;
}
enum {
DU_LIST_INDEX,
__DU_LIST_MAX
};
static const struct blobmsg_policy opkg_du_list_policy[__DU_LIST_MAX] = {
[DU_LIST_INDEX] = { .name = "index", .type = BLOBMSG_TYPE_INT32 },
};
static int opkg_du_list(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__DU_LIST_MAX] = {NULL};
struct uci_section *ss = NULL;
struct blob_buf bb;
void *a, *t;
char *config = NULL;
FILE *fp;
int idx = 0, max = 0, incr = 0;
if(blobmsg_parse(opkg_du_list_policy, __DU_LIST_MAX, tb, blob_data(msg), blob_len(msg)))
return UBUS_STATUS_UNKNOWN_ERROR;
synchronize_deployment_units_with_map_du_file();
memset(&bb,0,sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
if (tb[DU_LIST_INDEX]) {
idx = blobmsg_get_u32(tb[DU_LIST_INDEX]);
max = idx + 100;
}
a = blobmsg_open_array(&bb, "deployment_unit");
opkg_uci_foreach_section("map_du", "deployment", ss) {
if ((incr < idx) && (idx != 0)) {
incr++;
continue;
}
char line[256], path[512], *spch = NULL;
char *soft_name = opkg_uci_get_value_by_section(ss, "name");
char *soft_env = opkg_uci_get_value_by_section(ss, "environment");
char *soft_uuid = opkg_uci_get_value_by_section(ss, "uuid");
char *soft_duid = opkg_uci_get_value_by_section(ss, "duid");
char *soft_version = opkg_uci_get_value_by_section(ss, "version");
char *soft_url = opkg_uci_get_value_by_section(ss, "url");
t = blobmsg_open_table(&bb, "");
blobmsg_add_string(&bb, "name", soft_name);
blobmsg_add_string(&bb, "version", soft_version);
blobmsg_add_string(&bb, "environment", soft_env);
blobmsg_add_string(&bb, "uuid", soft_uuid);
blobmsg_add_string(&bb, "duid", soft_duid);
if (soft_url && *soft_url != '\0')
blobmsg_add_string(&bb, "url", soft_url);
if (strcmp(soft_env, "OpenWRT_Linux") == 0)
snprintf(path, sizeof(path), "%s/%s.control", OPKG_INFO_PATH, soft_name);
else
snprintf(path, sizeof(path), "%s/%s/rootfs/%s/%s.control", LXC_PATH, soft_env, OPKG_INFO_PATH, soft_name);
fp = fopen(path, "r");
if ( fp != NULL) {
while (fgets(line, 256, fp) != NULL) {
if ((spch = strstr(line, "Maintainer:"))) {
remove_newline(spch);
blobmsg_add_string(&bb, "vendor", spch+12);
}
if ((spch = strstr(line, "Description:"))) {
remove_newline(spch);
blobmsg_add_string(&bb, "description", spch+14);
break;
}
}
fclose(fp);
}
if (strcmp(soft_env, "OpenWRT_Linux") == 0)
snprintf(path, sizeof(path), "%s/%s.list", OPKG_INFO_PATH, soft_name);
else
snprintf(path, sizeof(path), "%s/%s/rootfs/%s/%s.list", LXC_PATH, soft_env, OPKG_INFO_PATH, soft_name);
fp = fopen(path, "r");
if ( fp != NULL) {
while (fgets(line, 256, fp) != NULL) {
if ((config = strstr(line, "/etc/config/"))) {
remove_newline(line);
blobmsg_add_string(&bb, "config", config+12);
break;
}
}
fclose(fp);
}
blobmsg_close_table(&bb, t);
incr++;
if (incr == max) break;
}
blobmsg_close_array(&bb, a);
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
return 0;
}
static int opkg_eu_list(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
DIR *dir, *dir_opkg, *dir_lxc;
struct dirent *ent, *ent_opkg, *ent_lxc;
char fstat[64], fcmd[64], cmdline[256], fopkg[256], line[256], lxc_proc_path[256], lxc_opkg_info[256];
char *package_name;
int dgt, pid, ppid, found;
unsigned int bsize, vsize;
struct blob_buf bb;
void *a, *t;
FILE *fp;
memset(&bb, 0, sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
a = blobmsg_open_array(&bb, "execution_unit");
LIST_HEAD(proc_list);
//parse processes for OpenWRT_Linux
sysfs_foreach_file(PROC_PATH, dir, ent) {
dgt = ent->d_name[0] - '0';
if (dgt < 0 || dgt > 9)
continue;
snprintf(fcmd, sizeof(fcmd), "%s/%s/cmdline", PROC_PATH, ent->d_name);
fp = fopen(fcmd, "r");
if (fp == NULL)
continue;
if ( fgets (cmdline , 255 , fp) == NULL ) {
fclose(fp);
continue;
}
fclose(fp);
snprintf(fstat, sizeof(fstat), "%s/%s/stat", PROC_PATH, ent->d_name);
if( access(fstat, F_OK ) == -1 ) {
continue;
}
fp = fopen(fstat, "r");
if (fp == NULL)
continue;
if (fscanf(fp, "%d %*s %*c %d %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %u", &pid, &ppid, &bsize) == 0) {
fclose(fp);
continue;
}
fclose(fp);
if (ppid != 1)
continue;
vsize = bsize / 1024;
opkg_add_data_to_list(&proc_list, cmdline, pid, vsize);
}
if (dir) closedir(dir);
sysfs_foreach_file(OPKG_INFO_PATH, dir_opkg, ent_opkg) {
if (strstr(ent_opkg->d_name, "busybox")
|| strstr(ent_opkg->d_name, "bcmkernel")
|| strstr(ent_opkg->d_name, "juci")
|| strstr(ent_opkg->d_name, "lib")
|| strstr(ent_opkg->d_name, ".control")
|| strstr(ent_opkg->d_name, ".postrm")
|| strstr(ent_opkg->d_name, ".prerm")
|| strstr(ent_opkg->d_name, ".preinst")
|| strstr(ent_opkg->d_name, ".postinst"))
continue;
snprintf(fopkg, sizeof(fopkg), "%s/%s", OPKG_INFO_PATH, ent_opkg->d_name);
fp = fopen(fopkg, "r");
if (fp == NULL)
continue;
while (fgets(line, 256, fp) != NULL) {
found = 0;
if (strstr(line, "bin/")) {
struct process_res *p;
list_for_each_entry(p, &proc_list, list) {
if (strstr(line, p->cmd)) {
char line[256], path[512], version[64], *spch = NULL, *config = NULL;
int disk_space;
FILE *fp;
t = blobmsg_open_table(&bb, "");
package_name = get_package_name(ent_opkg->d_name);
blobmsg_add_string(&bb, "name", package_name);
blobmsg_add_string(&bb, "command", p->cmd);
blobmsg_add_u32(&bb, "euid", p->pid);
blobmsg_add_u32(&bb, "memory_space", p->vsize);
blobmsg_add_string(&bb, "environment", "OpenWRT_Linux");
snprintf(path, sizeof(path), "%s/%s.control", OPKG_INFO_PATH, package_name);
fp = fopen(path, "r");
if ( fp != NULL) {
while (fgets(line, 256, fp) != NULL) {
if(sscanf(line, "Version: %63s", version))
blobmsg_add_string(&bb, "version", version);
if(sscanf(line, "Installed-Size: %d", &disk_space))
blobmsg_add_u32(&bb, "disk_space", disk_space);
if ((spch = strstr(line, "Maintainer:"))) {
remove_newline(spch);
blobmsg_add_string(&bb, "vendor", spch+12);
}
if ((spch = strstr(line, "Description:"))) {
remove_newline(spch);
blobmsg_add_string(&bb, "description", spch+14);
break;
}
}
fclose(fp);
}
snprintf(path, sizeof(path), "%s/%s.list", OPKG_INFO_PATH, package_name);
fp = fopen(path, "r");
if ( fp != NULL) {
while (fgets(line, 256, fp) != NULL) {
if ((config = strstr(line, "/etc/config/"))) {
remove_newline(line);
blobmsg_add_string(&bb, "config", config+12);
break;
}
}
fclose(fp);
}
blobmsg_close_table(&bb, t);
found = 1;
break;
}
}
}
if (found)
break;
}
fclose(fp);
}
if (dir_opkg) closedir(dir_opkg);
//parse processes for linux containers
if (isfileexist(LXC_PATH)) {
sysfs_foreach_file(LXC_PATH, dir_lxc, ent_lxc) {
if ((strstr(ent_lxc->d_name, ".")) || (!islxcrunning(ent_lxc->d_name)))
continue;
snprintf(lxc_proc_path, sizeof(lxc_opkg_info), "%s/%s/rootfs/proc", LXC_PATH, ent_lxc->d_name);
sysfs_foreach_file(lxc_proc_path, dir, ent) {
dgt = ent->d_name[0] - '0';
if (dgt < 0 || dgt > 9)
continue;
snprintf(fcmd, sizeof(fcmd), "%s/%s/rootfs/proc/%s/cmdline", LXC_PATH, ent_lxc->d_name, ent->d_name);
fp = fopen(fcmd, "r");
if (fp == NULL)
continue;
if ( fgets (cmdline , 255 , fp) == NULL ) {
fclose(fp);
continue;
}
fclose(fp);
snprintf(fstat, sizeof(fstat), "%s/%s/rootfs/proc/%s/stat", LXC_PATH, ent_lxc->d_name, ent->d_name);
if( access(fstat, F_OK ) == -1 ) {
continue;
}
fp = fopen(fstat, "r");
if (fp == NULL)
continue;
if (fscanf(fp, "%d %*s %*c %d %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %u", &pid, &ppid, &bsize) == 0) {
fclose(fp);
continue;
}
fclose(fp);
if (ppid != 1)
continue;
vsize = bsize / 1024;
opkg_add_data_to_list(&proc_list, cmdline, pid, vsize);
}
if (dir) closedir(dir);
snprintf(lxc_opkg_info, sizeof(lxc_opkg_info), "%s/%s/rootfs%s", LXC_PATH, ent_lxc->d_name, OPKG_INFO_PATH);
sysfs_foreach_file(lxc_opkg_info, dir_opkg, ent_opkg) {
if (strstr(ent_opkg->d_name, "busybox")
|| strstr(ent_opkg->d_name, "bcmkernel")
|| strstr(ent_opkg->d_name, "juci")
|| strstr(ent_opkg->d_name, "lib")
|| strstr(ent_opkg->d_name, ".control")
|| strstr(ent_opkg->d_name, ".postrm")
|| strstr(ent_opkg->d_name, ".prerm")
|| strstr(ent_opkg->d_name, ".preinst")
|| strstr(ent_opkg->d_name, ".postinst"))
continue;
snprintf(fopkg, sizeof(fopkg), "%s/%s/rootfs%s/%s", LXC_PATH, ent_lxc->d_name, OPKG_INFO_PATH, ent_opkg->d_name);
fp = fopen(fopkg, "r");
if (fp == NULL)
continue;
while (fgets(line, 256, fp) != NULL) {
found = 0;
if (strstr(line, "bin/")) {
struct process_res *p;
list_for_each_entry(p, &proc_list, list) {
if (strstr(line, p->cmd)) {
char line[256], path[512], version[64], *spch = NULL, *config = NULL;
int disk_space;
FILE *fp;
t = blobmsg_open_table(&bb, "");
package_name = get_package_name(ent_opkg->d_name);
blobmsg_add_string(&bb, "name", package_name);
blobmsg_add_string(&bb, "command", p->cmd);
blobmsg_add_u32(&bb, "euid", p->pid);
blobmsg_add_u32(&bb, "memory_space", p->vsize);
blobmsg_add_string(&bb, "environment", ent_lxc->d_name);
snprintf(path, sizeof(path), "%s/%s/rootfs%s/%s.control", LXC_PATH, ent_lxc->d_name, OPKG_INFO_PATH, package_name);
fp = fopen(path, "r");
if ( fp != NULL) {
while (fgets(line, 256, fp) != NULL) {
if(sscanf(line, "Version: %63s", version))
blobmsg_add_string(&bb, "version", version);
if(sscanf(line, "Installed-Size: %d", &disk_space))
blobmsg_add_u32(&bb, "disk_space", disk_space);
if ((spch = strstr(line, "Maintainer:"))) {
remove_newline(spch);
blobmsg_add_string(&bb, "vendor", spch+12);
}
if ((spch = strstr(line, "Description:"))) {
remove_newline(spch);
blobmsg_add_string(&bb, "description", spch+14);
break;
}
}
fclose(fp);
}
snprintf(path, sizeof(path), "%s/%s/rootfs%s/%s.list", LXC_PATH, ent_lxc->d_name, OPKG_INFO_PATH, package_name);
fp = fopen(path, "r");
if ( fp != NULL) {
while (fgets(line, 256, fp) != NULL) {
if ((config = strstr(line, "/etc/config/"))) {
remove_newline(line);
blobmsg_add_string(&bb, "config", config+12);
break;
}
}
fclose(fp);
}
blobmsg_close_table(&bb, t);
found = 1;
break;
}
}
}
if (found)
break;
}
fclose(fp);
}
if (dir_opkg) closedir(dir_opkg);
}
if (dir_lxc) closedir(dir_lxc);
}
blobmsg_close_array(&bb, a);
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
opkg_free_data_from_list(&proc_list);
return 0;
}
static struct ubus_method opkg_object_methods[] = {
UBUS_METHOD_NOARG("environment", opkg_software_environment),
UBUS_METHOD("install", opkg_install, install_policy),
UBUS_METHOD("remove", opkg_remove, remove_policy),
UBUS_METHOD("du_install", opkg_du_install, du_install_policy),
UBUS_METHOD("du_update", opkg_du_update, du_update_policy),
UBUS_METHOD("du_uninstall", opkg_du_uninstall, du_uninstall_policy),
UBUS_METHOD("du_list", opkg_du_list, opkg_du_list_policy),
UBUS_METHOD_NOARG("eu_list", opkg_eu_list),
};
static struct ubus_object_type opkg_object_type = UBUS_OBJECT_TYPE("softwaremanagement", opkg_object_methods);
static struct ubus_object opkg_object = {
.name = "softwaremanagement",
.type = &opkg_object_type,
.methods = opkg_object_methods,
.n_methods = ARRAY_SIZE(opkg_object_methods),
};
static void opkg_init(struct ubus_context *ctx)
{
int ret;
ret = ubus_add_object(ctx, &opkg_object);
if (ret)
fprintf(stderr, "Failed to publish '%s' object : %s\n", opkg_object.name, ubus_strerror(ret));
uloop_run();
}
int main(void)
{
const char *ubus_socket = NULL;
struct ubus_context *ctx = NULL;
uloop_init();
opkg_uci_init();
ctx = ubus_connect(ubus_socket);
if (!ctx) {
fprintf(stderr, "Failed to connect to ubus\n");
return -1;
}
synchronize_deployment_units_with_map_du_file();
ubus_add_uloop(ctx);
opkg_init(ctx);
uloop_run();
ubus_free(ctx);
opkg_uci_fini();
if (ctx) ubus_free(ctx);
uloop_done();
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment