From 139fb6496cef37895199a51c69ca93b4a557b0ba Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 28 Aug 2007 10:29:55 +0000 Subject: [PATCH] Finally commited the patch :P --- libisofs/libdax_msgs.c | 404 ++++++++++++++++++++++++++++++++++++++ libisofs/libdax_msgs.h | 434 +++++++++++++++++++++++++++++++++++++++++ libisofs/messages.c | 144 ++++++++++++++ libisofs/messages.h | 38 ++++ test/iso_grow.c | 171 ++++++++++++++++ 5 files changed, 1191 insertions(+) create mode 100644 libisofs/libdax_msgs.c create mode 100644 libisofs/libdax_msgs.h create mode 100644 libisofs/messages.c create mode 100644 libisofs/messages.h create mode 100644 test/iso_grow.c diff --git a/libisofs/libdax_msgs.c b/libisofs/libdax_msgs.c new file mode 100644 index 0000000..5f179ae --- /dev/null +++ b/libisofs/libdax_msgs.c @@ -0,0 +1,404 @@ + +/* libdax_msgs + Message handling facility of libdax. + Copyright (C) 2006 Thomas Schmitt , provided under GPL +*/ + +#include +#include +#include +#include +#include +#include +#include + +/* Only this single source module is entitled to do this */ +#define LIBDAX_MSGS_H_INTERNAL 1 + +/* All participants in the messaging system must do this */ +#include "libdax_msgs.h" + + +/* ----------------------------- libdax_msgs_item ------------------------- */ + + +static int libdax_msgs_item_new(struct libdax_msgs_item **item, + struct libdax_msgs_item *link, int flag) +{ + int ret; + struct libdax_msgs_item *o; + struct timeval tv; + struct timezone tz; + + (*item)= o= + (struct libdax_msgs_item *) malloc(sizeof(struct libdax_msgs_item)); + if(o==NULL) + return(-1); + o->timestamp= 0.0; + ret= gettimeofday(&tv,&tz); + if(ret==0) + o->timestamp= tv.tv_sec+0.000001*tv.tv_usec; + o->process_id= getpid(); + o->driveno= -1; + o->severity= LIBDAX_MSGS_SEV_ALL; + o->priority= LIBDAX_MSGS_PRIO_ZERO; + o->error_code= 0; + o->msg_text= NULL; + o->os_errno= 0; + o->prev= link; + o->next= NULL; + if(link!=NULL) { + if(link->next!=NULL) { + link->next->prev= o; + o->next= link->next; + } + link->next= o; + } + return(1); +} + + +/** Detaches item from its queue and eventually readjusts start, end pointers + of the queue */ +int libdax_msgs_item_unlink(struct libdax_msgs_item *o, + struct libdax_msgs_item **chain_start, + struct libdax_msgs_item **chain_end, int flag) +{ + if(o->prev!=NULL) + o->prev->next= o->next; + if(o->next!=NULL) + o->next->prev= o->prev; + if(chain_start!=NULL) + if(*chain_start == o) + *chain_start= o->next; + if(chain_end!=NULL) + if(*chain_end == o) + *chain_end= o->prev; + o->next= o->prev= NULL; + return(1); +} + + +int libdax_msgs_item_destroy(struct libdax_msgs_item **item, + int flag) +{ + struct libdax_msgs_item *o; + + o= *item; + if(o==NULL) + return(0); + libdax_msgs_item_unlink(o,NULL,NULL,0); + if(o->msg_text!=NULL) + free((char *) o->msg_text); + free((char *) o); + *item= NULL; + return(1); +} + + +int libdax_msgs_item_get_msg(struct libdax_msgs_item *item, + int *error_code, char **msg_text, int *os_errno, + int flag) +{ + *error_code= item->error_code; + *msg_text= item->msg_text; + *os_errno= item->os_errno; + return(1); +} + + +int libdax_msgs_item_get_origin(struct libdax_msgs_item *item, + double *timestamp, pid_t *process_id, int *driveno, + int flag) +{ + *timestamp= item->timestamp; + *process_id= item->process_id; + *driveno= item->driveno; + return(1); +} + + +int libdax_msgs_item_get_rank(struct libdax_msgs_item *item, + int *severity, int *priority, int flag) +{ + *severity= item->severity; + *priority= item->priority; + return(1); +} + + +/* ------------------------------- libdax_msgs ---------------------------- */ + + +int libdax_msgs_new(struct libdax_msgs **m, int flag) +{ + struct libdax_msgs *o; + + (*m)= o= (struct libdax_msgs *) malloc(sizeof(struct libdax_msgs)); + if(o==NULL) + return(-1); + o->oldest= NULL; + o->youngest= NULL; + o->count= 0; + o->queue_severity= LIBDAX_MSGS_SEV_ALL; + o->print_severity= LIBDAX_MSGS_SEV_NEVER; + strcpy(o->print_id,"libdax: "); + +#ifndef LIBDAX_MSGS_SINGLE_THREADED + pthread_mutex_init(&(o->lock_mutex),NULL); +#endif + + return(1); +} + + +int libdax_msgs_destroy(struct libdax_msgs **m, int flag) +{ + struct libdax_msgs *o; + struct libdax_msgs_item *item, *next_item; + + o= *m; + if(o==NULL) + return(0); + +#ifndef LIBDAX_MSGS_SINGLE_THREADED + if(pthread_mutex_destroy(&(o->lock_mutex))!=0) { + pthread_mutex_unlock(&(o->lock_mutex)); + pthread_mutex_destroy(&(o->lock_mutex)); + } +#endif + + for(item= o->oldest; item!=NULL; item= next_item) { + next_item= item->next; + libdax_msgs_item_destroy(&item,0); + } + free((char *) o); + *m= NULL; + return(1); +} + + +int libdax_msgs_set_severities(struct libdax_msgs *m, int queue_severity, + int print_severity, char *print_id, int flag) +{ + m->queue_severity= queue_severity; + m->print_severity= print_severity; + strncpy(m->print_id,print_id,80); + m->print_id[80]= 0; + return(1); +} + + +static int libdax_msgs_lock(struct libdax_msgs *m, int flag) +{ + +#ifndef LIBDAX_MSGS_SINGLE_THREADED + int ret; + + ret= pthread_mutex_lock(&(m->lock_mutex)); + if(ret!=0) + return(0); +#endif + + return(1); +} + + +static int libdax_msgs_unlock(struct libdax_msgs *m, int flag) +{ + +#ifndef LIBDAX_MSGS_SINGLE_THREADED + int ret; + + ret= pthread_mutex_unlock(&(m->lock_mutex)); + if(ret!=0) + return(0); +#endif + + return(1); +} + + +int libdax_msgs__text_to_sev(char *severity_name, int *severity, + int flag) +{ + if(strncmp(severity_name,"NEVER",5)==0) + *severity= LIBDAX_MSGS_SEV_NEVER; + else if(strncmp(severity_name,"ABORT",5)==0) + *severity= LIBDAX_MSGS_SEV_ABORT; + else if(strncmp(severity_name,"FATAL",5)==0) + *severity= LIBDAX_MSGS_SEV_FATAL; + else if(strncmp(severity_name,"SORRY",5)==0) + *severity= LIBDAX_MSGS_SEV_SORRY; + else if(strncmp(severity_name,"WARNING",7)==0) + *severity= LIBDAX_MSGS_SEV_WARNING; + else if(strncmp(severity_name,"HINT",4)==0) + *severity= LIBDAX_MSGS_SEV_HINT; + else if(strncmp(severity_name,"NOTE",4)==0) + *severity= LIBDAX_MSGS_SEV_NOTE; + else if(strncmp(severity_name,"UPDATE",6)==0) + *severity= LIBDAX_MSGS_SEV_UPDATE; + else if(strncmp(severity_name,"DEBUG",5)==0) + *severity= LIBDAX_MSGS_SEV_DEBUG; + else if(strncmp(severity_name,"ALL",3)==0) + *severity= LIBDAX_MSGS_SEV_ALL; + else { + *severity= LIBDAX_MSGS_SEV_NEVER; + return(0); + } + return(1); +} + + +int libdax_msgs__sev_to_text(int severity, char **severity_name, + int flag) +{ + if(flag&1) { + *severity_name= + "NEVER\nABORT\nFATAL\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nALL"; + return(1); + } + *severity_name= ""; + if(severity>=LIBDAX_MSGS_SEV_NEVER) + *severity_name= "NEVER"; + else if(severity>=LIBDAX_MSGS_SEV_ABORT) + *severity_name= "ABORT"; + else if(severity>=LIBDAX_MSGS_SEV_FATAL) + *severity_name= "FATAL"; + else if(severity>=LIBDAX_MSGS_SEV_SORRY) + *severity_name= "SORRY"; + else if(severity>=LIBDAX_MSGS_SEV_WARNING) + *severity_name= "WARNING"; + else if(severity>=LIBDAX_MSGS_SEV_HINT) + *severity_name= "HINT"; + else if(severity>=LIBDAX_MSGS_SEV_NOTE) + *severity_name= "NOTE"; + else if(severity>=LIBDAX_MSGS_SEV_UPDATE) + *severity_name= "UPDATE"; + else if(severity>=LIBDAX_MSGS_SEV_DEBUG) + *severity_name= "DEBUG"; + else if(severity>=LIBDAX_MSGS_SEV_ALL) + *severity_name= "ALL"; + else { + *severity_name= ""; + return(0); + } + return(1); +} + + +int libdax_msgs_submit(struct libdax_msgs *m, int driveno, int error_code, + int severity, int priority, char *msg_text, + int os_errno, int flag) +{ + int ret; + char *textpt,*sev_name,sev_text[81]; + struct libdax_msgs_item *item= NULL; + + if(severity >= m->print_severity) { + if(msg_text==NULL) + textpt= ""; + else + textpt= msg_text; + sev_text[0]= 0; + ret= libdax_msgs__sev_to_text(severity,&sev_name,0); + if(ret>0) + sprintf(sev_text,"%s : ",sev_name); + + fprintf(stderr,"%s%s%s\n",m->print_id,sev_text,textpt); + if(os_errno!=0) { + ret= libdax_msgs_lock(m,0); + if(ret<=0) + return(-1); + fprintf(stderr,"%s( Most recent system error: %d '%s' )\n", + m->print_id,os_errno,strerror(os_errno)); + libdax_msgs_unlock(m,0); + } + + } + if(severity < m->queue_severity) + return(0); + + ret= libdax_msgs_lock(m,0); + if(ret<=0) + return(-1); + ret= libdax_msgs_item_new(&item,m->youngest,0); + if(ret<=0) + goto failed; + item->driveno= driveno; + item->error_code= error_code; + item->severity= severity; + item->priority= priority; + if(msg_text!=NULL) { + item->msg_text= malloc(strlen(msg_text)+1); + if(item->msg_text==NULL) + goto failed; + strcpy(item->msg_text,msg_text); + } + item->os_errno= os_errno; + if(m->oldest==NULL) + m->oldest= item; + m->youngest= item; + m->count++; + libdax_msgs_unlock(m,0); + +/* +fprintf(stderr,"libdax_experimental: message submitted to queue (now %d)\n", + m->count); +*/ + + return(1); +failed:; + libdax_msgs_item_destroy(&item,0); + libdax_msgs_unlock(m,0); + return(-1); +} + + +int libdax_msgs_obtain(struct libdax_msgs *m, struct libdax_msgs_item **item, + int severity, int priority, int flag) +{ + int ret; + struct libdax_msgs_item *im, *next_im= NULL; + + *item= NULL; + ret= libdax_msgs_lock(m,0); + if(ret<=0) + return(-1); + for(im= m->oldest; im!=NULL; im= next_im) { + for(; im!=NULL; im= next_im) { + next_im= im->next; + if(im->severity>=severity) + break; + libdax_msgs_item_unlink(im,&(m->oldest),&(m->youngest),0); + libdax_msgs_item_destroy(&im,0); /* severity too low: delete */ + } + if(im==NULL) + break; + if(im->priority>=priority) + break; + } + if(im==NULL) + {ret= 0; goto ex;} + libdax_msgs_item_unlink(im,&(m->oldest),&(m->youngest),0); + *item= im; + ret= 1; +ex:; + libdax_msgs_unlock(m,0); + return(ret); +} + + +int libdax_msgs_destroy_item(struct libdax_msgs *m, + struct libdax_msgs_item **item, int flag) +{ + int ret; + + ret= libdax_msgs_lock(m,0); + if(ret<=0) + return(-1); + ret= libdax_msgs_item_destroy(item,0); + libdax_msgs_unlock(m,0); + return(ret); +} + diff --git a/libisofs/libdax_msgs.h b/libisofs/libdax_msgs.h new file mode 100644 index 0000000..0d532bb --- /dev/null +++ b/libisofs/libdax_msgs.h @@ -0,0 +1,434 @@ + +/* libdax_msgs + Message handling facility of libdax. + Copyright (C) 2006-2007 Thomas Schmitt , + provided under GPL +*/ + + +/* + *Never* set this macro outside libdax_msgs.c ! + The entrails of the message handling facility are not to be seen by + the other library components or the applications. +*/ +#ifdef LIBDAX_MSGS_H_INTERNAL + + +#ifndef LIBDAX_MSGS_SINGLE_THREADED +#include +#endif + + +struct libdax_msgs_item { + + double timestamp; + pid_t process_id; + int driveno; + + int severity; + int priority; + + /* Apply for your developer's error code range at + libburn-hackers@pykix.org + Report introduced codes in the list below. */ + int error_code; + + char *msg_text; + int os_errno; + + struct libdax_msgs_item *prev,*next; + +}; + + +struct libdax_msgs { + + struct libdax_msgs_item *oldest; + struct libdax_msgs_item *youngest; + int count; + + int queue_severity; + int print_severity; + char print_id[81]; + +#ifndef LIBDAX_MSGS_SINGLE_THREADED + pthread_mutex_t lock_mutex; +#endif + + +}; + +#endif /* LIBDAX_MSGS_H_INTERNAL */ + + +#ifndef LIBDAX_MSGS_H_INCLUDED +#define LIBDAX_MSGS_H_INCLUDED 1 + + +#ifndef LIBDAX_MSGS_H_INTERNAL + + + /* Public Opaque Handles */ + +/** A pointer to this is a opaque handle to a message handling facility */ +struct libdax_msgs; + +/** A pointer to this is a opaque handle to a single message item */ +struct libdax_msgs_item; + +#endif /* ! LIBDAX_MSGS_H_INTERNAL */ + + + /* Public Macros */ + + +/* Registered Severities */ + +/* It is well advisable to let applications select severities via strings and + forwarded functions libdax_msgs__text_to_sev(), libdax_msgs__sev_to_text(). + These macros are for use by libdax/libburn only. +*/ + +/** Use this to get messages of any severity. Do not use for submitting. +*/ +#define LIBDAX_MSGS_SEV_ALL 0x00000000 + +/** Debugging messages not to be visible to normal users by default +*/ +#define LIBDAX_MSGS_SEV_DEBUG 0x10000000 + +/** Update of a progress report about long running actions +*/ +#define LIBDAX_MSGS_SEV_UPDATE 0x20000000 + +/** Not so usual events which were gracefully handled +*/ +#define LIBDAX_MSGS_SEV_NOTE 0x30000000 + +/** Possibilities to achieve a better result +*/ +#define LIBDAX_MSGS_SEV_HINT 0x40000000 + +/** Warnings about problems which could not be handled optimally +*/ +#define LIBDAX_MSGS_SEV_WARNING 0x50000000 + +/** Non-fatal error messages indicating that parts of the action failed + but processing will/should go on +*/ +#define LIBDAX_MSGS_SEV_SORRY 0x60000000 + +/** An error message which puts the whole operation of libdax in question +*/ +#define LIBDAX_MSGS_SEV_FATAL 0x70000000 + +/** A message from an abort handler which will finally finish libburn +*/ +#define LIBDAX_MSGS_SEV_ABORT 0x71000000 + +/** A severity to exclude resp. discard any possible message. + Do not use this severity for submitting. +*/ +#define LIBDAX_MSGS_SEV_NEVER 0x7fffffff + + +/* Registered Priorities */ + +/* Priorities are to be used by libburn/libdax only. */ + +#define LIBDAX_MSGS_PRIO_ZERO 0x00000000 +#define LIBDAX_MSGS_PRIO_LOW 0x10000000 +#define LIBDAX_MSGS_PRIO_MEDIUM 0x20000000 +#define LIBDAX_MSGS_PRIO_HIGH 0x30000000 +#define LIBDAX_MSGS_PRIO_TOP 0x7ffffffe + +/* Do not use this priority for submitting */ +#define LIBDAX_MSGS_PRIO_NEVER 0x7fffffff + + + /* Public Functions */ + + /* Calls initiated from inside libdax/libburn */ + + +/** Create new empty message handling facility with queue. + @param flag Bitfield for control purposes (unused yet, submit 0) + @return >0 success, <=0 failure +*/ +int libdax_msgs_new(struct libdax_msgs **m, int flag); + + +/** Destroy a message handling facility and all its eventual messages. + The submitted pointer gets set to NULL. + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 for success, 0 for pointer to NULL +*/ +int libdax_msgs_destroy(struct libdax_msgs **m, int flag); + + +/** Submit a message to a message handling facility. + @param driveno libdax drive number. Use -1 if no number is known. + @param error_code Unique error code. Use only registered codes. See below. + The same unique error_code may be issued at different + occasions but those should be equivalent out of the view + of a libdax application. (E.g. "cannot open ATA drive" + versus "cannot open SCSI drive" would be equivalent.) + @param severity The LIBDAX_MSGS_SEV_* of the event. + @param priority The LIBDAX_MSGS_PRIO_* number of the event. + @param msg_text Printable and human readable message text. + @param os_errno Eventual error code from operating system (0 if none) + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 on success, 0 on rejection, <0 for severe errors +*/ +int libdax_msgs_submit(struct libdax_msgs *m, int driveno, int error_code, + int severity, int priority, char *msg_text, + int os_errno, int flag); + + + /* Calls from applications (to be forwarded by libdax/libburn) */ + + +/** Convert a registered severity number into a severity name + @param flag Bitfield for control purposes: + bit0= list all severity names in a newline separated string + @return >0 success, <=0 failure +*/ +int libdax_msgs__sev_to_text(int severity, char **severity_name, + int flag); + + +/** Convert a severity name into a severity number, + @param flag Bitfield for control purposes (unused yet, submit 0) + @return >0 success, <=0 failure +*/ +int libdax_msgs__text_to_sev(char *severity_name, int *severity, + int flag); + + +/** Set minimum severity for messages to be queued (default + LIBDAX_MSGS_SEV_ALL) and for messages to be printed directly to stderr + (default LIBDAX_MSGS_SEV_NEVER). + @param print_id A text of at most 80 characters to be printed before + any eventually printed message (default is "libdax: "). + @param flag Bitfield for control purposes (unused yet, submit 0) + @return always 1 for now +*/ +int libdax_msgs_set_severities(struct libdax_msgs *m, int queue_severity, + int print_severity, char *print_id, int flag); + + +/** Obtain a message item that has at least the given severity and priority. + Usually all older messages of lower severity are discarded then. If no + item of sufficient severity was found, all others are discarded from the + queue. + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 if a matching item was found, 0 if not, <0 for severe errors +*/ +int libdax_msgs_obtain(struct libdax_msgs *m, struct libdax_msgs_item **item, + int severity, int priority, int flag); + + +/** Destroy a message item obtained by libdax_msgs_obtain(). The submitted + pointer gets set to NULL. + Caution: Copy eventually obtained msg_text before destroying the item, + if you want to use it further. + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 for success, 0 for pointer to NULL, <0 for severe errors +*/ +int libdax_msgs_destroy_item(struct libdax_msgs *m, + struct libdax_msgs_item **item, int flag); + + +/** Obtain from a message item the three application oriented components as + submitted with the originating call of libdax_msgs_submit(). + Caution: msg_text becomes a pointer into item, not a copy. + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 on success, 0 on invalid item, <0 for servere errors +*/ +int libdax_msgs_item_get_msg(struct libdax_msgs_item *item, + int *error_code, char **msg_text, int *os_errno, + int flag); + + +/** Obtain from a message item the submitter identification submitted + with the originating call of libdax_msgs_submit(). + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 on success, 0 on invalid item, <0 for servere errors +*/ +int libdax_msgs_item_get_origin(struct libdax_msgs_item *item, + double *timestamp, pid_t *process_id, int *driveno, + int flag); + + +/** Obtain from a message item severity and priority as submitted + with the originating call of libdax_msgs_submit(). + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 on success, 0 on invalid item, <0 for servere errors +*/ +int libdax_msgs_item_get_rank(struct libdax_msgs_item *item, + int *severity, int *priority, int flag); + + +#ifdef LIDBAX_MSGS_________________ + + + /* Registered Error Codes */ + + +Format: error_code (LIBDAX_MSGS_SEV_*,LIBDAX_MSGS_PRIO_*) = explanation +If no severity or priority are fixely associates, use "(,)". + +------------------------------------------------------------------------------ +Range "libdax_msgs" : 0x00000000 to 0x0000ffff + + 0x00000000 (ALL,ZERO) = Initial setting in new libdax_msgs_item + 0x00000001 (DEBUG,ZERO) = Test error message + 0x00000002 (DEBUG,ZERO) = Debugging message + + +------------------------------------------------------------------------------ +Range "elmom" : 0x00010000 to 0x0001ffff + + + +------------------------------------------------------------------------------ +Range "scdbackup" : 0x00020000 to 0x0002ffff + + Acessing and defending drives: + + 0x00020001 (SORRY,LOW) = Cannot open busy device + 0x00020002 (SORRY,HIGH) = Encountered error when closing drive + 0x00020003 (SORRY,HIGH) = Could not grab drive + 0x00020004 (NOTE,HIGH) = Opened O_EXCL scsi sibling + 0x00020005 (SORRY,HIGH) = Failed to open device + 0x00020006 (FATAL,HIGH) = Too many scsi siblings + 0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings + 0x00020008 (SORRY,HIGH) = Device busy. Failed to fcntl-lock + + General library operations: + + 0x00020101 (WARNING,HIGH) = Cannot find given worker item + 0x00020102 (SORRY,HIGH) = A drive operation is still going on + 0x00020103 (WARNING,HIGH) = After scan a drive operation is still going on + 0x00020104 (SORRY,HIGH) = NULL pointer caught + 0x00020105 (SORRY,HIGH) = Drive is already released + 0x00020106 (SORRY,HIGH) = Drive is busy on attempt to close + 0x00020107 (SORRY,HIGH) = Drive is busy on attempt to shut down library + 0x00020108 (SORRY,HIGH) = Drive is not grabbed on disc status inquiry + 0x00020108 (FATAL,HIGH) = Could not allocate new drive object + 0x00020109 (FATAL,HIGH) = Library not running + 0x0002010a (FATAL,HIGH) = Unsuitable track mode + 0x0002010b (FATAL,HIGH) = Burn run failed + 0x0002010c (FATAL,HIGH) = Failed to transfer command to drive + 0x0002010d (DEBUG,HIGH) = Could not inquire TOC + 0x0002010e (FATAL,HIGH) = Attempt to read ATIP from ungrabbed drive + 0x0002010f (DEBUG,HIGH) = SCSI error condition on command + 0x00020110 (FATAL,HIGH) = Persistent drive address too long + 0x00020111 (FATAL,HIGH) = Could not allocate new auxiliary object + 0x00020112 (SORRY,HIGH) = Bad combination of write_type and block_type + 0x00020113 (FATAL,HIGH) = Drive capabilities not inquired yet + 0x00020114 (SORRY,HIGH) = Attempt to set ISRC with bad data + 0x00020115 (SORRY,HIGH) = Attempt to set track mode to unusable value + 0x00020116 (FATAL,HIGH) = Track mode has unusable value + 0x00020117 (FATAL,HIGH) = toc_entry of drive is already in use + 0x00020118 (DEBUG,HIGH) = Closing track + 0x00020119 (DEBUG,HIGH) = Closing session + 0x0002011a (NOTE,HIGH) = Padding up track to minimum size + 0x0002011b (FATAL,HIGH) = Attempt to read track info from ungrabbed drive + 0x0002011c (FATAL,HIGH) = Attempt to read track info from busy drive + 0x0002011d (FATAL,HIGH) = SCSI error on write + 0x0002011e (SORRY,HIGH) = Unsuitable media detected + 0x0002011f (SORRY,HIGH) = Burning is restricted to a single track + 0x00020120 (NOTE,HIGH) = FORMAT UNIT ignored + 0x00020121 (FATAL,HIGH) = Write preparation setup failed + 0x00020122 (FATAL,HIGH) = SCSI error on format_unit + 0x00020123 (SORRY,HIGH) = DVD Media are unsuitable for desired track type + 0x00020124 (SORRY,HIGH) = SCSI error on set_streaming + 0x00020125 (SORRY,HIGH) = Write start address not supported + 0x00020126 (SORRY,HIGH) = Write start address not properly aligned + 0x00020127 (NOTE,HIGH) = Write start address is ... + 0x00020128 (FATAL,HIGH) = Unsupported inquiry_type with mmc_get_performance + 0x00020129 (SORRY,HIGH) = Will not format media type + 0x0002012a (FATAL,HIGH) = Cannot inquire write mode capabilities + 0x0002012b (FATAL,HIGH) = Drive offers no suitable write mode with this job + 0x0002012c (SORRY,HIGH) = Too many logical tracks recorded + 0x0002012d (FATAL,HIGH) = Exceeding range of permissible write addresses + 0x0002012e (NOTE,HIGH) = Activated track default size + 0x0002012f (SORRY,HIGH) = SAO is restricted to single fixed size session + 0x00020130 (SORRY,HIGH) = Drive and media state unsuitable for blanking + 0x00020131 (SORRY,HIGH) = No suitable formatting type offered by drive + 0x00020132 (SORRY,HIGH) = Selected format is not suitable for libburn + 0x00020133 (SORRY,HIGH) = Cannot mix data and audio in SAO mode + 0x00020134 (NOTE,HIGH) = Defaulted TAO to DAO + 0x00020135 (SORRY,HIGH) = Cannot perform TAO, job unsuitable for DAO + 0x00020136 (SORRY,HIGH) = DAO burning restricted to single fixed size track + 0x00020137 (HINT,HIGH) = TAO would be possible + 0x00020138 (FATAL,HIGH) = Cannot reserve track + 0x00020139 (SORRY,HIGH) = Write job parameters are unsuitable + 0x0002013a (FATAL,HIGH) = No suitable media detected + 0x0002013b (DEBUG,HIGH) = SCSI command indicates host or driver error + 0x0002013c (SORRY,HIGH) = Malformed capabilities page 2Ah received + 0x0002013d (DEBUG,LOW) = Waiting for free buffer space takes long time + 0x0002013e (SORRY,HIGH) = Timeout with waiting for free buffer. Now disabled + 0x0002013f (DEBUG,LOW) = Reporting total time spent with waiting for buffer + + + libdax_audioxtr: + 0x00020200 (SORRY,HIGH) = Cannot open audio source file + 0x00020201 (SORRY,HIGH) = Audio source file has unsuitable format + 0x00020202 (SORRY,HIGH) = Failed to prepare reading of audio data + + +------------------------------------------------------------------------------ +Range "vreixo" : 0x00030000 to 0x0003ffff + + Image reading: + 0x00031000 (FATAL,HIGH) = Unsupported ISO-9660 image + 0x00031001 (HINT,MEDIUM) = Unsupported Vol Desc that will be ignored + 0x00031002 (FATAL,HIGH) = Damaged ISO-9660 image + + 0x00030101 (HINT,MEDIUM) = Unsupported SUSP entry that will be ignored + 0x00030102 (SORRY,HIGH) = Wrong/damaged SUSP entry + 0x00030103 (WARNING,MEDIUM)= Multiple SUSP ER entries where found + 0x00030111 (SORRY,HIGH) = Unsupported RR feature + 0x00030112 (SORRY,HIGH) = Error in a Rock Ridge entry + + +------------------------------------------------------------------------------ + +#endif /* LIDBAX_MSGS_________________ */ + + + +#ifdef LIBDAX_MSGS_H_INTERNAL + + /* Internal Functions */ + + +/** Lock before doing side effect operations on m */ +static int libdax_msgs_lock(struct libdax_msgs *m, int flag); + +/** Unlock after effect operations on m are done */ +static int libdax_msgs_unlock(struct libdax_msgs *m, int flag); + + +/** Create new empty message item. + @param link Previous item in queue + @param flag Bitfield for control purposes (unused yet, submit 0) + @return >0 success, <=0 failure +*/ +static int libdax_msgs_item_new(struct libdax_msgs_item **item, + struct libdax_msgs_item *link, int flag); + +/** Destroy a message item obtained by libdax_msgs_obtain(). The submitted + pointer gets set to NULL. + @param flag Bitfield for control purposes (unused yet, submit 0) + @return 1 for success, 0 for pointer to NULL +*/ +static int libdax_msgs_item_destroy(struct libdax_msgs_item **item, int flag); + + +#endif /* LIBDAX_MSGS_H_INTERNAL */ + + +#endif /* ! LIBDAX_MSGS_H_INCLUDED */ diff --git a/libisofs/messages.c b/libisofs/messages.c new file mode 100644 index 0000000..03ecf2d --- /dev/null +++ b/libisofs/messages.c @@ -0,0 +1,144 @@ +#include +#include + +#include "libisofs.h" +#include "messages.h" + +struct libdax_msgs *libdax_messenger = NULL; + +int iso_init() +{ + if (libdax_messenger == NULL) { + if (libdax_msgs_new(&libdax_messenger, 0) <= 0) + return 0; + } + libdax_msgs_set_severities(libdax_messenger, LIBDAX_MSGS_SEV_NEVER, + LIBDAX_MSGS_SEV_FATAL, "libisofs: ", 0); + return 1; +} + +void iso_finish() +{ + libdax_msgs_destroy(&libdax_messenger,0); +} + +void iso_msg_debug(char *msg_text) +{ + libdax_msgs_submit(libdax_messenger, -1, 0x00000002, + LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, + msg_text, 0, 0); +} + +void iso_msg_hint(int error_code, char *msg_text) +{ + libdax_msgs_submit(libdax_messenger, -1, error_code, + LIBDAX_MSGS_SEV_HINT, LIBDAX_MSGS_PRIO_MEDIUM, + msg_text, 0, 0); +} + +void iso_msg_warn(int error_code, char *msg_text) +{ + libdax_msgs_submit(libdax_messenger, -1, error_code, + LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_MEDIUM, + msg_text, 0, 0); +} + +void iso_msg_sorry(int error_code, char *msg_text) +{ + libdax_msgs_submit(libdax_messenger, -1, error_code, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg_text, 0, 0); +} + +void iso_msg_fatal(int error_code, char *msg_text) +{ + libdax_msgs_submit(libdax_messenger, -1, error_code, + LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + msg_text, 0, 0); +} + +/** + * Control queueing and stderr printing of messages from libisofs. + * 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 iso_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 iso_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; +} + +#define ISO_MSGS_MESSAGE_LEN 4096 + +/** + * Obtain the oldest pending libisofs 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 listed in messages.h + * @param msg_text Must provide at least ISO_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 iso_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, ISO_MSGS_MESSAGE_LEN-1); + if(strlen(textpt) >= ISO_MSGS_MESSAGE_LEN) + msg_text[ISO_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; +} diff --git a/libisofs/messages.h b/libisofs/messages.h new file mode 100644 index 0000000..53dfebe --- /dev/null +++ b/libisofs/messages.h @@ -0,0 +1,38 @@ +/* + * Message handling for libisofs + */ + +#ifndef MESSAGES_H_ +#define MESSAGES_H_ + +#include "libdax_msgs.h" + +/** Unsupported image feature */ +#define LIBISO_IMG_UNSUPPORTED 0x00031000 +/** Unsupported Vol Desc that will be ignored */ +#define LIBISO_UNSUPPORTED_VD 0x00031001 +/** damaged image */ +#define LIBISO_WRONG_IMG 0x00031002 + +/* Unsupported SUSP entry */ +#define LIBISO_SUSP_UNHANLED 0x00030101 +/* Wrong SUSP entry, that cause RR to be ignored */ +#define LIBISO_SUSP_WRONG 0x00030102 +/* Unsupported multiple SUSP ER entries where found */ +#define LIBISO_SUSP_MULTIPLE_ER 0x00030103 +/** Unsupported RR feature. */ +#define LIBISO_RR_UNSUPPORTED 0x00030111 +/** Error in a Rock Ridge entry. */ +#define LIBISO_RR_ERROR 0x00030112 + +void iso_msg_debug(char *msg_text); + +void iso_msg_hint(int error_code, char *msg_text); + +void iso_msg_warn(int error_code, char *msg_text); + +void iso_msg_sorry(int error_code, char *msg_text); + +void iso_msg_fatal(int error_code, char *msg_text); + +#endif /*MESSAGES_H_*/ diff --git a/test/iso_grow.c b/test/iso_grow.c new file mode 100644 index 0000000..46f11b7 --- /dev/null +++ b/test/iso_grow.c @@ -0,0 +1,171 @@ +/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ +/* vim: set ts=8 sts=8 sw=8 noet : */ + +#define _GNU_SOURCE + +#include "libisofs.h" +#include "libburn/libburn.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SECSIZE 2048 + +const char * const optstring = "JRL:h"; +extern char *optarg; +extern int optind; + +void usage() +{ + printf("test [OPTIONS] DISC DIRECTORY\n"); +} + +void help() +{ + printf( +"Options:\n" +" -J Add Joliet support\n" +" -R Add Rock Ridge support\n" +" -L Set the ISO level (1 or 2)\n" +" -h Print this message\n" +); +} + +int main(int argc, char **argv) +{ + struct ecma119_source_opts wopts; + struct ecma119_read_opts ropts; + struct data_source *rsrc; + struct iso_volset *volset; + struct iso_volume *volume; + struct iso_tree_node_dir *root; + struct burn_source *wsrc; + unsigned char buf[2048]; + int fd; + int c; + int constraints; + struct iso_tree_radd_dir_behavior behav = {0,0,0}; + int level=1, flags=0; + char *boot_img = NULL; + + while ((c = getopt(argc, argv, optstring)) != -1) { + switch(c) { + case 'h': + usage(); + help(); + exit(0); + break; + case 'J': + flags |= ECMA119_JOLIET; + break; + case 'R': + flags |= ECMA119_ROCKRIDGE; + break; + case 'L': + level = atoi(optarg); + break; + case '?': + usage(); + exit(1); + break; + } + } + + if (argc < optind + 1) { + printf ("Please supply device name\n"); + usage(); + return 1; + } + if (argc < optind + 2) { + printf ("Please supply directory to add to disc\n"); + usage(); + return 1; + } + + if (!iso_init()) { + err(1, "Can't init libisofs"); + } + iso_msgs_set_severities("NEVER", "ALL", ""); + + printf("Reading from %s\n", argv[optind]); + rsrc = data_source_from_file(argv[optind]); + if (rsrc == NULL) { + printf ("Can't open device\n"); + return 1; + } + + ropts.block = 0; /* image always start on first block */ + ropts.norock = 0; + ropts.nojoliet = 0; + ropts.preferjoliet = 0; + ropts.mode = 0555; + ropts.uid = 0; + ropts.gid = 0; + volset = iso_volset_read(rsrc, &ropts); + + if (volset == NULL) { + printf ("Error reading image\n"); + return 1; + } + + printf("Image size: %d blocks.\n", ropts.size); + + /* close source, no more needed */ + data_source_free(rsrc); + + root = iso_volume_get_root(iso_volset_get_volume(volset, 0)); + + /* add a new dir */ + iso_tree_radd_dir(root, argv[optind+1], &behav); + + memset(&wopts, 0, sizeof(struct ecma119_source_opts)); + wopts.level = level; + wopts.flags = flags; + wopts.relaxed_constraints = 0; + wopts.input_charset = "UTF-8"; + wopts.ouput_charset = "UTF-8"; + wopts.ms_block = ropts.size; + wopts.dvd_plus_rw = 1; + + wsrc = iso_source_new_ecma119(volset, &wopts); + + fd = open(argv[optind], O_WRONLY); + if ( fd == -1 ) { + printf ("Can't write to disc\n"); + return 1; + } + printf("HERE %d\n", wopts.vol_desc_count); + /* a. write the new image */ + printf("Adding new data...\n"); + if ( lseek(fd, ropts.size * 2048, SEEK_SET) == (off_t) -1) { + printf ("Can't seek to new location\n"); + return 1; + } + + while (wsrc->read(wsrc, buf, 2048) == 2048) { + write(fd, buf, 2048); + } + + /* b. write the new vol desc */ + printf("Writing the new vol desc...\n"); + if ( lseek(fd, 16 * 2048, SEEK_SET) == (off_t) -1) { + printf ("Can't seek to 16th sector\n"); + return 1; + } + write(fd, wopts.vol_desc, 2048 * wopts.vol_desc_count); + fsync(fd); + close(fd); + + iso_finish(); + + return 0; +}