Filewatcher File Search
FTP Search
  
Directory (beta)
  
Content Search (beta)
   
pkg://xcdroast-debuginfo-0.98a15-14.fc7.ppc.rpm:614443/usr/src/debug/xcdroast-0.98alpha15/src/io.c  info  downloads

/*
	io.c
	All the functions that interact with hardware and subprocesses
	and file IO. 
	28.3.99 tn
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "largefile.h"
#include "gettext.h"

#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#if defined(linux) || defined(__FreeBSD__)
# include <sys/soundcard.h>
# include <sys/ioctl.h>
#endif
#if defined(sun) || defined(__OpenBSD__)
# include <sys/ioctl.h>
# include <sys/audioio.h>
#endif
#ifdef aix
#include <sys/audio.h>
#endif
#ifdef hpux 
# ifndef hpux_alib
#  include <sys/audio.h>
# endif
#endif
#if defined(__sgi)
#include <dmedia/audio.h>
#endif

#if ENABLE_NLS
# define _(String) gettext (String)
# define N_(String) gettext_noop (String)
#else
# define _(String) (String)
# define N_(String) (String)
#endif
#define GTK_ENABLE_BROKEN

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <glib.h>
#include "xcdrdata.h"
#include "xcdroast.h"
#include "main.h"

writerreader_devices_t **writerreaderdevs;
gchar **alt_scsidevices;
cd_info_t cdinfo;
track_info_t **trackinfo;
writer_driver_t **drivers;
writer_driver_t **blankmodes;
write_track_param_t writeparams;
gchar xcdroast_version_loaded[MAXLINE];
gint read_done;
gint read_abort_mark;

static gint scsicount;
static gint busnr;
static gint tocstate;
static gint tocnr;
static gint drvcount;
static gint dfrun;
static gint readcdda_callback;
static gint readcdda_callback2;
static gint readcdda_callback3;
static gint read_output_ctrl;
static gint read_tracknr;
static gchar readtrack_info_string[1024];
static gfloat pct_so_far, pct_this_track;
static pid_t mkisofs_pid;
static pid_t readcdda_pid, readcdda_pid2;
static gint readcd_startsector, readcd_endsector;
static gint readerr_count;
static gint matchnr;
static gint cddb_in;
static gchar cdinfo_cddb_title_bak[MAXLINE];
static gint cd_is_still_the_same;
static gint cdrecord_stdin, cdrecord_reload;
static gint delete_count, delete_start, delete_all;
static gint msinfo_nr1, msinfo_nr2;
static gint cdrtimer, count_mmaperror, checkmedium_found;
static time_t cdrcmdtimer;
static GtkWidget *getcdtoc_atapi_timeout_dialog;

extern gint debug;
extern gint dialog_done2, dialog_done, dialog_done3;
extern setup_data_t setupdata;
extern track_read_set_t trackreadset;
extern current_set_t curset;
extern gchar *system_platform;
extern GtkWidget *toplevel;
extern GtkWidget *viewmode_dialog; 
extern GtkWidget *readtrack_info_label, *readtrack_textview;
extern GtkWidget *readtrack_pbar1, *readtrack_pbar2, *readtrack_pbar3;
extern GtkWidget *readtrack_pbar4, *readtrack_spd;
extern GtkWidget *readtrack_small_info, *readtrack_small_info2;
extern gchar hostname[MAXLINE];
extern gchar username[MAXLINE];
extern gchar sharedir[MAXLINE];
extern gchar configdir[MAXLINE];
extern gchar prefixdir[MAXLINE];
extern GtkWidget *cddb_info_label;
extern GtkCList *cddb_clist;
extern master_param_t masterparam;
extern gchar **charset_types;
extern gchar *master_fname1;
extern gchar *master_fname2;
extern GdkFont *fixedfont;
extern gint support_ontheflyaudio;

static void verify_readcd_err(gpointer pid, gint source, GdkInputCondition cond);
static void read_write_out(gpointer data, gint source, GdkInputCondition cond); 
static gint getdevicecap(gchar *dev, gint *readmax, gint *cdrmax, gint *dvdmax, gint *iscdr, gint *isdvdrom, gint *isdvdr);
static gint check_medium_loaded(gint devnr);
static gint get_cdrecord_toc(gint devnr);
static void remove_tmp_writetracks_tocfile(gchar *tocfile);
static void edit_xinf_for_cd_text2(gchar *infname, gchar *title, gchar *artist, gchar *cdtitle, gchar *cdartist);
static pid_t full_dpl_pipe3(gint *out, gint *in, gint *err, gchar *cmd, 
	gint use_socketpair);


/* convert device-type-names back to numeric */
/* -1 means unknown */

static gint get_scsi_type(gchar *type) {

	if (strcmp(type,"Disk") == 0) {
		return 0;
	}
	if (strcmp(type,"Tape") == 0) {
		return 1;
	}
	if (strcmp(type,"Printer") == 0) {
		return 2;
	}
	if (strcmp(type,"Processor") == 0) {
		return 3;
	}
	if (strcmp(type,"WORM") == 0) {
		return 4;
	}
	if (strcmp(type,"CD-ROM") == 0) {
		return 5;
	}
	if (strcmp(type,"Scanner") == 0) {
		return 6;
	}
	if (strcmp(type,"Optical Storage") == 0) {
		return 7;
	}
	if (strcmp(type,"Juke Box") == 0) {
		return 8;
	}
	if (strcmp(type,"Communication") == 0) {
		return 9;
	}

	return -1;
}


/* convert the scsi-type-number back to string */

#if 0
static void get_scsi_type_string(gchar *str, gint type,  gint removeable) {

	switch(type) {
	case 0:
		if (removeable == 0) {
			strcpy(str,_("Disk"));
		} else {
			strcpy(str,_("Removable Disk"));
		}
		break;
	case 1:
		strcpy(str,_("Tape"));
		break;
	case 2:
		strcpy(str,_("Printer"));
		break;
	case 3:
		strcpy(str,_("Processor/Scanner"));
		break;
	case 4:
		strcpy(str,_("WORM"));
		break;
	case 5:
		strcpy(str,_("CD-ROM"));
		break;
	case 6:
		strcpy(str,_("Scanner"));
		break;
	case 7:
		strcpy(str,_("Optical Storage"));
		break;
	case 8:
		strcpy(str,_("Juke Box"));
		break;
	case 9:
		strcpy(str,_("Communication"));
		break;
	default:
		strcpy(str,"");
		break;
	}
}
#endif


static gint get_cur_audioread_speed() {
gint i;
	i = get_writerreaderdevs_index(curset.reader_devnr);
	return (writerreaderdevs[i]->audioread_speed);
}

static gint get_cur_audioread_overlap() {
gint i;
	i = get_writerreaderdevs_index(curset.reader_devnr);
	return (writerreaderdevs[i]->audioread_overlap);
}

static gint get_cur_audioread_sectorburst() {
gint i;
	i = get_writerreaderdevs_index(curset.reader_devnr);
	return (writerreaderdevs[i]->audioread_sectorburst);
}

static gint get_cur_audioread_useparanoia() {
gint i;
	i = get_writerreaderdevs_index(curset.reader_devnr);
	return (writerreaderdevs[i]->audioread_useparanoia);
}

static gint get_cur_audioread_paranoiaretries() {
gint i;
	i = get_writerreaderdevs_index(curset.reader_devnr);
	return (writerreaderdevs[i]->audioread_paranoiaretries);
}

static gint get_cur_writer_speed() {
gint i;
	i = get_writerreaderdevs_index(curset.writer_devnr);
	return (writerreaderdevs[i]->writer_speed);
}

