mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-04-05 20:31:00 +08:00
commit
63e8cb54ac
@ -17,7 +17,7 @@ before_script:
|
||||
- autoreconf -i -f -Wno-portability
|
||||
|
||||
script:
|
||||
- ./configure --disable-man --disable-silent-rules
|
||||
- ./configure --disable-man --disable-silent-rules --disable-glib
|
||||
- make
|
||||
- ./src/util/mdb-array test/data/ASampleDatabase.accdb "Asset Items"
|
||||
- ./src/util/mdb-array test/data/nwind.mdb "Customers"
|
||||
|
90
README.md
90
README.md
@ -51,69 +51,24 @@ Builds on libmdb to provide a SQL engine (aka Jet)
|
||||
|
||||
Provids command line utilities, including:
|
||||
|
||||
### mdb-ver
|
||||
|
||||
Prints the version (JET 3 or 4) of an mdb file.
|
||||
|
||||
### mdb-schema
|
||||
|
||||
Prints DDL for the specified table.
|
||||
|
||||
### mdb-export
|
||||
|
||||
Export table to CSV format.
|
||||
|
||||
### mdb-tables
|
||||
|
||||
A simple dump of table names to be used with shell scripts.
|
||||
|
||||
### mdb-count
|
||||
|
||||
A simple count of number of rows in a table, to be used in shell scripts and ETL pipelines.
|
||||
|
||||
### mdb-header
|
||||
|
||||
Generates a C header to be used in exporting mdb data to a C prog.
|
||||
|
||||
### mdb-parsecsv
|
||||
|
||||
Generates a C program given a CSV file made with mdb-export.
|
||||
|
||||
### mdb-sql
|
||||
|
||||
A simple SQL engine (also used by ODBC and gmdb).
|
||||
|
||||
### prcat
|
||||
|
||||
Prints the catalog table from an mdb file.
|
||||
|
||||
### prkkd
|
||||
|
||||
Dump of information about design view data given the offset to it.
|
||||
|
||||
### prtable
|
||||
|
||||
Dump of a table definition.
|
||||
|
||||
### prdata
|
||||
|
||||
Dump of the data given a table name.
|
||||
|
||||
### prole
|
||||
|
||||
Dump of ole columns given a table name and sargs.
|
||||
|
||||
## odbc
|
||||
|
||||
An ODBC driver for use with unixODBC or iODBC driver manager. Allows one to use MDB files with PHP for example.
|
||||
|
||||
## gmdb2
|
||||
|
||||
The Gnome MDB File Viewer and debugger. Still alpha, but making great progress.
|
||||
|
||||
## src/extras/mdb-hexdump
|
||||
|
||||
Simple hex dump utility that I've been using to look at mdb files.
|
||||
| Command | Description |
|
||||
| ------- | ----------- |
|
||||
| mdb-ver | Prints the version (JET 3 or 4) of an mdb file. |
|
||||
| mdb-schema | Prints DDL for the specified table. |
|
||||
| mdb-export | Export table to CSV format. |
|
||||
| mdb-tables | A simple dump of table names to be used with shell scripts. |
|
||||
| mdb-count | A simple count of number of rows in a table, to be used in shell scripts and ETL pipelines. |
|
||||
| mdb-header | Generates a C header to be used in exporting mdb data to a C prog. |
|
||||
| mdb-parsecsv | Generates a C program given a CSV file made with mdb-export. |
|
||||
| mdb-sql | A simple SQL engine (also used by ODBC and gmdb). |
|
||||
| prcat | Prints the catalog table from an mdb file. |
|
||||
| prkkd | Dump of information about design view data given the offset to it. |
|
||||
| prtable | Dump of a table definition. |
|
||||
| prdata | Dump of the data given a table name. |
|
||||
| prole | Dump of ole columns given a table name and sargs. |
|
||||
| odbc | An ODBC driver for use with unixODBC or iODBC driver manager. Allows one to use MDB files with PHP for example. |
|
||||
| gmdb2 | The Gnome MDB File Viewer and debugger. Still alpha. |
|
||||
| mdb-hexdump | (in src/extras) Simple hex dump utility that I've been using to look at mdb files. |
|
||||
|
||||
# License
|
||||
|
||||
@ -150,7 +105,7 @@ If you want to generate the html version of the docbook, you'll need
|
||||
Last version is available at https://github.com/evanmiller/mdbtools
|
||||
|
||||
```bash
|
||||
$ autoreconf -i -f
|
||||
$ autoreconf -i -f -Wno-portability
|
||||
```
|
||||
|
||||
If you want to build the html version of the docbook documentation, you need to
|
||||
@ -169,6 +124,13 @@ OR for a complete install (requires bison, flex, and unixODBC):
|
||||
$ ./configure --with-unixodbc=/usr/local
|
||||
```
|
||||
|
||||
By default, MDB Tools is linked against the copy of
|
||||
[GLib](https://developer.gnome.org/glib/) returned by pkg-config. You can
|
||||
point to a different GLib installation using the `GLIB_CFLAGS` and `GLIB_LIBS`
|
||||
enivornment variables. Or, you can disable GLib entirely with the
|
||||
`--disable-glib` flag, in which case MDB Tools will use an internal
|
||||
implementation of GLib's functions.
|
||||
|
||||
configure can be passed any of the following flags to turn on other
|
||||
capabilities. Note that the options `--with-unixodbc` and `--with-iodbc` are
|
||||
mutually exclusive.
|
||||
|
@ -22,14 +22,12 @@ build_script:
|
||||
if ($env:TOOLCHAIN -eq "msys2")
|
||||
{
|
||||
$env:MSYSTEM="MINGW64"
|
||||
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-glib2"
|
||||
C:\msys64\usr\bin\bash -l -c "cd /c/projects/mdbtools && autoreconf -i -f -Wno-portability"
|
||||
C:\msys64\usr\bin\bash -l -c "cd /c/projects/mdbtools && ./configure --disable-man --disable-silent-rules"
|
||||
C:\msys64\usr\bin\bash -l -c "cd /c/projects/mdbtools && make"
|
||||
}
|
||||
else
|
||||
{
|
||||
C:\cygwin64\setup-x86_64.exe -qP libglib2.0-devel
|
||||
C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && autoreconf -i -f -Wno-portability"
|
||||
C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && ./configure --disable-man --disable-silent-rules"
|
||||
C:\cygwin64\bin\sh -lc "cd /cygdrive/c/projects/mdbtools && make"
|
||||
|
35
configure.ac
35
configure.ac
@ -21,6 +21,9 @@ AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(fcntl.h limits.h unistd.h)
|
||||
AC_CHECK_HEADERS(wordexp.h)
|
||||
AC_CHECK_LIB(mswstr, DBLCMapStringW)
|
||||
AC_CHECK_DECLS([program_invocation_short_name], [], [], [[
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>]])
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
@ -46,7 +49,11 @@ AC_MSG_RESULT( no - SQL engine disable);
|
||||
sql=false
|
||||
fi
|
||||
|
||||
if ! $YACC -V >/dev/null 2>&1; then
|
||||
if $YACC -V >/dev/null 2>&1; then
|
||||
if $YACC -Wno-conflicts-sr -V >/dev/null 2>&1; then
|
||||
YFLAGS="$YFLAGS -Wno-conflicts-sr"
|
||||
fi
|
||||
else
|
||||
sql=false
|
||||
fi
|
||||
|
||||
@ -61,9 +68,11 @@ AM_CONDITIONAL(SQL, test x$sql = xtrue)
|
||||
AC_SUBST(SQL)
|
||||
AC_SUBST(LFLAGS)
|
||||
|
||||
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes"
|
||||
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes -Werror"
|
||||
AS_CASE([$host],
|
||||
[*mingw*|*cygwin*], [LDFLAGS="$LDFLAGS -no-undefined"], [])
|
||||
AS_CASE([$host],
|
||||
[*mingw*], [LDFLAGS="$LDFLAGS -lWs2_32"], [])
|
||||
dnl Enable -Wl,--as-needed by default to prevent overlinking
|
||||
|
||||
AC_ARG_ENABLE([as-needed],
|
||||
@ -146,14 +155,22 @@ pkg-config is required.
|
||||
See pkg-config.freedesktop.org])
|
||||
fi
|
||||
|
||||
dnl See if GLib is present and wanted
|
||||
AC_ARG_ENABLE(glib,
|
||||
AS_HELP_STRING([--disable-glib], [do not link with GLib]),
|
||||
[enable_glib=$enableval], [enable_glib=yes])
|
||||
|
||||
dnl check for glib/gtk/gnome
|
||||
PKG_CHECK_MODULES([GLIB], [glib-2.0], ,
|
||||
AC_MSG_ERROR([
|
||||
glib 2.0 is required by MDB Tools (runtime and devel).
|
||||
It can be downloaded at www.gtk.org.
|
||||
]))
|
||||
if test "$enable_glib" = "yes"; then
|
||||
PKG_CHECK_MODULES([GLIB], [glib-2.0], HAVE_GLIB=true, HAVE_GLIB=false)
|
||||
if test "x$HAVE_GLIB" = "xtrue"; then
|
||||
GLIB_CFLAGS="$GLIB_CFLAGS -DHAVE_GLIB=1"
|
||||
else
|
||||
enable_glib=no
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL(FAKE_GLIB, test "x$enable_glib" != "xyes")
|
||||
|
||||
dnl check for gtk/gnome
|
||||
PKG_CHECK_MODULES([GNOME], [gtk+-2.0 >= 2.14 libglade-2.0 libgnomeui-2.0], HAVE_GNOME=true, HAVE_GNOME=false)
|
||||
|
||||
GNOME_DOC_INIT
|
||||
@ -277,6 +294,8 @@ if test x$sql = xtrue; then summary=${bold_green}enabled; else summary=${bold_re
|
||||
AC_MSG_NOTICE([ SQL : ${summary}${reset}])
|
||||
if test x$HAVE_ODBC = xtrue; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
|
||||
AC_MSG_NOTICE([ ODBC : ${summary}${reset}])
|
||||
if test x$enable_glib = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
|
||||
AC_MSG_NOTICE([ GLib : ${summary}${reset}])
|
||||
if test x$build_gmdb2 = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
|
||||
AC_MSG_NOTICE([ UI : ${summary}${reset}])
|
||||
if test x$enable_gtk_doc = xyes; then summary=${bold_green}enabled; else summary=${bold_red}disabled; fi
|
||||
|
@ -1,2 +1,5 @@
|
||||
include_HEADERS = mdbtools.h mdbsql.h mdbver.h
|
||||
if FAKE_GLIB
|
||||
include_HEADERS += mdbfakeglib.h
|
||||
endif
|
||||
noinst_HEADERS = mdbprivate.h
|
||||
|
157
include/mdbfakeglib.h
Normal file
157
include/mdbfakeglib.h
Normal file
@ -0,0 +1,157 @@
|
||||
#ifndef _mdbfakeglib_h_
|
||||
#define _mdbfakeglib_h_
|
||||
|
||||
#include <time.h>
|
||||
#include <locale.h>
|
||||
#include <inttypes.h>
|
||||
#include <strings.h>
|
||||
|
||||
// for ntohl
|
||||
#ifdef _WIN32
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
typedef uint16_t guint16;
|
||||
typedef uint32_t guint32;
|
||||
typedef uint64_t guint64;
|
||||
typedef int32_t gint32;
|
||||
typedef char gchar;
|
||||
typedef int gboolean;
|
||||
typedef int gint;
|
||||
typedef unsigned int guint;
|
||||
typedef void * gpointer;
|
||||
typedef const void * gconstpointer;
|
||||
typedef uint8_t guint8;
|
||||
typedef guint32 GQuark;
|
||||
|
||||
typedef guint (*GHashFunc)(gconstpointer);
|
||||
typedef int (*GCompareFunc)(gconstpointer, gconstpointer);
|
||||
typedef gboolean (*GEqualFunc)(gconstpointer, gconstpointer);
|
||||
typedef void (*GFunc) (gpointer data, gpointer user_data);
|
||||
typedef void (*GHFunc)(gpointer key, gpointer value, gpointer data);
|
||||
typedef gboolean (*GHRFunc)(gpointer key, gpointer value, gpointer data);
|
||||
|
||||
typedef struct GPtrArray {
|
||||
void **pdata;
|
||||
int len;
|
||||
} GPtrArray;
|
||||
|
||||
typedef struct GList {
|
||||
gpointer data;
|
||||
struct GList *next;
|
||||
struct GList *prev;
|
||||
} GList;
|
||||
|
||||
typedef struct GHashTable {
|
||||
GEqualFunc compare;
|
||||
GPtrArray *array;
|
||||
} GHashTable;
|
||||
|
||||
typedef struct GError {
|
||||
GQuark domain;
|
||||
gint code;
|
||||
gchar *message;
|
||||
} GError;
|
||||
|
||||
typedef enum GOptionArg {
|
||||
G_OPTION_ARG_NONE,
|
||||
G_OPTION_ARG_STRING,
|
||||
G_OPTION_ARG_INT
|
||||
} GOptionArg;
|
||||
|
||||
typedef enum GOptionFlags {
|
||||
G_OPTION_FLAG_NONE,
|
||||
G_OPTION_FLAG_REVERSE
|
||||
} GOptionFlags;
|
||||
|
||||
typedef struct GOptionEntry {
|
||||
const gchar *long_name;
|
||||
gchar short_name;
|
||||
gint flags;
|
||||
|
||||
GOptionArg arg;
|
||||
gpointer arg_data;
|
||||
|
||||
const gchar *description;
|
||||
const gchar *arg_description;
|
||||
} GOptionEntry;
|
||||
|
||||
typedef struct GOptionContext {
|
||||
const char *desc;
|
||||
const GOptionEntry *entries;
|
||||
} GOptionContext;
|
||||
|
||||
#define g_str_hash NULL
|
||||
|
||||
#define G_GUINT32_FORMAT PRIu32
|
||||
|
||||
#define g_return_val_if_fail(a, b) if (!a) { return b; }
|
||||
|
||||
#define g_ascii_strcasecmp strcasecmp
|
||||
#define g_malloc0(len) calloc(1, len)
|
||||
#define g_malloc malloc
|
||||
#define g_free free
|
||||
#define g_realloc realloc
|
||||
|
||||
#define G_STR_DELIMITERS "_-|> <."
|
||||
|
||||
#define g_ptr_array_index(array, i) \
|
||||
((void **)array->pdata)[i]
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define GUINT16_FROM_LE(l) (uint16_t)l
|
||||
#define GUINT32_FROM_LE(l) (uint32_t)l
|
||||
#define GUINT64_FROM_LE(l) (uint64_t)l
|
||||
#define GINT32_FROM_LE(l) (uint32_t)l
|
||||
#define GINT32_FROM_BE(l) (int32_t)ntohl(l)
|
||||
#define GUINT32_SWAP_LE_BE(l) (uint32_t)ntohl(l)
|
||||
#define GINT32_TO_LE(l) (int32_t)l
|
||||
#define GINT32_TO_BE(l) (int32_t)ntohl(l)
|
||||
|
||||
/* string functions */
|
||||
void *g_memdup(const void *src, size_t len);
|
||||
int g_str_equal(const void *str1, const void *str2);
|
||||
char **g_strsplit(const char *haystack, const char *needle, int something);
|
||||
void g_strfreev(char **dir);
|
||||
char *g_strconcat(const char *first, ...);
|
||||
char *g_strdup(const char *src);
|
||||
char *g_strdup_printf(const char *format, ...);
|
||||
gchar *g_strdelimit(gchar *string, const gchar *delimiters, gchar new_delimiter);
|
||||
|
||||
/* GHashTable */
|
||||
void *g_hash_table_lookup(GHashTable *tree, const void *key);
|
||||
void g_hash_table_insert(GHashTable *tree, void *key, void *value);
|
||||
GHashTable *g_hash_table_new(GHashFunc hashes, GEqualFunc equals);
|
||||
void g_hash_table_foreach(GHashTable *tree, GHFunc function, void *data);
|
||||
void g_hash_table_foreach_remove(GHashTable *tree, GHRFunc function, void *data);
|
||||
void g_hash_table_destroy(GHashTable *tree);
|
||||
|
||||
/* GPtrArray */
|
||||
void g_ptr_array_sort(GPtrArray *array, GCompareFunc func);
|
||||
void g_ptr_array_foreach(GPtrArray *array, GFunc function, gpointer user_data);
|
||||
GPtrArray *g_ptr_array_new(void);
|
||||
void g_ptr_array_add(GPtrArray *array, void *entry);
|
||||
void g_ptr_array_free(GPtrArray *array, gboolean something);
|
||||
|
||||
/* GList */
|
||||
GList *g_list_append(GList *list, void *data);
|
||||
GList *g_list_last(GList *list);
|
||||
GList *g_list_remove(GList *list, void *data);
|
||||
void g_list_free(GList *list);
|
||||
|
||||
/* GOption */
|
||||
GOptionContext *g_option_context_new(const char *description);
|
||||
void g_option_context_add_main_entries (GOptionContext *context,
|
||||
const GOptionEntry *entries,
|
||||
const gchar *translation_domain);
|
||||
gchar *g_option_context_get_help (GOptionContext *context,
|
||||
gboolean main_help, void *group);
|
||||
gboolean g_option_context_parse (GOptionContext *context,
|
||||
gint *argc, gchar ***argv, GError **error);
|
||||
void g_option_context_free (GOptionContext *context);
|
||||
|
||||
#endif
|
@ -25,7 +25,11 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_GLIB
|
||||
#include <glib.h>
|
||||
#else
|
||||
#include <mdbfakeglib.h>
|
||||
#endif
|
||||
#include <mdbtools.h>
|
||||
|
||||
typedef struct {
|
||||
|
@ -30,7 +30,12 @@
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_GLIB
|
||||
#include <glib.h>
|
||||
#else
|
||||
#include <mdbfakeglib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
#include <iconv.h>
|
||||
@ -284,8 +289,7 @@ typedef struct {
|
||||
int object_type;
|
||||
unsigned long table_pg; /* misnomer since object may not be a table */
|
||||
//int num_props; please use props->len
|
||||
GArray *props; /* GArray of MdbProperties */
|
||||
GArray *columns;
|
||||
GPtrArray *props; /* GPtrArray of MdbProperties */
|
||||
int flags;
|
||||
} MdbCatalogEntry;
|
||||
|
||||
@ -575,7 +579,7 @@ extern gint32 mdb_map_find_next(MdbHandle *mdb, unsigned char *map, unsigned int
|
||||
/* props.c */
|
||||
extern void mdb_free_props(MdbProperties *props);
|
||||
extern void mdb_dump_props(MdbProperties *props, FILE *outfile, int show_name);
|
||||
extern GArray* mdb_kkd_to_props(MdbHandle *mdb, void *kkd, size_t len);
|
||||
extern GPtrArray* mdb_kkd_to_props(MdbHandle *mdb, void *kkd, size_t len);
|
||||
|
||||
|
||||
/* worktable.c */
|
||||
|
@ -1,5 +1,8 @@
|
||||
lib_LTLIBRARIES = libmdb.la
|
||||
libmdb_la_SOURCES= catalog.c mem.c file.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c map.c props.c worktable.c options.c iconv.c
|
||||
if FAKE_GLIB
|
||||
libmdb_la_SOURCES += fakeglib.c
|
||||
endif
|
||||
libmdb_la_LDFLAGS = -version-info 2:1:0 -export-symbols-regex '^(mdb_|_mdb_put_int16$$|_mdb_put_int32$$)'
|
||||
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS)
|
||||
LIBS = $(GLIB_LIBS) @LIBS@ @LIBICONV@
|
||||
|
@ -184,7 +184,7 @@ enum {
|
||||
MDB_BACKEND_SQLITE,
|
||||
};
|
||||
|
||||
static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data);
|
||||
static void mdb_drop_backend(gpointer key, gpointer value, gpointer data);
|
||||
|
||||
static gchar*
|
||||
quote_generic(const gchar *value, gchar quote_char, gchar escape_char) {
|
||||
@ -451,14 +451,13 @@ mdb_remove_backends())
|
||||
void
|
||||
_mdb_remove_backends()
|
||||
{
|
||||
g_hash_table_foreach_remove(mdb_backends, mdb_drop_backend, NULL);
|
||||
g_hash_table_foreach(mdb_backends, mdb_drop_backend, NULL);
|
||||
g_hash_table_destroy(mdb_backends);
|
||||
}
|
||||
static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data)
|
||||
static void mdb_drop_backend(gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
MdbBackend *backend = (MdbBackend *)value;
|
||||
g_free (backend);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,8 +57,8 @@ void mdb_free_catalog(MdbHandle *mdb)
|
||||
if (entry) {
|
||||
if (entry->props) {
|
||||
for (j=0; j<entry->props->len; j++)
|
||||
mdb_free_props(g_array_index(entry->props, MdbProperties*, j));
|
||||
g_array_free(entry->props, TRUE);
|
||||
mdb_free_props(g_ptr_array_index(entry->props, j));
|
||||
g_ptr_array_free(entry->props, TRUE);
|
||||
}
|
||||
g_free(entry);
|
||||
}
|
||||
|
@ -140,9 +140,9 @@ int mdb_find_row(MdbHandle *mdb, int row, int *start, size_t *len)
|
||||
mdb_get_int16(mdb->pg_buf, rco + row*2) & OFFSET_MASK;
|
||||
*len = next_start - (*start & OFFSET_MASK);
|
||||
|
||||
if ((*start & OFFSET_MASK) >= mdb->fmt->pg_size ||
|
||||
next_start > mdb->fmt->pg_size)
|
||||
return -1;
|
||||
if ((*start & OFFSET_MASK) >= mdb->fmt->pg_size ||
|
||||
next_start > mdb->fmt->pg_size)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -304,8 +304,8 @@ int mdb_read_row(MdbTableDef *table, unsigned int row)
|
||||
|
||||
num_fields = mdb_crack_row(table, row_start, row_start + row_size - 1,
|
||||
fields);
|
||||
if (num_fields < 0)
|
||||
return 0;
|
||||
if (num_fields < 0)
|
||||
return 0;
|
||||
if (!mdb_test_sargs(table, fields, num_fields)) return 0;
|
||||
|
||||
#if MDB_DEBUG
|
||||
|
416
src/libmdb/fakeglib.c
Normal file
416
src/libmdb/fakeglib.c
Normal file
@ -0,0 +1,416 @@
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "mdbfakeglib.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* string functions */
|
||||
|
||||
void *g_memdup(const void *src, size_t len) {
|
||||
void *dst = malloc(len);
|
||||
memcpy(dst, src, len);
|
||||
return dst;
|
||||
}
|
||||
|
||||
int g_str_equal(const void *str1, const void *str2) {
|
||||
return strcmp(str1, str2) == 0;
|
||||
}
|
||||
|
||||
char **g_strsplit(const char *haystack, const char *needle, int something) {
|
||||
char **ret = NULL;
|
||||
char *found = NULL;
|
||||
size_t components = 1;
|
||||
|
||||
while ((found = strstr(haystack, needle))) {
|
||||
components++;
|
||||
haystack = found + strlen(needle);
|
||||
}
|
||||
|
||||
ret = malloc(components * sizeof(char *));
|
||||
|
||||
int i = 0;
|
||||
while ((found = strstr(haystack, needle))) {
|
||||
// Windows lacks strndup
|
||||
size_t chunk_len = found - haystack;
|
||||
char *chunk = malloc(chunk_len + 1);
|
||||
memcpy(chunk, haystack, chunk_len);
|
||||
chunk[chunk_len] = 0;
|
||||
|
||||
ret[i++] = chunk;
|
||||
haystack = found + strlen(needle);
|
||||
}
|
||||
ret[i] = strdup(haystack);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void g_strfreev(char **dir) {
|
||||
int i=0;
|
||||
while (dir[i]) {
|
||||
free(dir[i]);
|
||||
i++;
|
||||
}
|
||||
free(dir);
|
||||
}
|
||||
|
||||
char *g_strconcat(const char *first, ...) {
|
||||
char *ret = NULL;
|
||||
size_t len = strlen(first);
|
||||
char *arg = NULL;
|
||||
va_list argp;
|
||||
|
||||
va_start(argp, first);
|
||||
while ((arg = va_arg(argp, char *))) {
|
||||
len += strlen(arg);
|
||||
}
|
||||
va_end(argp);
|
||||
|
||||
ret = malloc(len+1);
|
||||
|
||||
char *pos = strcpy(ret, first) + strlen(first);
|
||||
|
||||
va_start(argp, first);
|
||||
while ((arg = va_arg(argp, char *))) {
|
||||
pos = strcpy(pos, arg) + strlen(arg);
|
||||
}
|
||||
va_end(argp);
|
||||
|
||||
ret[len] = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined _WIN32
|
||||
int vasprintf(char **ret, const char *format, va_list ap) {
|
||||
int len;
|
||||
int retval;
|
||||
char *result;
|
||||
if ((len = _vscprintf(format, ap)) < 0)
|
||||
return -1;
|
||||
if ((result = malloc(len+1)) == NULL)
|
||||
return -1;
|
||||
if ((retval = vsprintf_s(result, len+1, format, ap)) == -1) {
|
||||
free(result);
|
||||
return -1;
|
||||
}
|
||||
*ret = result;
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
char *g_strdup(const char *input) {
|
||||
size_t len = strlen(input);
|
||||
return g_memdup(input, len+1);
|
||||
}
|
||||
|
||||
char *g_strdup_printf(const char *format, ...) {
|
||||
char *ret = NULL;
|
||||
va_list argp;
|
||||
|
||||
va_start(argp, format);
|
||||
#ifdef __CYGWIN__
|
||||
size_t len = 0;
|
||||
ret = vasnprintf(ret, &len, format, argp);
|
||||
#else
|
||||
int gcc_is_dumb = vasprintf(&ret, format, argp);
|
||||
(void)gcc_is_dumb;
|
||||
#endif
|
||||
va_end(argp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gchar *g_strdelimit(gchar *string, const gchar *delimiters, gchar new_delimiter) {
|
||||
char *orig = string;
|
||||
if (delimiters == NULL)
|
||||
delimiters = G_STR_DELIMITERS;
|
||||
size_t n = strlen(delimiters);
|
||||
while (*string) {
|
||||
size_t i;
|
||||
for (i=0; i<n; i++) {
|
||||
if (*string == delimiters[i]) {
|
||||
*string = new_delimiter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
string++;
|
||||
}
|
||||
|
||||
return orig;
|
||||
}
|
||||
|
||||
/* GHashTable */
|
||||
|
||||
typedef struct MyNode {
|
||||
char *key;
|
||||
void *value;
|
||||
} MyNode;
|
||||
|
||||
void *g_hash_table_lookup(GHashTable *table, const void *key) {
|
||||
int i;
|
||||
for (i=0; i<table->array->len; i++) {
|
||||
MyNode *node = g_ptr_array_index(table->array, i);
|
||||
if (table->compare(key, node->key))
|
||||
return node->value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void g_hash_table_insert(GHashTable *table, void *key, void *value) {
|
||||
MyNode *node = calloc(1, sizeof(MyNode));
|
||||
node->value = value;
|
||||
node->key = key;
|
||||
g_ptr_array_add(table->array, node);
|
||||
}
|
||||
|
||||
GHashTable *g_hash_table_new(GHashFunc hashes, GEqualFunc equals) {
|
||||
GHashTable *table = calloc(1, sizeof(GHashTable));
|
||||
table->array = g_ptr_array_new();
|
||||
table->compare = equals;
|
||||
return table;
|
||||
}
|
||||
|
||||
void g_hash_table_foreach(GHashTable *table, GHFunc function, void *data) {
|
||||
int i;
|
||||
for (i=0; i<table->array->len; i++) {
|
||||
MyNode *node = g_ptr_array_index(table->array, i);
|
||||
function(node->key, node->value, data);
|
||||
}
|
||||
}
|
||||
|
||||
void g_hash_table_destroy(GHashTable *table) {
|
||||
int i;
|
||||
for (i=0; i<table->array->len; i++) {
|
||||
MyNode *node = g_ptr_array_index(table->array, i);
|
||||
free(node);
|
||||
}
|
||||
g_ptr_array_free(table->array, TRUE);
|
||||
free(table);
|
||||
}
|
||||
|
||||
/* GPtrArray */
|
||||
|
||||
void g_ptr_array_sort(GPtrArray *array, GCompareFunc func) {
|
||||
qsort(array->pdata, array->len, sizeof(void *), func);
|
||||
}
|
||||
|
||||
void g_ptr_array_foreach(GPtrArray *array, GFunc function, gpointer user_data) {
|
||||
int i;
|
||||
for (i=0; i<array->len; i++) {
|
||||
function(g_ptr_array_index(array, i), user_data);
|
||||
}
|
||||
}
|
||||
|
||||
GPtrArray *g_ptr_array_new() {
|
||||
GPtrArray *array = malloc(sizeof(GPtrArray));
|
||||
array->len = 0;
|
||||
array->pdata = NULL;
|
||||
return array;
|
||||
}
|
||||
|
||||
void g_ptr_array_add(GPtrArray *array, void *entry) {
|
||||
array->pdata = realloc(array->pdata, (array->len+1) * sizeof(void *));
|
||||
array->pdata[array->len++] = entry;
|
||||
}
|
||||
|
||||
void g_ptr_array_free(GPtrArray *array, gboolean something) {
|
||||
free(array->pdata);
|
||||
free(array);
|
||||
}
|
||||
|
||||
/* GList */
|
||||
|
||||
GList *g_list_append(GList *list, void *data) {
|
||||
GList *new_list = calloc(1, sizeof(GList));
|
||||
new_list->data = data;
|
||||
new_list->next = list;
|
||||
if (list)
|
||||
list->prev = new_list;
|
||||
return new_list;
|
||||
}
|
||||
|
||||
GList *g_list_last(GList *list) {
|
||||
while (list && list->next) {
|
||||
list = list->next;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
GList *g_list_remove(GList *list, void *data) {
|
||||
GList *link = list;
|
||||
while (link) {
|
||||
if (link->data == data) {
|
||||
GList *return_list = list;
|
||||
if (link->prev)
|
||||
link->prev->next = link->next;
|
||||
if (link->next)
|
||||
link->next->prev = link->prev;
|
||||
if (link == list)
|
||||
return_list = link->next;
|
||||
free(link);
|
||||
return return_list;
|
||||
}
|
||||
link = link->next;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void g_list_free(GList *list) {
|
||||
GList *next = NULL;
|
||||
while (list) {
|
||||
next = list->next;
|
||||
free(list);
|
||||
list = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* GOption */
|
||||
|
||||
void g_option_context_add_main_entries (GOptionContext *context,
|
||||
const GOptionEntry *entries,
|
||||
const gchar *translation_domain) {
|
||||
context->entries = entries;
|
||||
}
|
||||
|
||||
gchar *g_option_context_get_help (GOptionContext *context,
|
||||
gboolean main_help, void *group) {
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
const char * appname = getprogname();
|
||||
#elif HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
const char * appname = program_invocation_short_name;
|
||||
#else
|
||||
const char * appname = "mdb-util";
|
||||
#endif
|
||||
|
||||
char *help = malloc(4096);
|
||||
char *end = help + 4096;
|
||||
char *p = help;
|
||||
p += snprintf(p, end - p,
|
||||
"Usage:\n %s [OPTION\xE2\x80\xA6] %s\n\n", appname, context->desc);
|
||||
p += snprintf(p, end - p,
|
||||
"Help Options:\n -h, --%-20s%s\n\n", "help", "Show help options");
|
||||
p += snprintf(p, end - p,
|
||||
"Application Options:\n");
|
||||
int i=0;
|
||||
for (i=0; context->entries[i].long_name; i++) {
|
||||
p += snprintf(p, end - p, " ");
|
||||
if (context->entries[i].short_name) {
|
||||
p += snprintf(p, end - p, "-%c, ", context->entries[i].short_name);
|
||||
}
|
||||
p += snprintf(p, end - p, "--");
|
||||
if (context->entries[i].arg_description) {
|
||||
char *long_name = g_strconcat(
|
||||
context->entries[i].long_name, "=",
|
||||
context->entries[i].arg_description, NULL);
|
||||
p += snprintf(p, end - p, "%-20s", long_name);
|
||||
free(long_name);
|
||||
} else {
|
||||
p += snprintf(p, end - p, "%-20s", context->entries[i].long_name);
|
||||
}
|
||||
if (!context->entries[i].short_name) {
|
||||
p += snprintf(p, end - p, " ");
|
||||
}
|
||||
p += snprintf(p, end - p, "%s\n", context->entries[i].description);
|
||||
}
|
||||
p += snprintf(p, end - p, "\n");
|
||||
return help;
|
||||
}
|
||||
|
||||
GOptionContext *g_option_context_new(const char *description) {
|
||||
GOptionContext *ctx = calloc(1, sizeof(GOptionContext));
|
||||
ctx->desc = description;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
gboolean g_option_context_parse(GOptionContext *context,
|
||||
gint *argc, gchar ***argv, GError **error) {
|
||||
int i;
|
||||
int count = 0;
|
||||
int len = 0;
|
||||
if (*argc == 2 &&
|
||||
(strcmp((*argv)[1], "-h") == 0 || strcmp((*argv)[1], "--help") == 0)) {
|
||||
fprintf(stderr, "%s", g_option_context_get_help(context, TRUE, NULL));
|
||||
exit(0);
|
||||
}
|
||||
for (i=0; context->entries[i].long_name; i++) {
|
||||
GOptionArg arg = context->entries[i].arg;
|
||||
count++;
|
||||
len++;
|
||||
if (arg == G_OPTION_ARG_STRING || arg == G_OPTION_ARG_INT) {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
struct option *long_opts = calloc(count+1, sizeof(struct option));
|
||||
char *short_opts = calloc(1, len+1);
|
||||
int j=0;
|
||||
for (i=0; i<count; i++) {
|
||||
const GOptionEntry *entry = &context->entries[i];
|
||||
GOptionArg arg = entry->arg;
|
||||
short_opts[j++] = entry->short_name;
|
||||
if (arg == G_OPTION_ARG_STRING || arg == G_OPTION_ARG_INT) {
|
||||
short_opts[j++] = ':';
|
||||
}
|
||||
long_opts[i].name = entry->long_name;
|
||||
long_opts[i].has_arg = entry->arg == G_OPTION_ARG_NONE ? no_argument : required_argument;
|
||||
}
|
||||
int c;
|
||||
int longindex = 0;
|
||||
opterr = 0;
|
||||
while ((c = getopt_long(*argc, *argv, short_opts, long_opts, &longindex)) != -1) {
|
||||
if (c == '?') {
|
||||
*error = malloc(sizeof(GError));
|
||||
(*error)->message = malloc(100);
|
||||
if (optopt) {
|
||||
snprintf((*error)->message, 100, "Unrecognized option: -%c", optopt);
|
||||
} else {
|
||||
snprintf((*error)->message, 100, "Unrecognized option: %s", (*argv)[optind-1]);
|
||||
}
|
||||
free(short_opts);
|
||||
free(long_opts);
|
||||
return FALSE;
|
||||
}
|
||||
const GOptionEntry *entry = NULL;
|
||||
if (c == 0) {
|
||||
entry = &context->entries[longindex];
|
||||
} else {
|
||||
for (i=0; i<count; i++) {
|
||||
if (context->entries[i].short_name == c) {
|
||||
entry = &context->entries[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (entry->arg == G_OPTION_ARG_NONE) {
|
||||
*(int *)entry->arg_data = !(entry->flags & G_OPTION_FLAG_REVERSE);
|
||||
} else if (entry->arg == G_OPTION_ARG_INT) {
|
||||
char *endptr = NULL;
|
||||
*(int *)entry->arg_data = strtol(optarg, &endptr, 10);
|
||||
if (*endptr) {
|
||||
*error = malloc(sizeof(GError));
|
||||
(*error)->message = malloc(100);
|
||||
snprintf((*error)->message, 100, "Argument to --%s must be an integer", entry->long_name);
|
||||
free(short_opts);
|
||||
free(long_opts);
|
||||
return FALSE;
|
||||
}
|
||||
} else if (entry->arg == G_OPTION_ARG_STRING) {
|
||||
*(char **)entry->arg_data = strdup(optarg);
|
||||
}
|
||||
}
|
||||
*argc -= (optind - 1);
|
||||
*argv += (optind - 1);
|
||||
free(short_opts);
|
||||
free(long_opts);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void g_option_context_free(GOptionContext *context) {
|
||||
free(context);
|
||||
}
|
@ -23,6 +23,10 @@
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) (a>b ? b : a)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function is used in reading text data from an MDB table.
|
||||
*/
|
||||
|
@ -176,16 +176,16 @@ mdb_dump_props(MdbProperties *props, FILE *outfile, int show_name) {
|
||||
/*
|
||||
* That function takes a raw KKD/MR2 binary buffer,
|
||||
* typically read from LvProp in table MSysbjects
|
||||
* and returns a GArray of MdbProps*
|
||||
* and returns a GPtrArray of MdbProps*
|
||||
*/
|
||||
GArray*
|
||||
GPtrArray*
|
||||
mdb_kkd_to_props(MdbHandle *mdb, void *buffer, size_t len) {
|
||||
guint32 record_len;
|
||||
guint16 record_type;
|
||||
size_t pos;
|
||||
GPtrArray *names = NULL;
|
||||
MdbProperties *props;
|
||||
GArray *result;
|
||||
GPtrArray *result;
|
||||
|
||||
#if MDB_DEBUG
|
||||
mdb_buffer_dump(buffer, 0, len);
|
||||
@ -198,7 +198,7 @@ mdb_kkd_to_props(MdbHandle *mdb, void *buffer, size_t len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = g_array_new(0, 0, sizeof(MdbProperties*));
|
||||
result = g_ptr_array_new();
|
||||
|
||||
pos = 4;
|
||||
while (pos < len) {
|
||||
@ -219,7 +219,7 @@ mdb_kkd_to_props(MdbHandle *mdb, void *buffer, size_t len) {
|
||||
break;
|
||||
}
|
||||
props = mdb_read_props(mdb, names, (char*)buffer+pos+6, record_len - 6);
|
||||
g_array_append_val(result, props);
|
||||
g_ptr_array_add(result, props);
|
||||
//mdb_dump_props(props, stderr, 1);
|
||||
break;
|
||||
default:
|
||||
|
@ -108,7 +108,7 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
|
||||
|
||||
if (entry->props)
|
||||
for (i=0; i<entry->props->len; ++i) {
|
||||
MdbProperties *props = g_array_index(entry->props, MdbProperties*, i);
|
||||
MdbProperties *props = g_ptr_array_index(entry->props, i);
|
||||
if (!props->name)
|
||||
table->props = props;
|
||||
}
|
||||
@ -222,7 +222,7 @@ GPtrArray *mdb_read_columns(MdbTableDef *table)
|
||||
unsigned int i, j;
|
||||
int cur_pos;
|
||||
size_t name_sz;
|
||||
GArray *allprops;
|
||||
GPtrArray *allprops;
|
||||
|
||||
table->columns = g_ptr_array_new();
|
||||
|
||||
@ -315,8 +315,8 @@ GPtrArray *mdb_read_columns(MdbTableDef *table)
|
||||
for (i=0;i<table->num_cols;i++) {
|
||||
pcol = g_ptr_array_index(table->columns, i);
|
||||
for (j=0; j<allprops->len; ++j) {
|
||||
MdbProperties *props = g_array_index(allprops, MdbProperties*, j);
|
||||
if (props->name && pcol->name && !strcmp(props->name, pcol->name)) {
|
||||
MdbProperties *props = g_ptr_array_index(allprops, j);
|
||||
if (props->name && !strcmp(props->name, pcol->name)) {
|
||||
pcol->props = props;
|
||||
break;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ static int GetNextItem (FILE* stream, char** name, char** value);
|
||||
#endif //HAVE_SQLGETPRIVATEPROFILESTRING
|
||||
|
||||
static void visit (gpointer key, gpointer value, gpointer user_data);
|
||||
static gboolean cleanup (gpointer key, gpointer value, gpointer user_data);
|
||||
static void cleanup (gpointer key, gpointer value, gpointer user_data);
|
||||
|
||||
/*
|
||||
* Allocate create a ConnectParams object
|
||||
@ -91,7 +91,7 @@ void FreeConnectParams (ConnectParams* params)
|
||||
g_string_free (params->iniFileName, TRUE);
|
||||
if (params->table)
|
||||
{
|
||||
g_hash_table_foreach_remove (params->table, cleanup, NULL);
|
||||
g_hash_table_foreach (params->table, cleanup, NULL);
|
||||
g_hash_table_destroy (params->table);
|
||||
}
|
||||
g_free(params);
|
||||
@ -514,12 +514,10 @@ static void visit (gpointer key, gpointer value, gpointer user_data)
|
||||
fprintf(output, "Parameter: %s, Value: %s\n", (char*)key, (char*)value);
|
||||
}
|
||||
|
||||
static gboolean cleanup (gpointer key, gpointer value, gpointer user_data)
|
||||
static void cleanup (gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
g_free (key);
|
||||
g_free (value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,11 @@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
BUILT_SOURCES = parser.h
|
||||
AM_YFLAGS = -d
|
||||
lib_LTLIBRARIES = libmdbsql.la
|
||||
libmdbsql_la_SOURCES= mdbsql.c parser.y lexer.l
|
||||
if FAKE_GLIB
|
||||
libmdbsql_la_SOURCES += ../libmdb/fakeglib.c
|
||||
endif
|
||||
libmdbsql_la_LDFLAGS = -version-info 2:0:0 -export-symbols-regex '^mdb_sql_'
|
||||
CLEANFILES = parser.c parser.h lexer.c
|
||||
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS)
|
||||
|
@ -1,7 +1,24 @@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
SUBDIRS = bash-completion
|
||||
bin_PROGRAMS = mdb-export mdb-array mdb-schema mdb-tables mdb-parsecsv mdb-header mdb-sql mdb-ver mdb-prop mdb-count
|
||||
noinst_PROGRAMS = mdb-import prtable prcat prdata prkkd prdump prole updrow prindex
|
||||
LIBS = $(GLIB_LIBS) @LIBS@
|
||||
mdb_export_SOURCES = mdb-export.c
|
||||
mdb_schema_SOURCES = mdb-schema.c
|
||||
mdb_tables_SOURCES = mdb-tables.c
|
||||
mdb_sql_SOURCES = mdb-sql.c
|
||||
mdb_ver_SOURCES = mdb-ver.c
|
||||
mdb_import_SOURCES = mdb-import.c
|
||||
updrow_SOURCES = updrow.c
|
||||
if FAKE_GLIB
|
||||
mdb_export_SOURCES += ../libmdb/fakeglib.c
|
||||
mdb_schema_SOURCES += ../libmdb/fakeglib.c
|
||||
mdb_tables_SOURCES += ../libmdb/fakeglib.c
|
||||
mdb_sql_SOURCES += ../libmdb/fakeglib.c
|
||||
mdb_ver_SOURCES += ../libmdb/fakeglib.c
|
||||
mdb_import_SOURCES += ../libmdb/fakeglib.c
|
||||
updrow_SOURCES += ../libmdb/fakeglib.c
|
||||
endif
|
||||
LIBS = $(GLIB_LIBS) @LIBS@
|
||||
DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\"
|
||||
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS)
|
||||
LDADD = ../libmdb/libmdb.la
|
||||
|
@ -91,12 +91,12 @@ main(int argc, char **argv)
|
||||
}
|
||||
void dump_kkd(MdbHandle *mdb, void *kkd, size_t len)
|
||||
{
|
||||
GArray *aprops = mdb_kkd_to_props(mdb, kkd, len);
|
||||
GPtrArray *aprops = mdb_kkd_to_props(mdb, kkd, len);
|
||||
int i;
|
||||
if (!aprops)
|
||||
return;
|
||||
for (i=0; i<aprops->len; ++i) {
|
||||
MdbProperties *props = g_array_index(aprops, MdbProperties*, i);
|
||||
MdbProperties *props = g_ptr_array_index(aprops, i);
|
||||
mdb_dump_props(props, stdout, 1);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user