543 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			543 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  | **	Copyright (C) 2005-2011 Erik de Castro Lopo | ||
|  | ** | ||
|  | **	This program is free software; you can redistribute it and/or modify | ||
|  | **	it under the terms of the GNU General Public License as published by | ||
|  | **	the Free Software Foundation; either version 2 of the License, or | ||
|  | **	(at your option) any later version. | ||
|  | ** | ||
|  | **	This program is distributed in the hope that it will be useful, | ||
|  | **	but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
|  | **	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||
|  | **	GNU General Public License for more details. | ||
|  | ** | ||
|  | **	You should have received a copy of the GNU General Public License | ||
|  | **	along with this program; if not, write to the Free Software | ||
|  | **	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
|  | */ | ||
|  | 
 | ||
|  | #include "config.h"
 | ||
|  | 
 | ||
|  | #include <stdio.h>
 | ||
|  | #include <stdlib.h>
 | ||
|  | #if HAVE_UNISTD_H
 | ||
|  | #include <unistd.h>
 | ||
|  | #else
 | ||
|  | #include "sf_unistd.h"
 | ||
|  | #endif
 | ||
|  | #include <string.h>
 | ||
|  | #include <fcntl.h>
 | ||
|  | #ifdef HAVE_DIRECT_H
 | ||
|  | #include <direct.h>
 | ||
|  | #endif
 | ||
|  | #include <sys/stat.h>
 | ||
|  | 
 | ||
|  | #include <sndfile.h>
 | ||
|  | 
 | ||
|  | #include "regtest.h"
 | ||
|  | 
 | ||
|  | #if HAVE_SQLITE3
 | ||
|  | 
 | ||
|  | #include <ctype.h>
 | ||
|  | #include <sqlite3.h>
 | ||
|  | 
 | ||
|  | typedef struct | ||
|  | {	sqlite3 *sql ; | ||
|  | 
 | ||
|  | 	int count ; | ||
|  | 	int ekey_max ; | ||
|  | 
 | ||
|  | 	/* Filename and pathname for file. */ | ||
|  | 	char filename [256] ; | ||
|  | 	char pathname [512] ; | ||
|  | 
 | ||
|  | 	/* Storage for createding SQL commands. Must be larger than logbuf below. */ | ||
|  | 	char cmdbuf [1 << 15] ; | ||
|  | 
 | ||
|  | 	/* Storage for log buffer retrieved from SNDFILE* .*/ | ||
|  | 	char logbuf [1 << 14] ; | ||
|  | 
 | ||
|  | } REGTEST_DB ; | ||
|  | 
 | ||
|  | /* In checksum.c */ | ||
|  | int calc_checksum (SNDFILE * file, const SF_INFO * info) ; | ||
|  | 
 | ||
|  | static void get_filename_pathname (REGTEST_DB * db, const char *filepath) ; | ||
|  | static void single_quote_replace (char * buf) ; | ||
|  | 
 | ||
|  | static int get_ekey_from_filename (REGTEST_DB * db, const char *filepath) ; | ||
|  | static int get_filename_pathname_by_ekey (REGTEST_DB * db, int ekey) ; | ||
|  | static int check_file_by_ekey (REGTEST_DB * db, int ekey) ; | ||
|  | 
 | ||
|  | static int count_callback (REGTEST_DB * db, int argc, char **argv, char **colname) ; | ||
|  | static int ekey_max_callback (REGTEST_DB * db, int argc, char **argv, char **colname) ; | ||
|  | static int callback (void *unused, int argc, char **argv, char **colname) ; | ||
|  | static const char *db_basename (const char *fname); | ||
|  | 
 | ||
|  | /* Windows accepts both '\\' and '/' in paths */ | ||
|  | #ifdef _WIN32
 | ||
|  |   #define IS_SLASH(c)			((c) == '\\' || (c) == '/')
 | ||
|  |   #define HAS_DRIVELETTER(path)	(isalpha ((int)(path[0])) && path[1] == ':' && IS_SLASH(path[2]))
 | ||
|  | #else
 | ||
|  |   #define IS_SLASH(c)			((c) == '/')
 | ||
