246 lines
7.6 KiB
C
246 lines
7.6 KiB
C
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
|
|
#include <unistd.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
|
|
#include "init.h"
|
|
#include "sg.h"
|
|
#include "error.h"
|
|
#include "libburn.h"
|
|
#include "drive.h"
|
|
|
|
/* ts A60825 : The storage location for back_hacks.h variables. */
|
|
#define BURN_BACK_HACKS_INIT 1
|
|
#include "back_hacks.h"
|
|
|
|
/* ts A60924 : a new message handling facility */
|
|
#include "libdax_msgs.h"
|
|
struct libdax_msgs *libdax_messenger= NULL;
|
|
|
|
|
|
int burn_running = 0;
|
|
|
|
/* ts A60813 : wether to use O_EXCL and/or O_NONBLOCK in libburn/sg.c */
|
|
int burn_sg_open_o_excl = 1;
|
|
|
|
/* O_NONBLOCK was hardcoded in enumerate_ata() which i hardly use.
|
|
For enumerate_sg() it seems ok.
|
|
So it should stay default mode until enumerate_ata() without O_NONBLOCK
|
|
has been thoroughly tested. */
|
|
int burn_sg_open_o_nonblock = 1;
|
|
|
|
/* wether to take a busy drive as an error */
|
|
/* Caution: this is implemented by a rough hack and eventually leads
|
|
to unconditional abort of the process */
|
|
int burn_sg_open_abort_busy = 0;
|
|
|
|
|
|
/* ts A61002 */
|
|
|
|
#include "cleanup.h"
|
|
|
|
/* Parameters for builtin abort handler */
|
|
static char abort_message_prefix[81] = {"libburn : "};
|
|
static pid_t abort_control_pid= 0;
|
|
|
|
|
|
/* ts A60925 : ticket 74 */
|
|
/** Create the messenger object for libburn. */
|
|
int burn_msgs_initialize(void)
|
|
{
|
|
int ret;
|
|
|
|
if(libdax_messenger == NULL) {
|
|
ret = libdax_msgs_new(&libdax_messenger,0);
|
|
if (ret <= 0)
|
|
return 0;
|
|
}
|
|
libdax_msgs_set_severities(libdax_messenger, LIBDAX_MSGS_SEV_NEVER,
|
|
LIBDAX_MSGS_SEV_FATAL, "libburn: ", 0);
|
|
return 1;
|
|
}
|
|
|
|
/* ts A60924 : ticket 74 : Added use of global libdax_messenger */
|
|
int burn_initialize(void)
|
|
{
|
|
int ret;
|
|
|
|
if (burn_running)
|
|
return 1;
|
|
ret = burn_msgs_initialize();
|
|
if (ret <= 0)
|
|
return 0;
|
|
burn_running = 1;
|
|
return 1;
|
|
}
|
|
|
|
void burn_finish(void)
|
|
{
|
|
assert(burn_running);
|
|
|
|
burn_wait_all();
|
|
|
|
/* ts A60904 : ticket 62, contribution by elmom : name addon "_all" */
|
|
burn_drive_free_all();
|
|
|
|
/* ts A60924 : ticket 74 */
|
|
libdax_msgs_destroy(&libdax_messenger,0);
|
|
|
|
burn_running = 0;
|
|
}
|
|
|
|
|
|
/* ts A60813 */
|
|
/** Set parameters for behavior on opening device files. To be called early
|
|
after burn_initialize() and before any bus scan. But not mandatory at all.
|
|
@param exclusive Try to open only devices which are not marked as busy
|
|
and try to mark them busy if opened sucessfully. (O_EXCL)
|
|
There are kernels which simply don't care about O_EXCL.
|
|
Some have it off, some have it on, some are switchable.
|
|
Values: 0=off, 1=on, 2=on,O_EXCL scsi siblings (sr,scd,st)
|
|
@param blocking Try to wait for drives which do not open immediately but
|
|
also do not return an error as well. (O_NONBLOCK)
|
|
This might stall indefinitely with /dev/hdX hard disks.
|
|
@param abort_on_busy Unconditionally abort process when a non blocking
|
|
exclusive opening attempt indicates a busy drive.
|
|
Use this only after thorough tests with your app.
|
|
Parameter value 1 enables a feature, 0 disables.
|
|
Default is (1,0,0). Have a good reason before you change it.
|
|
*/
|
|
void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
|
|
{
|
|
assert(burn_running);
|
|
|
|
burn_sg_open_o_excl= exclusive;
|
|
burn_sg_open_o_nonblock= !blocking;
|
|
burn_sg_open_abort_busy= !!abort_on_busy;
|
|
}
|
|
|
|
|
|
/* ts A60924 : ticket 74 */
|
|
/** Control queueing and stderr printing of messages from libburn.
|
|
Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
|
|
"NOTE", "UPDATE", "DEBUG", "ALL".
|
|
@param queue_severity Gives the minimum limit for messages to be queued.
|
|
Default: "NEVER". If you queue messages then you
|
|
must consume them by burn_msgs_obtain().
|
|
@param print_severity Does the same for messages to be printed directly
|
|
to stderr.
|
|
@param print_id A text prefix to be printed before the message.
|
|
@return >0 for success, <=0 for error
|
|
|
|
*/
|
|
int burn_msgs_set_severities(char *queue_severity,
|
|
char *print_severity, char *print_id)
|
|
{
|
|
int ret, queue_sevno, print_sevno;
|
|
|
|
ret = libdax_msgs__text_to_sev(queue_severity, &queue_sevno, 0);
|
|
if (ret <= 0)
|
|
return 0;
|
|
ret = libdax_msgs__text_to_sev(print_severity, &print_sevno, 0);
|
|
if (ret <= 0)
|
|
return 0;
|
|
ret = libdax_msgs_set_severities(libdax_messenger, queue_sevno,
|
|
print_sevno, print_id, 0);
|
|
if (ret <= 0)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* ts A60924 : ticket 74 */
|
|
#define BURM_MSGS_MESSAGE_LEN 4096
|
|
|
|
/** Obtain the oldest pending libburn message from the queue which has at
|
|
least the given minimum_severity. This message and any older message of
|
|
lower severity will get discarded from the queue and is then lost forever.
|
|
Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
|
|
"NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER"
|
|
will discard the whole queue.
|
|
@param error_code Will become a unique error code as liste in
|
|
libburn/libdax_msgs.h
|
|
@param msg_text Must provide at least BURM_MSGS_MESSAGE_LEN bytes.
|
|
@param os_errno Will become the eventual errno related to the message
|
|
@param severity Will become the severity related to the message and
|
|
should provide at least 80 bytes.
|
|
@return 1 if a matching item was found, 0 if not, <0 for severe errors
|
|
*/
|
|
int burn_msgs_obtain(char *minimum_severity,
|
|
int *error_code, char msg_text[], int *os_errno,
|
|
char severity[])
|
|
{
|
|
int ret, minimum_sevno, sevno, priority;
|
|
char *textpt, *sev_name;
|
|
struct libdax_msgs_item *item = NULL;
|
|
|
|
ret = libdax_msgs__text_to_sev(minimum_severity, &minimum_sevno, 0);
|
|
if (ret <= 0)
|
|
return 0;
|
|
ret = libdax_msgs_obtain(libdax_messenger, &item, minimum_sevno,
|
|
LIBDAX_MSGS_PRIO_ZERO, 0);
|
|
if (ret <= 0)
|
|
goto ex;
|
|
ret = libdax_msgs_item_get_msg(item, error_code, &textpt, os_errno, 0);
|
|
if (ret <= 0)
|
|
goto ex;
|
|
strncpy(msg_text, textpt, BURM_MSGS_MESSAGE_LEN-1);
|
|
if(strlen(textpt) >= BURM_MSGS_MESSAGE_LEN)
|
|
msg_text[BURM_MSGS_MESSAGE_LEN-1] = 0;
|
|
|
|
severity[0]= 0;
|
|
ret = libdax_msgs_item_get_rank(item, &sevno, &priority, 0);
|
|
if(ret <= 0)
|
|
goto ex;
|
|
ret = libdax_msgs__sev_to_text(sevno, &sev_name, 0);
|
|
if(ret <= 0)
|
|
goto ex;
|
|
strcpy(severity,sev_name);
|
|
|
|
ret = 1;
|
|
ex:
|
|
libdax_msgs_destroy_item(libdax_messenger, &item, 0);
|
|
return ret;
|
|
}
|
|
|
|
int burn_builtin_abort_handler(void *handle, int signum, int flag)
|
|
{
|
|
if(getpid() != abort_control_pid)
|
|
return -2;
|
|
Cleanup_set_handlers(NULL, NULL, 2);
|
|
fprintf(stderr,"%sABORT : Trying to shut down drive and library\n",
|
|
abort_message_prefix);
|
|
fprintf(stderr,
|
|
"%sABORT : Wait the normal burning time before any kill -9\n",
|
|
abort_message_prefix);
|
|
close(0); /* somehow stdin as input blocks abort until EOF */
|
|
burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
|
|
fprintf(stderr,
|
|
"\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n",
|
|
abort_message_prefix);
|
|
return(1);
|
|
}
|
|
|
|
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
|
|
int mode)
|
|
{
|
|
if(handler == NULL && mode == 0) {
|
|
handler = burn_builtin_abort_handler;
|
|
/*
|
|
fprintf(stderr, "libburn_experimental: activated burn_builtin_abort_handler() with handle '%s'\n",(handle==NULL ? "libburn : " : (char *) handle));
|
|
*/
|
|
|
|
}
|
|
strcpy(abort_message_prefix, "libburn : ");
|
|
if(handle != NULL)
|
|
strncpy(abort_message_prefix, (char *) handle,
|
|
sizeof(abort_message_prefix)-1);
|
|
abort_message_prefix[sizeof(abort_message_prefix)-1] = 0;
|
|
abort_control_pid= getpid();
|
|
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler, mode|4);
|
|
}
|
|
|