static gint get_cur_writer_fifo() {
gint i;
	i = get_writerreaderdevs_index(curset.writer_devnr);
	return (writerreaderdevs[i]->writer_fifo);
}

static gint get_cur_writemode() {
gint i;
	i = get_writerreaderdevs_index(curset.writer_devnr);
	return (writerreaderdevs[i]->writer_mode);
}

static gint get_cur_writer_drvmode() {
gint i;
	i = get_writerreaderdevs_index(curset.writer_devnr);
	return (writerreaderdevs[i]->writer_drvmode);
}

 
/* look in given string for "' '" and return index to it */
/* return -1 if not found */

static gint look_for_scan_delimitor(gchar *str) {
gint i;

	for(i = 0; i < strlen(str)-2; i++) {

		if (str[i] == '\'' && str[i+1] == ' ' && str[i+2] == '\'') {
			return i;
		}
	}
	return -1;
}


/* look in given string for "' " and return index to it */
/* return -1 if not found */

static gint look_for_scan_delimitor2(gchar *str) {
gint i;

	for(i = 0; i < strlen(str)-1; i++) {

		if (str[i] == '\'' && str[i+1] == ' ') {
			return i;
		}
	}
	return -1;
}


/* interpret output of -scanbus and sort into memory structure */
/* if idx != -1 then we run in manual-device-mode */

static void parse_scan(gchar *line, gint idx, gint transport, scsi_devices_t **scsidevices) {
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
gchar *p1, *p2;
gint s_id;
gchar s_vendor[9];
gchar s_model[17];
gchar s_rev[5];
gint s_removable;
gint s_type;
gint next;

	/* skip header */
	if (strncmp(line,"Cdrecord",8) == 0) {
		return;
	}
#if 0
	if (strncmp(line,"devname",7) == 0 ) {
		/* set current scsibus nr */
		strcpy(tmp,line+7);
		p1=strtok(tmp,":");
		/* now tmp2 contains the current busnr as string */
		devname = strdup(p1);
		return;
	}
#endif
       if (strncmp(line,"scsibus",7) == 0 ) {
                /* set current scsibus nr */
                strcpy(tmp,line+7);
                p1=strtok(tmp,":");
                strcpy(tmp2,p1);
                /* now tmp2 contains the current busnr as string */
                busnr = atoi(tmp2);
                return;
        }


	/* a line with an error message? */
	/* get_spawn_path(CDRECORD,tmp); */
	strcpy(tmp,"cdrecord: ");
	if (strncmp(line, tmp, strlen(tmp)) == 0) {
		return;
	}

	/* a line with device-info found (by checking for ")")*/
	p1 = index(line,')');
	if (p1 != NULL && !strstr(line,")\"") && 
	   (strstr(line,"\t") || line[0] == ' ')) {
		strip_string(line); 

		/* get scsi-id */
		p1=strtok(line,")");
		if (!p1) return;

		strcpy(tmp,p1);
		strcpy(tmp2,p1);
		/* look for last tab or last space in tmp and remove 
		   everything before */
		p1=rindex(tmp2,'\t');
		p2=rindex(tmp2,' ');
		if (p1 > p2) {
			/* last interesting char was a tab - cut here */
			if (p1 != NULL) {
				strcpy(tmp,p1+1);
			}	
		} else {
			/* last interesting char was a space - cut here */
			if (p2 != NULL) {
				strcpy(tmp,p2+1);
			}	
		}
		s_id = atoi(tmp);	
	
		/* strip host-id from scsi-id-number */
		s_id = s_id % 100;

		p1=strtok(NULL,"'");
		if (p1 == NULL) {
			g_warning("cdrecord scanbus error: Try to remove all media from your CD-ROM drives before starting X-CD-Roast.\n");
			return;
		}

		strcpy(tmp,p1);
		strip_string(tmp);

		if (*tmp == '*') {
			/* no device found */
			return;
		}

		if (*tmp == 'H') {
			/* HOST ADAPTER found */
			/* treat as no device for now */
			return;
		}

		/* get full rest of line */
		p1=strtok(NULL,"");
		if (!p1) return;
		strcpy(tmp,p1);

		if (*tmp == '\'') {
			/* empty device found? ignore */
			return;
		}

		/* e.g. tmp=YAMAHA  ' 'CRW8424S        ' '1.0j' */ 
		/* get vendor */
		next = look_for_scan_delimitor(tmp);
		if (next < 0) {
			g_error("cdrecord -scanbus output syntax error\n");
		}

		strcpy(s_vendor,"        ");
		if (next <= 8) {
			strncpy(s_vendor,tmp,next);
		} else {
			/* strip if to long */
			strncpy(s_vendor,tmp,8);
		}	
		s_vendor[8] = '\0';

		/* get model */
		strcpy(tmp2,tmp+next+3);
		strcpy(tmp,tmp2);
		next = look_for_scan_delimitor(tmp);
		if (next < 0) {
			g_error("cdrecord -scanbus output syntax error\n");
		}
		strcpy(s_model,"                ");
		if (next <= 16) {
			strncpy(s_model,tmp,next);
		} else {
			strncpy(s_model,tmp,16);
		}
		s_model[16] = '\0';

		/* get revision */
		strcpy(tmp2,tmp+next+3);
		strcpy(tmp,tmp2);
		next = look_for_scan_delimitor2(tmp);
		if (next < 0) {
			g_error("cdrecord -scanbus output syntax error\n");
		}
		strcpy(s_rev,"    ");
		if (next <= 4) {
			strncpy(s_rev,tmp,next);
		} else {
			strncpy(s_rev,tmp,4);
		}
		s_rev[4] = '\0';

		/* get type */
		strcpy(tmp2,tmp+next+2);
		strcpy(tmp,tmp2);
		strip_string(tmp);

		if (strncmp(tmp,"Removable",9) == 0) {
			s_removable = 1;
			strcpy(tmp2,tmp+10);
			strcpy(tmp,tmp2);
		} else {
			s_removable = 0;
		}
		
		s_type = get_scsi_type(tmp);

		/* allocate and fill structure */
		scsidevices[scsicount]=g_new(scsi_devices_t,1);
		if (idx == -1) {
			/* autoscan mode */
			scsidevices[scsicount]->devnr = 
				transport*1024+busnr*32+s_id;
			scsidevices[scsicount]->alt_dev = -1;
		} else {
			/* manual mode */
			scsidevices[scsicount]->devnr = idx;
			scsidevices[scsicount]->alt_dev = idx;
		}

		scsidevices[scsicount]->sector_size = DATASECTORSIZE;
		scsidevices[scsicount]->transport = transport;
		scsidevices[scsicount]->bus = busnr;
		scsidevices[scsicount]->id = s_id;
		strcpy(scsidevices[scsicount]->vendor,s_vendor);
		strcpy(scsidevices[scsicount]->model,s_model);
		strcpy(scsidevices[scsicount]->rev,s_rev);
		scsidevices[scsicount]->removable = s_removable;
		scsidevices[scsicount]->type = s_type;
		
		scsicount++;
		if (scsicount >= MAXDEVICES) {
			g_error("Error: More than %d devices scanned\n",MAXDEVICES);
		}
	}
}


