|
Packit |
4f15d5 |
/*
|
|
Packit |
4f15d5 |
Copyright (C) 2010 ABRT team
|
|
Packit |
4f15d5 |
Copyright (C) 2010 RedHat Inc
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
4f15d5 |
it under the terms of the GNU General Public License as published by
|
|
Packit |
4f15d5 |
the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
4f15d5 |
(at your option) any later version.
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
This program is distributed in the hope that it will be useful,
|
|
Packit |
4f15d5 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
4f15d5 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
4f15d5 |
GNU General Public License for more details.
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
You should have received a copy of the GNU General Public License along
|
|
Packit |
4f15d5 |
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
4f15d5 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
4f15d5 |
*/
|
|
Packit |
4f15d5 |
#include <sys/un.h>
|
|
Packit |
4f15d5 |
#include "internal_libreport.h"
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
#define SOCKET_FILE VAR_RUN"/abrt/abrt.socket"
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* connects to abrtd
|
|
Packit |
4f15d5 |
* returns: socketfd
|
|
Packit |
4f15d5 |
* -1 on error
|
|
Packit |
4f15d5 |
*/
|
|
Packit |
4f15d5 |
static int connect_to_abrtd_socket()
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
int socketfd = xsocket(AF_UNIX, SOCK_STREAM, 0);
|
|
Packit |
4f15d5 |
if (socketfd == -1)
|
|
Packit |
4f15d5 |
return -1;
|
|
Packit |
4f15d5 |
/*close_on_exec_on(socketfd); - not needed, we are closing it soon */
|
|
Packit |
4f15d5 |
struct sockaddr_un local;
|
|
Packit |
4f15d5 |
memset(&local, 0, sizeof(local));
|
|
Packit |
4f15d5 |
local.sun_family = AF_UNIX;
|
|
Packit |
4f15d5 |
strcpy(local.sun_path, SOCKET_FILE);
|
|
Packit |
4f15d5 |
int r = connect(socketfd, (struct sockaddr*)&local, sizeof(local));
|
|
Packit |
4f15d5 |
if (r != 0)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
VERB1 pwarn_msg("Can't connect to '%s'", SOCKET_FILE);
|
|
Packit |
4f15d5 |
close(socketfd);
|
|
Packit |
4f15d5 |
return -1;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return socketfd;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
static int connect_to_abrtd_and_call_DeleteDebugDump(const char *dump_dir_name)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
int result = -1; /* error so far */
|
|
Packit |
4f15d5 |
int socketfd = connect_to_abrtd_socket();
|
|
Packit |
4f15d5 |
if (socketfd != -1)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
full_write(socketfd, "DELETE ", strlen("DELETE "));
|
|
Packit |
4f15d5 |
full_write(socketfd, dump_dir_name, strlen(dump_dir_name));
|
|
Packit |
4f15d5 |
full_write(socketfd, " HTTP/1.1\r\n\r\n", strlen(" HTTP/1.1\r\n\r\n"));
|
|
Packit |
4f15d5 |
shutdown(socketfd, SHUT_WR);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char response[64];
|
|
Packit |
4f15d5 |
int r = full_read(socketfd, response, sizeof(response) - 1);
|
|
Packit |
4f15d5 |
if (r >= 0)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
log_notice("Response via socket:'%.*s'", r, response);
|
|
Packit |
4f15d5 |
/* 0123456789... */
|
|
Packit |
4f15d5 |
/* "HTTP/1.1 200 " */
|
|
Packit |
4f15d5 |
response[5] = '1';
|
|
Packit |
4f15d5 |
response[7] = '1';
|
|
Packit |
4f15d5 |
if (strncmp(response, "HTTP/1.1 ", strlen("HTTP/1.1 ")) == 0
|
|
Packit |
4f15d5 |
&& isdigit(response[9])
|
|
Packit |
4f15d5 |
&& isdigit(response[10])
|
|
Packit |
4f15d5 |
&& isdigit(response[11])
|
|
Packit |
4f15d5 |
&& response[12] == ' ')
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
result = (response[9] - '0') * 100 + (response[10] - '0') * 10 + (response[11] - '0');
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(socketfd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return result;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
int problem_data_send_to_abrt(problem_data_t* problem_data)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
int result = 1; /* error so far */
|
|
Packit |
4f15d5 |
int socketfd = connect_to_abrtd_socket();
|
|
Packit |
4f15d5 |
if (socketfd != -1)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
GHashTableIter iter;
|
|
Packit |
4f15d5 |
char *name;
|
|
Packit |
4f15d5 |
struct problem_item *value;
|
|
Packit |
4f15d5 |
g_hash_table_iter_init(&iter, problem_data);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
full_write(socketfd, "PUT / HTTP/1.1\r\n\r\n", strlen("PUT / HTTP/1.1\r\n\r\n"));
|
|
Packit |
4f15d5 |
while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value))
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (value->flags & CD_FLAG_BIN)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
/* sending files over the socket is not implemented yet */
|
|
Packit |
4f15d5 |
log_warning("Skipping binary file %s", name);
|
|
Packit |
4f15d5 |
continue;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* only files should contain '/' and those are handled earlier */
|
|
Packit |
4f15d5 |
if (name[0] == '.' || strchr(name, '/'))
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
error_msg("Problem data field name contains disallowed chars: '%s'", name);
|
|
Packit |
4f15d5 |
continue;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char* msg = xasprintf("%s=%s", name, value->content);
|
|
Packit |
4f15d5 |
full_write(socketfd, msg, strlen(msg)+1 /* yes, +1 coz we want to send the trailing 0 */);
|
|
Packit |
4f15d5 |
free(msg);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
shutdown(socketfd, SHUT_WR);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
char response[64];
|
|
Packit |
4f15d5 |
int r = full_read(socketfd, response, sizeof(response) - 1);
|
|
Packit |
4f15d5 |
if (r >= 0)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
log_notice("Response via socket:'%.*s'", r, response);
|
|
Packit |
4f15d5 |
/* 0123456789... */
|
|
Packit |
4f15d5 |
/* "HTTP/1.1 200 " */
|
|
Packit |
4f15d5 |
response[5] = '1';
|
|
Packit |
4f15d5 |
response[7] = '1';
|
|
Packit |
4f15d5 |
result = strncmp(response, "HTTP/1.1 201 ", strlen("HTTP/1.1 201 "));
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
close(socketfd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return result;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
int delete_dump_dir_possibly_using_abrtd(const char *dump_dir_name)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
INITIALIZE_LIBREPORT();
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
#if DUMP_DIR_OWNED_BY_USER == 0
|
|
Packit |
4f15d5 |
/* Try to delete it ourselves */
|
|
Packit |
4f15d5 |
struct dump_dir *dd = dd_opendir(dump_dir_name, DD_OPEN_READONLY);
|
|
Packit |
4f15d5 |
if (dd)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (dd->locked) /* it is not readonly */
|
|
Packit |
4f15d5 |
return dd_delete(dd);
|
|
Packit |
4f15d5 |
dd_close(dd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (errno == ENOENT || errno == ENOTDIR)
|
|
Packit |
4f15d5 |
/* No such dir, no point in trying to talk over socket */
|
|
Packit |
4f15d5 |
return 1;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
log_notice("Deleting '%s' via abrtd", dump_dir_name);
|
|
Packit |
4f15d5 |
const int res = connect_to_abrtd_and_call_DeleteDebugDump(dump_dir_name);
|
|
Packit |
4f15d5 |
if (res != 0)
|
|
Packit |
4f15d5 |
error_msg(_("Can't delete: '%s'"), dump_dir_name);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
return res;
|
|
Packit |
4f15d5 |
#else
|
|
Packit |
4f15d5 |
log_notice("Deleting '%s' via abrtd", dump_dir_name);
|
|
Packit |
4f15d5 |
const int res = connect_to_abrtd_and_call_DeleteDebugDump(dump_dir_name);
|
|
Packit |
4f15d5 |
if (res == 200)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
/*
|
|
Packit |
4f15d5 |
* Deleted
|
|
Packit |
4f15d5 |
*/
|
|
Packit |
4f15d5 |
return 0;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/*
|
|
Packit |
4f15d5 |
* An error occurred but we can still try to delete it directly
|
|
Packit |
4f15d5 |
*/
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
/* Using NULL in order to easily detect a buggy error message */
|
|
Packit |
4f15d5 |
const char *error_reason = NULL;
|
|
Packit |
4f15d5 |
/* Used only for error messages */
|
|
Packit |
4f15d5 |
char num_buf[sizeof(int)*3 + 1];
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
if (res < 0 || res == 400)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
/* -1 : an error in communication
|
|
Packit |
4f15d5 |
* 400 : bad request or abrtd refused to delete the directory outside of the dump location
|
|
Packit |
4f15d5 |
*
|
|
Packit |
4f15d5 |
* Try to delete it ourselves
|
|
Packit |
4f15d5 |
*/
|
|
Packit |
4f15d5 |
struct dump_dir *dd = dd_opendir(dump_dir_name, DD_OPEN_READONLY);
|
|
Packit |
4f15d5 |
if (dd)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
if (dd->locked) /* it is not readonly */
|
|
Packit |
4f15d5 |
return dd_delete(dd);
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
error_reason = _("locked by another process");
|
|
Packit |
4f15d5 |
dd_close(dd);
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
else
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
switch (res)
|
|
Packit |
4f15d5 |
{
|
|
Packit |
4f15d5 |
case 403:
|
|
Packit |
4f15d5 |
error_reason = _("permission denied");
|
|
Packit |
4f15d5 |
break;
|
|
Packit |
4f15d5 |
case 404:
|
|
Packit |
4f15d5 |
error_reason = _("not a problem directory");
|
|
Packit |
4f15d5 |
break;
|
|
Packit |
4f15d5 |
default:
|
|
Packit |
4f15d5 |
snprintf(num_buf, sizeof(num_buf), "%d", res);
|
|
Packit |
4f15d5 |
error_reason = num_buf;
|
|
Packit |
4f15d5 |
break;
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
}
|
|
Packit |
4f15d5 |
|
|
Packit |
4f15d5 |
error_msg(_("Can't delete '%s': %s"), dump_dir_name, error_reason);
|
|
Packit |
4f15d5 |
return 1;
|
|
Packit |
4f15d5 |
#endif
|
|
Packit |
4f15d5 |
}
|