mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-28 08:05:56 -05:00
[db,conf,json] new backup endpoint
This commit is contained in:
parent
2ca10d9bba
commit
d567bd004a
@ -46,6 +46,7 @@ static cfg_opt_t sec_general[] =
|
||||
{
|
||||
CFG_STR("uid", "nobody", CFGF_NONE),
|
||||
CFG_STR("db_path", STATEDIR "/cache/" PACKAGE "/songs3.db", CFGF_NONE),
|
||||
CFG_STR("db_backup_path", NULL, CFGF_NONE),
|
||||
CFG_STR("logfile", STATEDIR "/log/" PACKAGE ".log", CFGF_NONE),
|
||||
CFG_INT_CB("loglevel", E_LOG, CFGF_NONE, &cb_loglevel),
|
||||
CFG_STR("admin_password", NULL, CFGF_NONE),
|
||||
|
61
src/db.c
61
src/db.c
@ -6946,6 +6946,67 @@ db_statements_prepare(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
db_backup()
|
||||
{
|
||||
int ret;
|
||||
sqlite3 *backup_hdl;
|
||||
sqlite3_backup *backup;
|
||||
const char *backup_path;
|
||||
|
||||
char resolved_bp[PATH_MAX];
|
||||
char resolved_dbp[PATH_MAX];
|
||||
|
||||
backup_path = cfg_getstr(cfg_getsec(cfg, "general"), "db_backup_path");
|
||||
if (!backup_path)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Backup not enabled, 'db_backup_path' is unset\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (realpath(db_path, resolved_dbp) == NULL || realpath(backup_path, resolved_bp) == NULL)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Failed to resolve real path of db/backup path: %s\n", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (strcmp(resolved_bp, resolved_dbp) == 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_DB, "Backup path same as main db path, ignoring\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
DPRINTF(E_INFO, L_DB, "Backup starting...\n");
|
||||
|
||||
ret = sqlite3_open(backup_path, &backup_hdl);
|
||||
if (ret != SQLITE_OK)
|
||||
{
|
||||
DPRINTF(E_WARN, L_DB, "Failed to create backup '%s': %s\n", backup_path, sqlite3_errmsg(backup_hdl));
|
||||
goto error;
|
||||
}
|
||||
|
||||
backup = sqlite3_backup_init(backup_hdl, "main", hdl, "main");
|
||||
if (!backup)
|
||||
{
|
||||
DPRINTF(E_WARN, L_DB, "Failed to initiate backup '%s': %s\n", backup_path, sqlite3_errmsg(backup_hdl));
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = sqlite3_backup_step(backup, -1);
|
||||
sqlite3_backup_finish(backup);
|
||||
sqlite3_close(backup_hdl);
|
||||
|
||||
if (ret == SQLITE_DONE || ret == SQLITE_OK)
|
||||
DPRINTF(E_INFO, L_DB, "Backup complete to '%s'\n", backup_path);
|
||||
else
|
||||
DPRINTF(E_WARN, L_DB, "Failed to complete backup '%s': %s (%d)\n", backup_path, sqlite3_errstr(ret), ret);
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
db_perthread_init(void)
|
||||
{
|
||||
|
2
src/db.h
2
src/db.h
@ -938,6 +938,8 @@ db_watch_enum_end(struct watch_enum *we);
|
||||
int
|
||||
db_watch_enum_fetchwd(struct watch_enum *we, uint32_t *wd);
|
||||
|
||||
int
|
||||
db_backup();
|
||||
|
||||
int
|
||||
db_perthread_init(void);
|
||||
|
@ -4213,6 +4213,24 @@ jsonapi_reply_search(struct httpd_request *hreq)
|
||||
return HTTP_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
jsonapi_reply_library_backup(struct httpd_request *hreq)
|
||||
{
|
||||
int ret;
|
||||
ret = db_backup();
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret == -2)
|
||||
return HTTP_SERVUNAVAIL; // not enabled by config
|
||||
|
||||
return HTTP_INTERNAL;
|
||||
}
|
||||
|
||||
return HTTP_OK;
|
||||
}
|
||||
|
||||
|
||||
static struct httpd_uri_map adm_handlers[] =
|
||||
{
|
||||
{ EVHTTP_REQ_GET, "^/api/config$", jsonapi_reply_config },
|
||||
@ -4284,6 +4302,7 @@ static struct httpd_uri_map adm_handlers[] =
|
||||
{ EVHTTP_REQ_GET, "^/api/library/count$", jsonapi_reply_library_count },
|
||||
{ EVHTTP_REQ_GET, "^/api/library/files$", jsonapi_reply_library_files },
|
||||
{ EVHTTP_REQ_POST, "^/api/library/add$", jsonapi_reply_library_add },
|
||||
{ EVHTTP_REQ_PUT, "^/api/library/backup$", jsonapi_reply_library_backup },
|
||||
|
||||
{ EVHTTP_REQ_GET, "^/api/search$", jsonapi_reply_search },
|
||||
|
||||
@ -4344,6 +4363,9 @@ jsonapi_request(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
||||
case HTTP_NOTFOUND: /* 404 Not Found */
|
||||
httpd_send_error(req, status_code, "Not Found");
|
||||
break;
|
||||
case HTTP_SERVUNAVAIL: /* 503 */
|
||||
httpd_send_error(req, status_code, "Service Unavailable");
|
||||
break;
|
||||
case HTTP_INTERNAL: /* 500 Internal Server Error */
|
||||
default:
|
||||
httpd_send_error(req, HTTP_INTERNAL, "Internal Server Error");
|
||||
|
Loading…
Reference in New Issue
Block a user