/* print memory-structure with scsidevices (debug purposes) */
#if 0
static void print_scsidevices(scsi_devices_t **scsidevices) {
gint count;

	dodebug(2,"------ cdrecord scsidevices-structure -----\n");
	count = 0;
	while(scsidevices[count] != NULL) {
		dodebug(2,"devnr=%d %d:%d %s %s %s %d,%d (alt: %d) (ssize: %d)\n",
			scsidevices[count]->devnr,
			scsidevices[count]->bus,
			scsidevices[count]->id,
			scsidevices[count]->vendor,
			scsidevices[count]->model,
			scsidevices[count]->rev,
			scsidevices[count]->removable,
			scsidevices[count]->type,
			scsidevices[count]->alt_dev,
			scsidevices[count]->sector_size);
			
		count++;
	}
}
#endif

static void print_writerreaderdevs() {
gint count;

	dodebug(2,"------ cdrecord writerreaderdevs-structure -----\n");
	count = 0;
	while(writerreaderdevs[count] != NULL) {
		dodebug(2, "devnr=%d (%s) [%s %s %s] (ssize: %d)\n", 
			writerreaderdevs[count]->devnr,
			writerreaderdevs[count]->devicestr,
			writerreaderdevs[count]->vendor,
			writerreaderdevs[count]->model,
			writerreaderdevs[count]->rev,
			writerreaderdevs[count]->sector_size);
		dodebug(2, "  readmax: %d, cdrmax: %d, dvdmax: %d, is_cdrwriter: %d, is_dvdreader: %d, is_dvdwriter: %d\n",
			writerreaderdevs[count]->writer_readmaxspeed,
			writerreaderdevs[count]->writer_cdrmaxspeed,
			writerreaderdevs[count]->writer_dvdmaxspeed,
			writerreaderdevs[count]->is_cdrwriter,
			writerreaderdevs[count]->is_dvdreader,
			writerreaderdevs[count]->is_dvdwriter,
			writerreaderdevs[count]->sector_size);
		dodebug(2, "  writer_flags: %s\n", 
			writerreaderdevs[count]->writer_flags);
		dodebug(2, "  writer_modes: %s\n", 
			writerreaderdevs[count]->writer_modes);
			
		count++;
	}
}


/* create a new writer/reader entry */

static gint add_writerreader(scsi_devices_t *scsidev, gchar *transport, GtkWidget *txt) {
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
gchar drvflags[MAXLINE], drvmodes[MAXLINE];
gint readmax, cdrmax, dvdmax, iscdr, isdvdr, isdvdrom;
gint count;
gint mmap_error;
gint i;
static const gchar *writemodes[] = WRITE_MODES;

	/* first search last entry of writerreader struct */
	count = 0;
	while(writerreaderdevs[count] != NULL) {
		if (count == MAXDEVICES-1) {
			return 0;
		}
		count++;
	}

	/* only add type WORM and CD-ROM types */
	if (scsidev->type != 4 && scsidev->type != 5) {
		return 0;
	}

	/* build device string */
	if (scsidev->alt_dev == -1) {
		g_snprintf(tmp,MAXLINE,"%s%d,%d,%d",
			transport, scsidev->bus, scsidev->id, 0);
	} else {
		strncpy(tmp, transport, MAXLINE);
	}	

	/* check if this device already exists */
	if (get_writerreaderdevs_index_from_devstr(tmp) != -1) {
		if (txt) {
			g_snprintf(tmp2,MAXLINE,"([%s] %s %s %s)\n",
				tmp, scsidev->vendor,
				scsidev->model, scsidev->rev);
			convert_for_gtk2_textwidget(tmp2);
               	 	gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp2, strlen(tmp2));
                	wait_and_process_events();      
		}
		return 0;
	}

	/* create a new entry */
	writerreaderdevs[count]=g_new0(writerreader_devices_t,1);
	writerreaderdevs[count]->devnr = scsidev->devnr;
	writerreaderdevs[count]->devicestr = g_strdup(tmp);
	strncpy(writerreaderdevs[count]->vendor, scsidev->vendor,9);
	strncpy(writerreaderdevs[count]->model, scsidev->model,17);
	strncpy(writerreaderdevs[count]->rev, scsidev->rev,5);
	writerreaderdevs[count]->sector_size = scsidev->sector_size;

	getmodesflags(tmp, drvflags, drvmodes); 
	writerreaderdevs[count]->writer_flags = g_strdup(drvflags);
	writerreaderdevs[count]->writer_modes = g_strdup(drvmodes);

	/* get more detailed information about this device */
        mmap_error=getdevicecap(tmp, &readmax, &cdrmax, &dvdmax, &iscdr, &isdvdrom, &isdvdr);
	writerreaderdevs[count]->writer_readmaxspeed = readmax;
	writerreaderdevs[count]->writer_cdrmaxspeed = cdrmax;
	writerreaderdevs[count]->writer_dvdmaxspeed = dvdmax;
	writerreaderdevs[count]->is_cdrwriter = iscdr;
	writerreaderdevs[count]->is_dvdreader = isdvdrom;
	writerreaderdevs[count]->is_dvdwriter = isdvdr;
	

	/* workaround for non-mcc drives */
	if (writerreaderdevs[count]->is_cdrwriter == 0) {
		/* not detected as writer, but got write modes? */
		if (strlen(drvmodes) > 0) {
			/* assume its really a writer then */
			writerreaderdevs[count]->is_cdrwriter = 1;
		}
	}

	/* set defaults for other fields */
	writerreaderdevs[count]->writer_drvmode = -1;
	writerreaderdevs[count]->writer_speed = cdrmax;
	writerreaderdevs[count]->writer_fifo = 4096;

	/* get the first supported mode for that writer */
	i = 0;
	while (writemodes[i]) {
		if (writemode_supported(i, scsidev->devnr)) {
			writerreaderdevs[count]->writer_mode = i; 
			break;
		}	
		i++;
	}

	writerreaderdevs[count]->audioread_interface = 0;
	writerreaderdevs[count]->audioread_speed = readmax;
	writerreaderdevs[count]->audioread_overlap = 0;
	writerreaderdevs[count]->audioread_sectorburst = 75;
	writerreaderdevs[count]->audioread_useparanoia = 0;
	writerreaderdevs[count]->audioread_paranoiaretries = 20;

	/* add to dialog window */
        if (txt) {
		g_snprintf(tmp2,MAXLINE,"[%s] %s %s %s\n",
			tmp, scsidev->vendor,
			scsidev->model, scsidev->rev);
		convert_for_gtk2_textwidget(tmp2);
                gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp2, strlen(tmp2));
                wait_and_process_events();      
	}

	return mmap_error;
}


/* does scan for a single device only */
/* return 1 when new device was found */

static gint scanbus_single(gchar *dev, gint newdevnr, GtkWidget *txt) {
gchar line[MAXLINE];
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
FILE *fpin;
scsi_devices_t **scsidevices;
gint found;

	scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
	scsicount = 0;

	get_wrap_path_cdrecord(line);

	/* make sure we escape any critical chars in input */
	strncpy(tmp2,dev,MAXLINE);
	convert_escape(tmp2);

	g_snprintf(tmp,MAXLINE," -scanbus dev= \"%s\" 2>&1",tmp2);
	strcat(line,tmp);

	dodebug(1, "calling: %s\n", line);
        if ((fpin = popen(line,"r")) == NULL) {
                g_error("popen error\n");
        }

        for (;;) {
                if (fgets(line,MAXLINE,fpin) == NULL) 
                        break;
		dodebug(10,"scanbus: %s",line);
                parse_scan(line, newdevnr, 0, scsidevices);
        }

        if (pclose(fpin) == -1) {
                g_error("pclose error\n");
        }

	found = 0;
	if (scsidevices[0]) {
		add_writerreader(scsidevices[0], dev, txt);
		g_free(scsidevices[0]);
		found = 1;
	}
	g_free(scsidevices);

	return found;
}