|  |   #define HAS_DRIVELETTER(path)	0
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | REG_DB * | ||
|  | db_open (const char * db_name) | ||
|  | {	REGTEST_DB * db ; | ||
|  | 	int err ; | ||
|  | 
 | ||
|  | 	if ((db = malloc (sizeof (REGTEST_DB))) == NULL) | ||
|  | 	{	perror ("malloc") ; | ||
|  | 		exit (1) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	if ((err = sqlite3_open (db_name, &(db->sql))) != 0) | ||
|  | 	{	printf ("Can't open database: %s\n", sqlite3_errmsg (db->sql)) ; | ||
|  |         sqlite3_close (db->sql) ; | ||
|  | 		free (db) ; | ||
|  | 		exit (1) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	return (REG_DB *) db ; | ||
|  | } /* db_open */ | ||
|  | 
 | ||
|  | int | ||
|  | db_create (const char * db_name) | ||
|  | {	REGTEST_DB * db ; | ||
|  | 	const char *cmd ; | ||
|  | 	char * errmsg = NULL ; | ||
|  | 	int err ; | ||
|  | 
 | ||
|  | 	db = (REGTEST_DB *) db_open (db_name) ; | ||
|  | 
 | ||
|  | 	cmd = "create table sndfile (ekey INTEGER PRIMARY KEY," | ||
|  | 			"fname VARCHAR(1)," | ||
|  | 			"fpath VARCHAR(1)," | ||
|  | 			"srate INTEGER," | ||
|  | 			"frames VARCHAR(1)," | ||
|  | 			"channels INTEGER," | ||
|  | 			"format VARCHAR(1)," | ||
|  | 			"checksum VARCHAR(1)," | ||
|  | 			"logbuf VARCHAR(1)" | ||
|  | 			");" ; | ||
|  | 
 | ||
|  | 	err = sqlite3_exec (db->sql, cmd, callback, 0, &errmsg) ; | ||
|  | 	if (err != SQLITE_OK) | ||
|  | 		printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ; | ||
|  | 
 | ||
|  | 	sqlite3_close (db->sql) ; | ||
|  | 	free (db) ; | ||
|  | 
 | ||
|  | 	return 0 ; | ||
|  | } /* db_create */ | ||
|  | 
 | ||
|  | int | ||
|  | db_close (REG_DB * db_handle) | ||
|  | {	REGTEST_DB * db ; | ||
|  | 
 | ||
|  | 	db = (REGTEST_DB *) db_handle ; | ||
|  | 
 | ||
|  | 	sqlite3_close (db->sql) ; | ||
|  | 	free (db) ; | ||
|  | 
 | ||
|  | 	return 0 ; | ||
|  | } /* db_close */ | ||
|  | 
 | ||
|  | /*==============================================================================
 | ||
|  | */ | ||
|  | 
 | ||
|  | int | ||
|  | db_file_exists (REG_DB * db_handle, const char * filename) | ||
|  | {	REGTEST_DB * db ; | ||
|  | 	char * errmsg ; | ||
|  | 	int err ; | ||
|  | 
 | ||
|  | 	db = (REGTEST_DB *) db_handle ; | ||
|  | 
 | ||
|  | 	filename = db_basename (filename); | ||
|  | 
 | ||
|  | 	snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select fname from sndfile where fname='%s'", filename) ; | ||
|  | 
 | ||
|  | 	db->count = 0 ; | ||
|  | 	err = sqlite3_exec (db->sql, db->cmdbuf, (sqlite3_callback) count_callback, db, &errmsg) ; | ||
|  | 	if (err == 0 && db->count == 1) | ||
|  | 		return 1 ; | ||
|  | 
 | ||
|  | 	return 0 ; | ||
|  | } /* db_file_exists */ | ||
|  | 
 | ||
|  | int | ||
|  | db_add_file (REG_DB * db_handle, const char * filepath) | ||
|  | {	REGTEST_DB * db ; | ||
|  | 	SNDFILE * sndfile ; | ||
|  | 	SF_INFO info ; | ||
|  | 	char * errmsg ; | ||
|  | 	int err, checksum ; | ||
|  | 
 | ||
|  | 	db = (REGTEST_DB *) db_handle ; | ||
|  | 
 | ||
|  | 	get_filename_pathname (db, filepath) ; | ||
|  | 
 | ||
|  | 	if (db_file_exists (db_handle, filepath)) | ||
|  | 	{	printf ("    %s : already in database\n", db->filename) ; | ||
|  | 		return 0 ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	memset (&info, 0, sizeof (info)) ; | ||
|  | 	sndfile = sf_open (db->pathname, SFM_READ, &info) ; | ||
|  | 	sf_command (sndfile, SFC_GET_LOG_INFO, db->logbuf, sizeof (db->logbuf)) ; | ||
|  | 	checksum = (sndfile == NULL) ? 0 : calc_checksum (sndfile, &info) ; | ||
|  | 	sf_close (sndfile) ; | ||
|  | 
 | ||
|  | 	if (sndfile == NULL) | ||
|  | 	{	printf ("    %s : could not open : %s, filepath: '%s'\n", db->filename, sf_strerror (NULL), filepath) ; | ||
|  | 		puts (db->logbuf) ; | ||
|  | 		return 1 ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	single_quote_replace (db->logbuf) ; | ||
|  | 
 | ||
|  | 	snprintf (db->cmdbuf, sizeof (db->cmdbuf), "insert into sndfile " | ||
|  | 		"(fname, fpath, srate, frames, channels, format, checksum, logbuf) values" | ||
|  | 		"('%s','%s',%d,'%ld', %d, '0x%08x', '0x%08x', '%s');", | ||
|  | 		db->filename, db->pathname, info.samplerate, (long) info.frames, info.channels, info.format, checksum, db->logbuf) ; | ||
|  | 
 | ||
|  | 	if (strlen (db->cmdbuf) >= sizeof (db->cmdbuf) - 1) | ||
|  | 	{	printf ("strlen (db->cmdbuf) too long.\n") ; | ||
|  | 		exit (1) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	err = sqlite3_exec (db->sql, db->cmdbuf, callback, 0, &errmsg) ; | ||
|  | 	if (err != SQLITE_OK) | ||
|  | 	{	printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ; | ||
|  | 		puts (db->cmdbuf) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	return 0 ; | ||
|  | } /* db_add_file */ | ||
|  | 
 | ||
|  | int | ||
|  | db_check_file (REG_DB * db_handle, const char * filepath) | ||
|  | {	REGTEST_DB * db ; | ||
|  | 	int ekey ; | ||
|  | 
 | ||
|  | 	if (db_file_exists (db_handle, filepath) == 0) | ||
|  | 	{	printf ("\nFile not in database.\n\n") ; | ||
|  | 		exit (0) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	db = (REGTEST_DB *) db_handle ; | ||
|  | 
 | ||
|  | 	ekey = get_ekey_from_filename (db, filepath) ; | ||
|  | 
 | ||
|  | 	return check_file_by_ekey (db, ekey) ; | ||
|  | } /* db_check_file */ | ||
|  | 
 | ||
|  | /*==============================================================================
 | ||
|  | */ | ||
|  | 
 | ||
|  | int | ||
|  | db_check_all (REG_DB * db_handle) | ||
|  | {	REGTEST_DB * db ; | ||
|  | 	char * errmsg ; | ||
|  | 	int err, ekey ; | ||
|  | 
 | ||
|  | 	db = (REGTEST_DB *) db_handle ; | ||
|  | 
 | ||
|  | 	db->ekey_max = 0 ; | ||
|  | 
 | ||
|  | 	snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select ekey from sndfile") ; | ||
|  | 
 | ||
|  | 	err = sqlite3_exec (db->sql, db->cmdbuf, (sqlite3_callback) ekey_max_callback, db, &errmsg) ; | ||
|  | 	if (err != SQLITE_OK) | ||
|  | 	{	printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ; | ||
|  | 		puts (db->cmdbuf) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	for (ekey = 1 ; ekey <= db->ekey_max ; ekey++) | ||
|  | 		if (get_filename_pathname_by_ekey (db, ekey) != 0) | ||
|  | 			check_file_by_ekey (db, ekey) ; | ||
|  | 
 | ||
|  | 	return 0 ; | ||
|  | } /* db_check_all */ | ||
|  | 
 | ||
|  | 
 | ||
|  | int | ||
|  | db_list_all (REG_DB * db_handle) | ||
|  | { | ||
|  | 	printf ("%s : %p\n", __func__, (void *) db_handle) ; | ||
|  | 	return 0 ; | ||
|  | } /* db_list_all */ | ||
|  | 
 | ||
|  | int | ||
|  | db_del_entry (REG_DB * db_handle, const char * entry) | ||
|  | { | ||
|  | 	printf ("%s : %p %s\n", __func__, (void *) db_handle, entry) ; | ||
|  | 	return 0 ; | ||
|  | } /* db_del_entry */ | ||
|  | 
 | ||
|  | /*==============================================================================
 | ||
|  | */ | ||
|  | 
 | ||
|  | static int | ||
|  | get_ekey_from_filename (REGTEST_DB * db, const char *filepath) | ||
|  | {	char * errmsg, **result ; | ||
|  | 	int err, ekey = 0, rows, cols ; | ||
|  | 
 | ||
|  | 	get_filename_pathname (db, filepath) ; | ||
|  | 
 | ||
|  | 	snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select ekey from sndfile where fname='%s'", db->filename) ; | ||
|  | 
 | ||
|  | 	err = sqlite3_get_table (db->sql, db->cmdbuf, &result, &rows, &cols, &errmsg) ; | ||
|  | 	if (err != SQLITE_OK) | ||
|  | 	{	printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ; | ||
|  | 		puts (db->cmdbuf) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	if (cols != 1 || rows != 1) | ||
|  | 	{	printf ("Bad juju!! rows = %d cols = %d\n", rows, cols) ; | ||
|  | 		exit (1) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	ekey = strtol (result [1], NULL, 10) ; | ||
|  | 
 | ||
|  | 	sqlite3_free_table (result) ; | ||
|  | 
 | ||
|  | 	return ekey ; | ||
|  | } /* get_ekey_from_filename */ | ||
|  | 
 | ||
|  | static int | ||
|  | get_filename_pathname_by_ekey (REGTEST_DB * db, int ekey) | ||
|  | {	char *errmsg, **result ; | ||
|  | 	int err, rows, cols ; | ||
|  | 
 | ||
|  | 	snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select fname,fpath from sndfile where ekey='%d'", ekey) ; | ||
|  | 
 | ||
|  | 	err = sqlite3_get_table (db->sql, db->cmdbuf, &result, &rows, &cols, &errmsg) ; | ||
|  | 	if (err != SQLITE_OK) | ||
|  | 	{	printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ; | ||
|  | 		puts (db->cmdbuf) ; | ||
|  | 		return 0 ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	if (cols != 2 || rows != 1) | ||
|  | 	{	printf ("\nError (%s %d) : rows = %d cols = %d\n", __func__, __LINE__, rows, cols) ; | ||
|  | 		exit (1) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	snprintf (db->filename, sizeof (db->filename), "%s", result [2]) ; | ||
|  | 	snprintf (db->pathname, sizeof (db->pathname), "%s", result [3]) ; | ||
|  | 
 | ||
|  | 	sqlite3_free_table (result) ; | ||
|  | 
 | ||
|  | 	return 1 ; | ||
|  | } /* get_filename_pathname_by_ekey */ | ||
|  | 
 | ||
|  | static int | ||
|  | check_file_by_ekey (REGTEST_DB * db, int ekey) | ||
|  | {	SNDFILE * sndfile ; | ||
|  | 	SF_INFO info ; | ||
|  | 	char * errmsg, **result ; | ||
|  | 	int err, k, rows, cols, checksum ; | ||
|  | 
 | ||
|  | 	printf ("    %s : ", db->filename) ; | ||
|  | 	fflush (stdout) ; | ||
|  | 
 | ||
|  | 	memset (&info, 0, sizeof (info)) ; | ||
|  | 	sndfile = sf_open (db->pathname, SFM_READ, &info) ; | ||
|  | 	sf_command (sndfile, SFC_GET_LOG_INFO, db->logbuf, sizeof (db->logbuf)) ; | ||
|  | 	checksum = (sndfile == NULL) ? 0 : calc_checksum (sndfile, &info) ; | ||
|  | 	sf_close (sndfile) ; | ||
|  | 
 | ||
|  | 	if (sndfile == NULL) | ||
|  | 	{	printf ("\n\nError : Could not open '%s' : %s\n", db->pathname, sf_strerror (NULL)) ; | ||
|  | 		puts (db->logbuf) ; | ||
|  | 		exit (1) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	single_quote_replace (db->logbuf) ; | ||
|  | 
 | ||
|  | 	snprintf (db->cmdbuf, sizeof (db->cmdbuf), "select fname,srate,frames,channels,format," | ||
|  | 			"checksum,logbuf from sndfile where ekey='%d'", ekey) ; | ||
|  | 
 | ||
|  | 	err = sqlite3_get_table (db->sql, db->cmdbuf, &result, &rows, &cols, &errmsg) ; | ||
|  | 	if (err != SQLITE_OK) | ||
|  | 	{	printf ("Line %d : SQL error: %s\n", __LINE__, errmsg) ; | ||
|  | 		puts (db->cmdbuf) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	for (k = 0 ; k < cols ; k++) | ||
|  | 	{	if (strcmp (result [k], "fname") == 0) | ||
|  | 		{	if (strcmp (result [k + cols], db->filename) == 0) | ||
|  | 				continue ; | ||
|  | 			printf ("\n\nError : fname doesn't match : %s != %s\n", result [k + cols], db->filename) ; | ||
|  | 			} ; | ||
|  | 
 | ||
|  | 		if (strcmp (result [k], "srate") == 0) | ||
|  | 		{	if (strtol (result [k + cols], NULL, 10) == info.samplerate) | ||
|  | 				continue ; | ||
|  | 			printf ("\n\nError : srate doesn't match : %s == %d\n", result [k + cols], info.samplerate) ; | ||
|  | 			} ; | ||
|  | 
 | ||
|  | 		if (strcmp (result [k], "frames") == 0) | ||
|  | 		{	if (strtoll (result [k + cols], NULL, 10) == info.frames) | ||
|  | 				continue ; | ||
|  | 			printf ("\n\nError : frames doesn't match : %s == %ld\n", result [k + cols], (long) info.frames) ; | ||
|  | 			} ; | ||
|  | 
 | ||
|  | 		if (strcmp (result [k], "channels") == 0) | ||
|  | 		{	if (strtol (result [k + cols], NULL, 10) == info.channels) | ||
|  | 				continue ; | ||
|  | 			printf ("\n\nError : channels doesn't match : %s == %d\n", result [k + cols], info.channels) ; | ||
|  | 			} ; | ||
|  | 
 | ||
|  | 		if (strcmp (result [k], "format") == 0) | ||
|  | 		{	if (strtol (result [k + cols], NULL, 16) == info.format) | ||
|  | 				continue ; | ||
|  | 			printf ("\n\nError : format doesn't match : %s == 0x%08x\n", result [k + cols], info.format) ; | ||
|  | 			} ; | ||
|  | 
 | ||
|  | 		if (strcmp (result [k], "checksum") == 0) | ||
|  | 		{	int db_val = (int) strtoll (result [k + cols], NULL, 16) ; | ||
|  | 
 | ||
|  | 			if (db_val == checksum) | ||
|  | 				continue ; | ||
|  | 			printf ("\n\nError : checksum doesn't match : 0x%08x == 0x%08x\n", db_val, checksum) ; | ||
|  | 			} ; | ||
|  | 
 | ||
|  | 		if (strcmp (result [k], "logbuf") == 0) | ||
|  | 			continue ; | ||
|  | 
 | ||
|  | 		printf ("\nHere is the old logubuffer :\n\n%s\n\nand the new :\n\n%s\n\n", result [2 * cols - 1], db->logbuf) ; | ||
|  | 		exit (1) ; | ||
|  | 		} ; | ||
|  | 
 | ||
|  | 	sqlite3_free_table (result) ; | ||
|  | 
 | ||
|  | 	puts ("ok") ; | ||
|  | 
 | ||
|  | 	return 0 ; | ||
|  | } /* check_file_by_ekey */ | ||
|  | 
 | ||
|  | /*==============================================================================
 | ||
|  | */ | ||
|  | 
 | ||
|  | static void | ||
|  | get_filename_pathname (REGTEST_DB * db, const char *filepath) | ||
|  | { | ||
|  | 	const char * basename = db_basename (filepath) ; | ||
|  | 	size_t slen ; | ||
|  | 
 | ||
|  | 	/* Test for a relative path
 | ||
|  | 	 */ | ||
|  | 	if (!IS_SLASH(filepath [0]) && !HAS_DRIVELETTER(filepath)) | ||
|  | 	{	memset (db->pathname, 0, sizeof (db->pathname)) ; | ||
|  | 		if (getcwd (db->pathname, sizeof (db->pathname)) == NULL) | ||
|  | 		{	perror ("\ngetcwd failed") ; | ||
|  | 			exit (1) ; | ||
|  | 			} ; | ||
|  | 
 | ||
|  | 		slen = strlen (db->pathname) ; | ||
|  | 		/* a '/' is fine for Windows too */ | ||
|  | 		snprintf (db->pathname + slen, sizeof (db->pathname) - slen, "/%s", filepath) ; | ||
|  | 		} | ||
|  | 	else | ||
|  | 		snprintf (db->pathname, sizeof (db->pathname), "%s", filepath) ; | ||
|  | 
 | ||
|  | 	snprintf (db->filename, sizeof (db->filename), "%s", basename) ; | ||
|  | 
 | ||
|  | 	basename = db_basename (db->pathname) ; | ||
|  | 	if (basename == db->pathname) | ||
|  | 	{	printf ("\nError : bad pathname %s\n", filepath) ; | ||
|  | 		exit (1) ; | ||
|  | 		} ; | ||
|  | } /* get filename_pathname */ | ||
|  | 
 | ||
|  | static void | ||
|  | single_quote_replace (char * buf) | ||
|  | {	while ((buf = strchr (buf, '\'')) != 0) | ||
|  | 		buf [0] = '"' ; | ||
|  | } /* single_quote_replace */ | ||
|  | 
 | ||
|  | static int | ||
|  | count_callback (REGTEST_DB * db, int argc, char **argv, char **colname) | ||
|  | {	db->count ++ ; | ||
|  | 
 | ||
|  | 	(void) argc ; | ||
|  | 	(void) argv ; | ||
|  | 	(void) colname ; | ||
|  | 	return 0 ; | ||
|  | } /* count_callback */ | ||
|  | 
 | ||
|  | static int | ||
|  | ekey_max_callback (REGTEST_DB * db, int argc, char **argv, char **unused) | ||
|  | {	int ekey ; | ||
|  | 
 | ||
|  | 	(void) argc ; | ||
|  | 	(void) unused ; | ||
|  | 
 | ||
|  | 	ekey = strtol (argv [0], NULL, 10) ; | ||
|  | 	if (ekey > db->ekey_max) | ||
|  | 		db->ekey_max = ekey ; | ||
|  | 
 | ||
|  | 	return 0 ; | ||
|  | } /* ekey_max_callback */ | ||
|  | 
 | ||
|  | static int | ||
|  | callback (void *unused, int argc, char **argv, char **colname) | ||
|  | {	int k ; | ||
|  | 
 | ||
|  | 	(void) unused ; | ||
|  | 
 | ||
|  | 	for (k = 0 ; k < argc ; k++) | ||
|  | 		printf ("%s = %s\n", colname [k], argv [k] ? argv [k] : "NULL") ; | ||
|  | 
 | ||
|  | 	printf ("\n") ; | ||
|  | 
 | ||
|  | 	return 0 ; | ||
|  | } /* callback */ | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Win32:     Strip drive-letter and directory from a filename. | ||
|  |  * non-Win32: Strip directory from a filename. | ||
|  |  */ | ||
|  | static const char *db_basename (const char *fname) | ||
|  | { | ||
|  |   const char *base = fname; | ||
|  | 
 | ||
|  | #if !defined(_WIN32)
 | ||
|  |   const char *slash = strrchr (base, '/'); | ||
|  | 
 | ||
|  |   if (slash) | ||
|  | 		base = slash + 1 ; | ||
|  | #else
 | ||
|  | 	if (fname[0] && fname[1] == ':')  { | ||
|  | 		fname += 2; | ||
|  | 		base = fname; | ||
|  | 	} | ||
|  | 	while (*fname) { | ||
|  | 		if (IS_SLASH(*fname)) | ||
|  | 			base = fname + 1; | ||
|  | 		fname++; | ||
|  | 	} | ||
|  | #endif
 | ||
|  | 	return base ; | ||
|  | } | ||
|  | 
 | ||
|  | #else
 | ||
|  | 
 | ||
|  | int dummy (void) ; | ||
|  | 
 | ||
|  | int | ||
|  | dummy (void) | ||
|  | {	/*
 | ||
|  | 	**	Empty dummy fnction so tha compiler doesn't winge about an | ||
|  | 	**	empty file. | ||
|  | 	*/ | ||
|  | 	return 0 ; | ||
|  | } /* dummy */ | ||
|  | 
 | ||
|  | #endif
 |