#if (defined(__MACH__) && defined(__APPLE__)) 

/* interpret output of -inq and sort into memory structure */
/* if idx != -1 then we run in manual-device-mode */

static void parse_inq(gchar *line, gint idx, scsi_devices_t **scsidevices) {
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
gchar *p;
gchar s_vendor[9];
gchar s_model[17];
gchar s_rev[5];
gint s_removable;
gint s_type;


	if (strncmp("Device type",line,11) == 0) {
		p = strtok(line,":");
		if (p) {
			p = strtok(NULL,"");
			if (p) {
				strcpy(tmp,p);
				strip_string(tmp);
				if (strncmp(tmp,"Removable",9) == 0) {
					s_removable = 1;
					strcpy(tmp2,tmp+10);
					strcpy(tmp,tmp2);
				} else {
					s_removable = 0;
				}
		
				s_type = get_scsi_type(tmp);

				/* allocate entry now */
				scsidevices[scsicount]=g_new(scsi_devices_t,1);
				scsidevices[scsicount]->sector_size = DATASECTORSIZE;
				scsidevices[scsicount]->devnr = idx;
				scsidevices[scsicount]->alt_dev = idx;
				scsidevices[scsicount]->transport = 0;
				scsidevices[scsicount]->bus = 0;
				scsidevices[scsicount]->id = idx;
				scsidevices[scsicount]->removable = s_removable;
				scsidevices[scsicount]->type = s_type;
			}
		}
	}

	if (strncmp("Vendor_info",line,11) == 0) {
		p = strtok(line,":");
		if (p) {
			p = strtok(NULL,"");
			if (p) {
				strcpy(tmp2,p);
				extract_singlequoted(tmp2);

				strcpy(s_vendor,"        ");
				if (strlen(tmp2) <= 8) {
					strncpy(s_vendor,tmp2,strlen(tmp2));
				} else {
					/* strip if to long */
					strncpy(s_vendor,tmp2,8);
				}	
				s_vendor[8] = '\0';

				if (scsidevices[scsicount]) {
					strcpy(scsidevices[scsicount]->vendor,s_vendor);
				}
			}
		}
	}

	if (strncmp("Identifikation",line,14) == 0) {
		p = strtok(line,":");
		if (p) {
			p = strtok(NULL,"");
			if (p) {
				strcpy(tmp2,p);
				extract_singlequoted(tmp2);

				strcpy(s_model,"                ");
				if (strlen(tmp2) <= 16) {
					strncpy(s_model,tmp2,strlen(tmp2));
				} else {
					strncpy(s_model,tmp2,16);
				}
				s_model[16] = '\0';

				if (scsidevices[scsicount]) {
					strcpy(scsidevices[scsicount]->model,s_model);
				}	
			}
		}
	}

	if (strncmp("Revision",line,8) == 0) {
		p = strtok(line,":");
		if (p) {
			p = strtok(NULL,"");
			if (p) {
				strcpy(tmp2,p);
				extract_singlequoted(tmp2);

				strcpy(s_rev,"    ");
				if (strlen(tmp2) <= 4) {
					strncpy(s_rev,tmp2,strlen(tmp2));
				} else {
					strncpy(s_rev,tmp2,4);
				}
				s_rev[4] = '\0';

				if (scsidevices[scsicount]) {
					strcpy(scsidevices[scsicount]->rev,s_rev);
					scsicount++;
				}
			}
		}
	}

	if (scsicount >= MAXDEVICES) {
		g_error("Error: More than %d devices scanned\n",MAXDEVICES);
	}
}


/* does scan for a single device only via inq call (osX) */

static gint scanbus_via_inq(gchar *dev, gint newdevnr, GtkWidget *txt) {
gchar line[MAXLINE];
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
FILE *fpin;
scsi_devices_t **scsidevices;
gint found;

        scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
        scsicount = 0;

	get_wrap_path_cdrecord(line);

	/* make sure we escape any critical chars in input */
	strncpy(tmp2,dev,MAXLINE);
	convert_escape(tmp2);

	g_snprintf(tmp,MAXLINE," -inq dev= \"%s\" 2>&1",tmp2);
	strcat(line,tmp);

	dodebug(1, "calling: %s\n", line);
        if ((fpin = popen(line,"r")) == NULL) {
                g_error("popen error\n");
        }

        for (;;) {
                if (fgets(line,MAXLINE,fpin) == NULL) 
                        break;
		dodebug(10,"scanbus: %s",line);
                parse_inq(line, newdevnr, scsidevices);
        }

        if (pclose(fpin) == -1) {
                g_error("pclose error\n");
        }

        found = 0;
        if (scsidevices[0]) {
                add_writerreader(scsidevices[0], dev, txt);
                g_free(scsidevices[0]);
                found = 1;
        }
        g_free(scsidevices);

        return found;
}

#endif

/* scanbus scsi */

static void scan_traditional(GtkWidget *txt) {
gchar line[MAXLINE];
FILE *fpin;
gint count, errcount, ret;
scsi_devices_t **scsidevices;

	scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
	scsicount = 0;

	/* traditional scanning first */
	get_wrap_path_cdrecord(line);
	strcat(line," -scanbus 2>&1");

	dodebug(1, "calling: %s\n", line);
        if ((fpin = popen(line,"r")) == NULL) {
                g_error("popen error\n");
        }

        for (;;) {
                if (fgets(line,MAXLINE,fpin) == NULL) 
                        break;
		dodebug(10,"scanbus: %s",line);
                parse_scan(line, -1, 0, scsidevices);
        }

        if (pclose(fpin) == -1) {
                g_error("pclose error\n");
        }

	/* add the found devices to the writerreader structure */
	count = 0;
	errcount = 0;
	while(scsidevices[count] != NULL) {
		errcount+=add_writerreader(scsidevices[count],"", txt);
		g_free(scsidevices[count]);
		count++;
	}
	g_free(scsidevices);

	/* historic mmap error check */
	if (errcount > 0) {
                ret = show_dialog(ICO_WARN, _("Warning: The cdrtools binaries you have installed are\nnot compatible with your system. You will NOT be\nable to read or write CDs. Please read the FAQ\non www.xcdroast.org for more information."), T_ANYWAY, _("Exit"), NULL, 1);
                if (ret == 1)
                        gtk_exit(1);
	}
}


/* alternative transport method scanning */
/* valid transport choices for now: ATAPI USCSI REMOTE */

static gint scan_other(gchar *transport, gint transid, GtkWidget *txt) {
gchar line[MAXLINE];
gchar tmp[MAXLINE];
FILE *fpin;
gint count;
scsi_devices_t **scsidevices;

	scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
	scsicount = 0;

	get_wrap_path_cdrecord(line);
	g_snprintf(tmp,MAXLINE," dev=%s -scanbus 2>&1", transport);
	strcat(line, tmp);
	
	dodebug(1, "calling: %s\n", line);
       	if ((fpin = popen(line,"r")) == NULL) {
               	 g_error("popen error\n");
       	}

        for (;;) {
         	if (fgets(line,MAXLINE,fpin) == NULL) 
                       	break;
		dodebug(10,"scanbus (%s): %s", transport, line);
               	parse_scan(line, -1, transid, scsidevices);
       	}

       	if (pclose(fpin) == -1) {
               	g_error("pclose error\n");
       	}

	/* add the found devices to the writerreader structure */
	count = 0;
	g_snprintf(tmp,MAXLINE,"%s:", transport);
	while(scsidevices[count] != NULL) {
		add_writerreader(scsidevices[count], tmp, txt);
		g_free(scsidevices[count]);
		count++;
	}
	g_free(scsidevices);

	return count;
}


/* new scanbus version */

void scanbus_new(GtkWidget *txt, gint scanparam) {
gchar tmp[MAXLINE];
GdkFont *boldfont;
gint doscanbus;
gint i, devnr;

	/* allocate memory */
	if (!writerreaderdevs) {
		writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
	}

	boldfont = get_some_font(BOLDFONT);
	doscanbus = 1;

	/* output status texts? */
	if (txt) {
		strncpy(tmp,_("Starting to scan for devices...\n"), MAXLINE);
		convert_for_gtk2_textwidget(tmp);
		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
		wait_and_process_events();	
	}

	/* check if we have to do full scanbus, or only partial */
	if (alt_scsidevices[0] != NULL) {
		i = 0;
		while (alt_scsidevices[i] != NULL) {
			/* look for a free device number (greater 8192) */
			for (devnr = 8192; devnr < 8192 + MAXDEVICES; devnr++) {
				if (get_writerreaderdevs_index(devnr) == -1) {
					break;
				}	
			}	
			scanbus_single(alt_scsidevices[i], devnr, txt);
			i++;
		}		

		/* trigger not to scan the bus any futher */
		doscanbus = 0;
	}

#if (defined(__MACH__) && defined(__APPLE__)) 

	/* special handling for osX */
	/* try fixed list of devices */
	alt_scsidevices[0] = g_strdup("IOCompactDiscServices");
	alt_scsidevices[1] = g_strdup("IOCompactDiscServices/2");
	alt_scsidevices[2] = g_strdup("IOCompactDiscServices/3");
	alt_scsidevices[3] = g_strdup("IODVDServices");
	alt_scsidevices[4] = g_strdup("IODVDServices/2");
	alt_scsidevices[5] = g_strdup("IODVDServices/3");

	i = 0;
	while (alt_scsidevices[i] != NULL) {
		scanbus_via_inq(alt_scsidevices[i], 4096+i, txt);
		i++;
	}		
	
	/* trigger not to scan the bus any futher */
	doscanbus = 0;
#endif

	if (doscanbus) {
		/* scan for scsi devices */
		scan_other("ATA", 1, txt);
		scan_traditional(txt);

		/* scan for alternatives */
#if defined(linux)
		if (scanparam) {
			scan_other("ATAPI", 2, txt);
		}
#endif
#if defined(sun)
		if (scanparam) {
			scan_other("USCSI", 3, txt);
		}
#endif
	}

	if (txt) {
		strncpy(tmp,_("Scan finished.\n"), MAXLINE);
		convert_for_gtk2_textwidget(tmp);
		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
		wait_and_process_events();	
	}

	gdk_font_unref(boldfont);


	if (debug) print_writerreaderdevs();

}



/* scan for remote scsi devices */

void scanbus_rscsi(gchar *devstr, GtkWidget *txt) {
gchar tmp[MAXLINE];
GdkFont *boldfont;
gint found;
gint i, highest;

	/* allocate memory */
	if (!writerreaderdevs) {
		writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
	}

	boldfont = get_some_font(BOLDFONT);

	/* output status texts? */
	if (txt) {
		strncpy(tmp,_("Starting to scan for remote devices...\n"), MAXLINE);
		convert_for_gtk2_textwidget(tmp);
		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
		wait_and_process_events();	
	}

	/* look for highest free devnr - but at least a multiple of 16384 */
	i = 0;
	highest = -1;
	while(writerreaderdevs[i] != NULL) {
		if (writerreaderdevs[i]->devnr > highest) {
			highest = writerreaderdevs[i]->devnr;
		}
		i++;
	}
	highest++;

	/* when we scan multiple times always arange a new block to play safe */
	highest = ((highest/16384)+1)*16384;

	found = scan_other(devstr, highest/1024, txt);

	if (txt) {
		if (found == 0) {
			strncpy(tmp,_("No devices found - check your remote scsi setup.\n"), MAXLINE);
			convert_for_gtk2_textwidget(tmp);
			gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp, strlen(tmp));
		}
		strncpy(tmp,_("Scan finished.\n"), MAXLINE);
		convert_for_gtk2_textwidget(tmp);
		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
		wait_and_process_events();	
	}

	gdk_font_unref(boldfont);


	if (debug) print_writerreaderdevs();
}


/* special version where we scan only for a single device */

void scanbus_new_single(gchar *devstr, GtkWidget *txt) {
gchar tmp[MAXLINE];
GdkFont *boldfont;
gint devnr, found;

	/* allocate memory */
	if (!writerreaderdevs) {
		writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
	}

	boldfont = get_some_font(BOLDFONT);

	/* output status texts? */
	if (txt) {
		strncpy(tmp,_("Starting to scan for devices...\n"), MAXLINE);
		convert_for_gtk2_textwidget(tmp);
		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
		wait_and_process_events();	
	}

	/* look for a free device number (greater 8192) */
	for (devnr = 8192; devnr < 8192 + MAXDEVICES; devnr++) {
		if (get_writerreaderdevs_index(devnr) == -1) {
			break;
		}	
	}	
	found = scanbus_single(devstr, devnr, txt);

	if (txt) {
		if (!found) {
			strncpy(tmp,_("Device not found.\n"), MAXLINE);
			convert_for_gtk2_textwidget(tmp);
			gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp, strlen(tmp));
		}
		strncpy(tmp,_("Scan finished.\n"), MAXLINE);
		convert_for_gtk2_textwidget(tmp);
		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
		wait_and_process_events();	
	}

	gdk_font_unref(boldfont);


	if (debug) print_writerreaderdevs();
}


/* interpret output of driver=help and sort into memory structure */

static void parse_driver(gchar *line) {
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
gchar drv[MAXLINE];
gchar *p1;
gint n;
	if (strncmp(line,"Driver types:",13) != 0 ) {

		strcpy(tmp,line);
		p1=strtok(tmp," ");
		strcpy(drv,p1);	
		/* now drv contains the driver name */

		p1=strtok(NULL,"");
		strcpy(tmp2,p1);
		strip_string(tmp2);
		/* now tmp2 contains the description */

		/* cut "driver for" away */ 
		if (strncmp(tmp2,"driver for ",11) == 0 ){
			strcpy(tmp,tmp2+11);
			strcpy(tmp2,tmp);
		}

		/* allocate structure */
		drivers[drvcount]=g_new(writer_driver_t,1);

		n = strlen(drv)+1;
		drivers[drvcount]->driver=g_new(gchar,n);
		strcpy(drivers[drvcount]->driver,drv);

		n = strlen(tmp2)+1;
		drivers[drvcount]->desc=g_new(gchar,n);
		strcpy(drivers[drvcount]->desc,tmp2);

		drvcount++;
		if (drvcount >= MAXDRIVERS) {
			g_error("Error: More than %d writer devices found\n",MAXDRIVERS);
		}
	}
}


/* print memory-structure with drivers (debug purposes) */

static void print_drivers() {
gint count;

	dodebug(2,"------ cdrecord drivers-structure -----\n");
	count = 0;
	while(drivers[count] != NULL) {
		dodebug(2, "%s:%s\n",
			drivers[count]->driver,
			drivers[count]->desc);
			
		count++;
	}
}


/* call cdrecord driver=help */

void scandrivers() {
gchar line[MAXLINE];
FILE *fpin;

	/* allocate memory */
	drivers = g_new0(writer_driver_t *,MAXDRIVERS);
	drvcount = 0;

	get_wrap_path_cdrecord(line);
	strcat(line," driver=help 2>&1");

	dodebug(1, "calling: %s\n", line);
        if ((fpin = popen(line,"r")) == NULL) {
                g_error("popen error\n");
        }

        for (;;) {
                if (fgets(line,MAXLINE,fpin) == NULL) 
                        break;
		dodebug(10, "driverlist: %s",line);
                parse_driver(line);
        }

        if (pclose(fpin) == -1) {
                g_error("pclose error\n");
        }

	if (debug) print_drivers();
}


/* print memory-structure with charsets (debug purposes) */

static void print_charsets() {
gint count;
gchar tmp[MAXLINE];

	dodebug(2,"------ mkisofs-charsets-structure -----\n");
	count = 0;
	strcpy(tmp,"");	
	while(charset_types[count] != NULL) {

		strcat(tmp,charset_types[count]);

		if ((count+1) % 6) {
			strcat(tmp, ", ");
		} else {
			dodebug(2, "%s\n", tmp);
			strcpy(tmp,"");	
		}
		count++;
	}
	if (strcmp(tmp,"") != 0) 
		dodebug(2, "%s\n", tmp);
}


/* call mkisofs -input-charset help */

void scancharsets() {
gchar line[MAXLINE];
FILE *fpin;
gint start,count,backcount;
gchar **tmp_types;

	/* allocate memory */
	charset_types = g_new0(gchar *,MAXCHARSETS+1);
	tmp_types = g_new0(gchar *,MAXCHARSETS+1);

	start = 0;
	count = 0;

	get_wrap_path("MKISOFS",line);
	strcat(line," -input-charset help 2>&1");

	dodebug(1, "calling: %s\n", line);
        if ((fpin = popen(line,"r")) == NULL) {
                g_error("popen error\n");
        }

        for (;;) {
                if (fgets(line,MAXLINE,fpin) == NULL) 
                        break;
		/* wait for Known charsets.... line */
		if (strncmp("Known",line,5) == 0) {
			start = 1;
			continue;
		}
		if (start) {
			dodebug(10, "mkisofs charsets: %s",line);

			tmp_types[count] = g_strdup(strip_string(line));
			count++;		
			if (count >= MAXCHARSETS) {
				g_error("Error: More than %d input charsets found\n",MAXCHARSETS);
			}
		}
        }

	tmp_types[count] = g_strdup("default");
	
        if (pclose(fpin) == -1) {
                g_error("pclose error\n");
        }

	/* now the types list is reversed, make it right */
	backcount = count;
	count = 0;
	while(backcount >= 0) {
		charset_types[count] = tmp_types[backcount];
		count++;
		backcount--;
	}
	g_free(tmp_types);

	if (debug) print_charsets();
}


/* call cdrecord -prcap to get some device information */
/* also checks for mmap errors and return 1 if one occured */

static gint getdevicecap(gchar *dev, gint *readmax, gint *cdrmax, gint *dvdmax, gint *iscdr, gint *isdvdrom, gint *isdvdr) {
gchar tmp[MAXLINE];
gchar line[MAXLINE];
gint tmpnr, errcount;
FILE *fpin;
gchar *p;

	/* set reasonable defaults */
	*readmax = 0;
	*cdrmax = 0;
	*dvdmax = 0;
	*iscdr = 0;
	*isdvdr = 0;
	*isdvdrom = 0;

        if (!dev) return 0;

        get_wrap_path_cdrecord(tmp);
        g_snprintf(line, MAXLINE, "%s dev= \"%s\" -prcap 2>&1", tmp, dev);

        dodebug(1, "calling: %s\n", line);
        if ((fpin = popen(line,"r")) == NULL) {
                g_error("popen error\n");
        }

	errcount = 0;
        for (;;) {
                if (fgets(line,MAXLINE,fpin) == NULL) 
                        break;
                dodebug(10, "prcap: %s",line);

                /* line with mmap error? */
                if (strstr(line,"annot get mmap for")) {
                        errcount++;
                }

		if (strstr(line, "Does write CD-R media")) {
			*iscdr = 1;
		}
		if (strstr(line, "Does read DVD-ROM media")) {
			*isdvdrom = 1;
		}
		if (strstr(line, "Does write DVD-R media")) {
			*isdvdr = 1;
		}
		if (strstr(line, "Maximum read  speed:")) {
			p = strtok(line,"(");
			if (p) {
				p = strtok(NULL,")");
				if (p) {
					strcpy(tmp,p);
					sscanf(tmp,"CD %3dx, DVD %3d",
						readmax, &tmpnr);
				}
			}
		} else 
		if (strstr(line, "Maximum write speed:")) {
			p = strtok(line,"(");
			if (p) {
				p = strtok(NULL,")");
				if (p) {
					strcpy(tmp,p);
					sscanf(tmp,"CD %3dx, DVD %3d",
						cdrmax, dvdmax);
				}
			}
		}
	}

        if (pclose(fpin) == -1) {
                g_error("pclose error\n");
        }

        if (errcount > 0) {
                return 1;
        } else {
                return 0;
        }
}


/* get driverflags and modes from drive */

void getmodesflags(gchar *dev, gchar *drvflags, gchar *drvmodes) {
gchar tmp[MAXLINE];
gchar line[MAXLINE];
FILE *fpin;
gchar *p;

	strcpy(drvflags,"");
	strcpy(drvmodes,"");

        if (!dev) return;

	/* if prodvd available use it to get additional info */
       	get_wrap_path_cdrecord(tmp);
        g_snprintf(line, MAXLINE, "%s dev= \"%s\" -v -checkdrive 2>&1", tmp, dev);

        dodebug(1, "calling: %s\n", line);
        if ((fpin = popen(line,"r")) == NULL) {
                g_error("popen error\n");
        }
        for (;;) {
                if (fgets(line,MAXLINE,fpin) == NULL) 
                        break;
                dodebug(10, "checkdrive: %s",line);

		if (strstr(line, "Driver flags   :")) {
			p = strtok(line,":");
			if (p) {
				p = strtok(NULL,"");
				if (p) {
					strncpy(tmp,p,MAXLINE);
					strip_string(tmp);
					strncpy(drvflags,tmp,MAXLINE);
				}
			}
		} else 
		if (strstr(line, "Supported modes:")) {
			p = strtok(line,":");
			if (p) {
				p = strtok(NULL,"");
				if (p) {
					strncpy(tmp,p,MAXLINE);
					strip_string(tmp);
					strncpy(drvmodes,tmp,MAXLINE);
				}
			}
		}
	}

        if (pclose(fpin) == -1) {
                g_error("pclose error\n");
        }
}


static gint parse_freespace(gchar *line, gchar *fs) {
gchar tmp[MAXLINE];
gchar *p1;

	/* skip first line(s) */
	if (index(line,'/')) {
	        strcpy(tmp,line);
#if defined (aix)
		/* filesystem label */
		p1=strtok(tmp," ");
		if (fs != NULL) {
		     /* get the filesystem */
		     strcpy(fs,p1);
		}
		/* size of filesystem */
		p1=strtok(NULL," ");
		if (p1 == NULL) { 
			g_error("df -k output syntax error\n");
		}
		/* available blocks */
		p1=strtok(NULL," ");
		if (p1 == NULL) { 
			g_error("df -k output syntax error\n");
		}
		return (atoi(p1));
#elif defined (hpux)
		/* mountpoint */
		p1=strtok(tmp,"(");
		if (p1 == NULL) { 
			g_error("df -b output syntax error\n");
		}
		/* filesystem label */
		p1=strtok(NULL,")");
		if (fs != NULL) {
		     /* get the filesystem - avoid "(" at the beginning */
		     strcpy(fs,p1);
		}
		/* size in kb */
		p1=strtok(NULL,": ");
		if (p1 == NULL) { 
			g_error("df -b output syntax error\n");
		}		
		return (atoi(p1));
#else

		/* skip the first 4 fields in output to come to "available" */

		/* are we handling the first line of two?*/
		p1=strtok(tmp," ");

		if (dfrun == 0) {
			if (fs != NULL) {
				/* get the filesystem */
				strcpy(fs,p1);
			}

			p1=strtok(NULL," ");
			if (p1 == NULL) {
				/* ok..output splitted on two lines */
				dfrun = 1;
				return -1;
			}
		}
		p1=strtok(NULL," ");
		if (p1 == NULL) {
			g_error("df -k output syntax error\n");
		} 
		p1=strtok(NULL," ");
		if (p1 == NULL) { 
			g_error("df -k output syntax error\n");
		}
		return (atoi(p1));
#endif
	}
	return -1;
}


/* get free diskspace. return in 1024byte blocks or -1 if not valid */
/* return filesystem if not set to NULL */
/* will handle if output is in two lines...like when the filesystem
   output is longer that 20 chars - e.g. on nfs-links */
/* will handle df-output like:

(Solaris)
Filesystem            kbytes    used   avail capacity  Mounted on
fileserv:/export/home
                     17502608 11609120 5718464    67%    /export/home

OR

(Linux)
Filesystem         1024-blocks  Used Available Capacity Mounted on
/dev/sda3            2494898 1606489   759428     68%   /

Système de
fichiers          1K-blocs    Utilisé Disponible U.% Monté sur
/dev/hda6             10080488   8043456   1524964  85% /

OR

(AIX)
Filesystem    1024-blocks      Free %Used    Iused %Iused Mounted on
/dev/hd4             8192      2968   64%     1319    33% /
/dev/hd2           573440     31644   95%    22280    16% /usr

OR

(HP-UXs df -b)
/tmp                   (/dev/vg00/lvol4       ) :   188158 Kbytes free
/usr                   (/dev/vg00/lvol5       ) :   286696 Kbytes free


*/

gint get_free_space(gchar *path, gchar *filesystem) {
gchar line[MAXLINE];
FILE *fpin;
gint space;

	space = -1;
	dfrun = 0;

	if (is_directory(path) != 1) {
		return -1;
	}

	if (stat_file(DF)) {
		strcpy(line,DF);
		strcat(line," \"");
		strcat(line,path);
		strcat(line,"\"");
	} else {
		strcpy(line,DF2);
		strcat(line," \"");
		strcat(line,path);
		strcat(line,"\"");
	}

	dodebug(1, "calling: %s\n", line);
        if ((fpin = popen(line,"r")) == NULL) {
                g_error("popen error\n");
        }

        for (;;) {
                if (fgets(line,MAXLINE,fpin) == NULL) 
                        break;
		dodebug(10,"df: %s",line);
                space = parse_freespace(line,filesystem);
        }

        if (pclose(fpin) == -1) {
                g_error("pclose error\n");
        }

	if (filesystem != NULL) {
		dodebug(2, "filesystem lookup for %s = %d blocks, fs = %s\n", 
			path, space, filesystem);
	} else {
		dodebug(2, "filesystem lookup for %s = %d blocks, fs = %s\n", 
			path, space, "(NULL)");
	}
 
	return space;
}


/* get a list of all audio-devices found on a system. This has to be
   done platform dependent */

GList *get_dsp_devices() {
GList *dsp;
GList *loop;
#if !(defined(__MACH__) && defined(__APPLE__)) 
struct stat buf;
#endif

#if defined(sun) || defined(aix) || defined(__OpenBSD__)
gchar *audiodev;
#endif
	dsp = NULL;

#if defined(linux) || defined(__FreeBSD__)
	/* for linux check if /dev/dsp or /dev/dsp1 exist */

	if (stat("/dev/dsp",&buf) == 0) {
		dsp = g_list_append(dsp,"/dev/dsp");
	}
	if (stat("/dev/dsp1",&buf) == 0) {
		dsp = g_list_append(dsp,"/dev/dsp1");
	}
#endif
#if defined(sun) || defined(__OpenBSD__)
	/* check if the user has any special audio-hardware running,
	   which set the AUDIODEV-environment-variable */
	audiodev = getenv("AUDIODEV");
	if (audiodev != NULL) {

		if (stat(audiodev,&buf) == 0) {
			dsp = g_list_append(dsp,g_strdup(audiodev));
		}
	} else {
		audiodev = "";
	}
	if (strcmp(audiodev,"/dev/audio") != 0) {

		if (stat("/dev/audio",&buf) == 0) {
			dsp = g_list_append(dsp,"/dev/audio");
		}
	}
#endif
#ifdef aix
       audiodev = getenv ("AUDIODEV");
       if (audiodev != NULL) {

               if (stat (audiodev, &buf) == 0) {
                       dsp = g_list_append (dsp, g_strdup(audiodev));
               }
       }
       /* Try to use the device of a machine with PCI bus */
        if (stat ("/dev/paud0/1", &buf) == 0) {
               dsp = g_list_append (dsp, "/dev/paud0/1");
       }
        /* Try to use the device of a machine with MCA bus */
        if (stat ("/dev/baud0/1", &buf) == 0) {
               dsp = g_list_append (dsp, "/dev/baud0/1");
       }
#endif
#ifdef hpux
# ifndef hpux_alib

       /* for HP-UX check if /dev/audio exists - I've never seen */
       /* other audio devices under HP-UX                        */

       if (stat("/dev/audio",&buf) == 0) {
               dsp = g_list_append(dsp,"/dev/audio");
       }
# else
       /* for HP-UX with the Alib we dont need to check if the    */
       /* device exists - we actually do not know even the device */
       dsp = g_list_append(dsp,"AUDIO ENVIRONMENT");
# endif
#endif

#if (defined(__MACH__) && defined(__APPLE__))

	/* on macosX we always should have the build-in-audio device */
       dsp = g_list_append(dsp,"Apple CoreAudio");
#endif

#if defined(__sgi)
{
       int     i, rv;
       ALvalue devs [16];
       ALpv    q [1];
       char    devLabel [32];

       /*
        * Fetch the list of available output audio devices.
        */
       q[0].param = AL_TYPE;
       q[0].value.i = AL_OUTPUT_DEVICE_TYPE;
       if ((rv = alQueryValues(AL_SYSTEM, AL_DEVICES, devs, 16, q, 1)) >= 0) {

               for (i = 0; i < rv; i++) {
                       q[0].param = AL_LABEL;
                       q[0].value.ptr = devLabel;
                       q[0].sizeIn = 32;
                       alGetParams(devs[i].i, q, 1);
                       if (alIsSubtype(AL_DEVICE_TYPE, devs[i].i)) {
                               dsp = g_list_append(dsp, g_strdup(devLabel));
                       }
               }
       }
}
#endif

	/* do some debug output */
	if (debug) {
		loop = g_list_first(dsp);
		while(loop) {
			if (loop->data != NULL) 
				dodebug(10, "dspscan: %s\n", 
					(gchar *) loop->data);
			loop = loop->next;
		}
	}

	return g_list_first(dsp);
}


/* take a dsp-device and find the fitting mixer-device */

gchar *gen_mix_from_dspdev(gchar *dsp, gchar *ret) {
#if !(defined(__MACH__) && defined(__APPLE__)) 
gchar tmp[MAXLINE];
# ifndef aix
struct stat buf;
# endif
#endif
#if defined(linux) || defined(__FreeBSD__)
gchar tmp2[MAXLINE];
#endif

	strcpy(ret,"");

#if defined(linux) || defined(__FreeBSD__)

	if (strncmp(dsp,"/dev/dsp",8) == 0) {
		strcpy(tmp,dsp+8);
		g_snprintf(tmp2,MAXLINE,"/dev/mixer%s",tmp);

		/* does device exist? */
		if (stat(tmp2,&buf) == 0) {
			strcpy(ret,tmp2);
		}	
	}	
#endif
#if defined(sun) || defined(__OpenBSD__)

	g_snprintf(tmp,MAXLINE,"%s%s",dsp,"ctl");

		/* does device exist? */
		if (stat(tmp,&buf) == 0) {
			strcpy(ret,tmp);
		}
#endif
#ifdef aix
       /* The gain will be set via ioctl and the usual */
        /* output device                                */
       g_snprintf(tmp,MAXLINE,"%s",dsp);
       strcpy(ret,tmp);
#endif
#ifdef hpux
# ifndef hpux_alib
	g_snprintf(tmp,MAXLINE,"%s%s",dsp,"Ctl");

	/* does device exist? */
	if (stat(tmp,&buf) == 0) {
	        strcpy(ret,tmp);
	}
# else
	/* We have no control or mixer device -> all is */
	/* done via the Aserver-daemon and its API      */
	strcpy(ret, "ASERVER");	
# endif
#endif

	dodebug(10, "mixer: %s\n", ret);
	return ret;
}


/* call uname -a to get a nice system-id-string */

gchar *get_uname_info(gchar *str) {
FILE *fpin;

	if (stat_file(UNAME)) {
		dodebug(1, "calling: %s\n", UNAME);
       		if ((fpin = popen(UNAME,"r")) == NULL) {
                	g_error("popen error\n");
		}
        } else {
		dodebug(1, "calling: %s\n", UNAME2);
       		if ((fpin = popen(UNAME2,"r")) == NULL) {
                	g_error("popen error\n");
		}
	}

	strcpy(str,"");
	fgets(str,MAXLINE,fpin); 

        if (pclose(fpin) == -1) {
                g_error("pclose error\n");
        }

	dodebug(10, "uname: %s\n", str);

	return str;
}


/* Save the setup-configuration to a file - all strings are converted
   in a printable form first:  return 0 if ok, or 1 on error */

gint save_setup_config(gchar *confdir, gchar *fname) {
FILE *fd;
gchar tmp[MAXLINE];
gchar tmp2[MAXLINE];
GList *loop;
gint count;

	/* no confdir? treat path absolute */
	if (strcmp(confdir,"") == 0) {
		strncpy(tmp,fname,MAXLINE);
	} else {

		/* now check if the confdir exists */
		if (!is_directory(confdir)) {
			/* try to create directory */
			mkdir(confdir, 0700);
			dodebug(2, "trying to mkdir %s\n", confdir);
		}

		g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
	}

	dodebug(1, "Opening %s for writing\n", tmp);
	dolog(3, "Saving config file %s\n", tmp);

	fd = fopen(tmp,"w"); 

	if (fd == NULL) { 
		/* error opening file */
		return 1;
	}

	/* write the config-file header */
	fputs("#\n",fd);
	g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Configuration-File\n",XCDROAST_VERSION);
	fputs(tmp,fd);
	fputs("#\n",fd);
	fputs("# Automatically created by the X-CD-Roast-Setup\n",fd);
	fputs("# Don't edit! (Unless you REALLY know what you are doing)\n",fd);
	fputs("#\n\n",fd);

	/* write data */
	g_snprintf(tmp,MAXLINE,"VERSION = \"%s\"\n",XCDROAST_VERSION); 
	fputs(tmp,fd);
	g_snprintf(tmp,MAXLINE,"PLATFORM = \"%s\"\n",system_platform); 
	fputs(tmp,fd);
	g_snprintf(tmp,MAXLINE,"WRITER_DEVNR = %d\n",setupdata.writer_devnr);
	fputs(tmp,fd);
	g_snprintf(tmp,MAXLINE,"READER_DEVNR = %d\n",setupdata.reader_devnr);
	fputs(tmp,fd);

	fputs("#\n",fd);

	/* write hardware structure */
	count = 0;
	while(writerreaderdevs[count] != NULL) {

		g_snprintf(tmp,MAXLINE,"WRITERREADER_DEVNR = %d\n",writerreaderdevs[count]->devnr);
		fputs(tmp,fd);

		strcpy(tmp2,writerreaderdevs[count]->devicestr);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_DEVICESTR = \"%s\"\n",convert_escape(tmp2));
		fputs(tmp,fd);

		strcpy(tmp2,writerreaderdevs[count]->vendor);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_VENDOR = \"%s\"\n",convert_escape(tmp2));
		fputs(tmp,fd);
		strcpy(tmp2,writerreaderdevs[count]->model);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_MODEL = \"%s\"\n",convert_escape(tmp2));
		fputs(tmp,fd);
		strcpy(tmp2,writerreaderdevs[count]->rev);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_REV = \"%s\"\n",convert_escape(tmp2));
		fputs(tmp,fd);
		
		g_snprintf(tmp,MAXLINE,"WRITERREADER_READMAXSPEED = %d\n",writerreaderdevs[count]->writer_readmaxspeed);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_CDRMAXSPEED = %d\n",writerreaderdevs[count]->writer_cdrmaxspeed);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_DVDMAXSPEED = %d\n",writerreaderdevs[count]->writer_dvdmaxspeed);
		fputs(tmp,fd);

		strcpy(tmp2,writerreaderdevs[count]->writer_flags);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_WRITER_FLAGS = \"%s\"\n",convert_escape(tmp2));
		fputs(tmp,fd);
		strcpy(tmp2,writerreaderdevs[count]->writer_modes);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_WRITER_MODES = \"%s\"\n",convert_escape(tmp2));
		fputs(tmp,fd);

		g_snprintf(tmp,MAXLINE,"WRITERREADER_IS_CDRWRITER = %d\n",writerreaderdevs[count]->is_cdrwriter);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_IS_DVDWRITER = %d\n",writerreaderdevs[count]->is_dvdwriter);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_IS_DVDREADER = %d\n",writerreaderdevs[count]->is_dvdreader);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_SECTOR_SIZE = %d\n",writerreaderdevs[count]->sector_size);
		fputs(tmp,fd);

		g_snprintf(tmp,MAXLINE,"WRITERREADER_DRVMODE = %d\n",writerreaderdevs[count]->writer_drvmode);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_MODE = %d\n",writerreaderdevs[count]->writer_mode);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_SPEED = %d\n",writerreaderdevs[count]->writer_speed);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_FIFO = %d\n",writerreaderdevs[count]->writer_fifo);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_INTERFACE = %d\n",writerreaderdevs[count]->audioread_interface);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_SPEED = %d\n",writerreaderdevs[count]->audioread_speed);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_OVERLAP = %d\n",writerreaderdevs[count]->audioread_overlap);
		fputs(tmp,fd);
		g_snprintf(tmp,MAXLINE,"WRITERREADER
Results 1 - 1
Help - FTP Sites List - Software Dir.
Searching half a billion files worldwide
© 1997-2008 IT MARUHN