summaryrefslogtreecommitdiff
path: root/contrib/pg_dumplo
diff options
context:
space:
mode:
authorBruce Momjian2000-06-15 19:05:22 +0000
committerBruce Momjian2000-06-15 19:05:22 +0000
commit5683e704d09caaa29f7a76f0d93ca8fc5f8c0e75 (patch)
tree3ae68795e6580e8ca4e464d8416cfc42d1b1bc49 /contrib/pg_dumplo
parentf7f177d372750e4f766ccefdf20e1b30d66cba0a (diff)
Add missing /contrib files to CVS.
Diffstat (limited to 'contrib/pg_dumplo')
-rw-r--r--contrib/pg_dumplo/INSTALL37
-rw-r--r--contrib/pg_dumplo/Makefile.out42
-rw-r--r--contrib/pg_dumplo/lo_export.c176
-rw-r--r--contrib/pg_dumplo/lo_import.c89
-rw-r--r--contrib/pg_dumplo/main.c308
-rw-r--r--contrib/pg_dumplo/pg_dumplo.h68
-rw-r--r--contrib/pg_dumplo/utils.c94
7 files changed, 814 insertions, 0 deletions
diff --git a/contrib/pg_dumplo/INSTALL b/contrib/pg_dumplo/INSTALL
new file mode 100644
index 0000000000..15733527a9
--- /dev/null
+++ b/contrib/pg_dumplo/INSTALL
@@ -0,0 +1,37 @@
+
+
+pg_dumplo - PostgreSQL large object dumper
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For more information see the help ( pg_dumplo -h ) and examples in
+this help or the cool HOWTO.
+
+
+Compilation:
+~~~~~~~~~~~
+ - In the PG contrib tree:
+ * run master ./configure in the PG source top directory
+ * run 'make'
+ * run 'make install'
+
+ - Out of PG contrib:
+ * edit Makefile.out
+ * run 'make -f Makefile.out'
+
+
+THANKS:
+~~~~~~
+ <??? I lost his e-mail ???>
+ * option '--all' and pg_class usage
+
+ Pavel Janík ml. <Pavel.Janik@linux.cz>
+ * HOWTO
+
+
+
+ Karel Zak <zakkr@zf.jcu.cz>
+
+
+
+
+
diff --git a/contrib/pg_dumplo/Makefile.out b/contrib/pg_dumplo/Makefile.out
new file mode 100644
index 0000000000..15bae55e20
--- /dev/null
+++ b/contrib/pg_dumplo/Makefile.out
@@ -0,0 +1,42 @@
+
+# ----------
+# pg_dumplo - Makefile for compilation out of PostgreSQL contrib tree
+# ----------
+
+
+# Set correct values
+#
+CFLAGS = -Wall -fpic
+CC = gcc
+RM = rm
+INCLUDE = -I/usr/include/pgsql
+LIBS =-L/usr/lib/postgresql/lib -lpq
+
+# Comment this option if your system not has getopt_long()
+#
+HAVE_GETOPT_LONG = -DHAVE_GETOPT_LONG
+
+
+# --------------------------- not edit ---------------------------------
+
+PROGRAM = pg_dumplo
+
+OBJECTS = main.o lo_export.o lo_import.o utils.o
+
+CFLAGS += -DOUT_OF_PG $(HAVE_GETOPT_LONG)
+
+COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDE)
+LINK = $(CC) $(CFLAGS) -o $@ $(LIBS)
+
+
+all: $(PROGRAM)
+
+$(PROGRAM): $(OBJECTS)
+ $(LINK) $(OBJECTS)
+
+.c.o: $<
+ $(COMPILE) -c $<
+
+clean:
+ $(RM) -f *~ $(OBJECTS) $(PROGRAM)
+
diff --git a/contrib/pg_dumplo/lo_export.c b/contrib/pg_dumplo/lo_export.c
new file mode 100644
index 0000000000..80d401902c
--- /dev/null
+++ b/contrib/pg_dumplo/lo_export.c
@@ -0,0 +1,176 @@
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+
+#include <libpq-fe.h>
+#include <libpq/libpq-fs.h>
+
+#include "pg_dumplo.h"
+
+extern int errno;
+
+#define LOAD_LOLIST_QUERY "\
+ SELECT c.relname, a.attname \
+ FROM pg_class c, pg_attribute a, pg_type t \
+ WHERE a.attnum > 0 \
+ AND a.attrelid = c.oid \
+ AND a.atttypid = t.oid \
+ AND t.typname = 'oid' \
+ AND c.relname NOT LIKE 'pg_%'"
+
+
+void
+load_lolist( LODumpMaster *pgLO )
+{
+ LOlist *ll;
+ int i;
+ int n;
+
+ /* ----------
+ * Now find any candidate tables who have columns of type oid (the
+ * column oid is ignored, as it has attnum < 1)
+ * ----------
+ */
+ if (!(pgLO->res = PQexec(pgLO->conn, LOAD_LOLIST_QUERY))) {
+
+ fprintf(stderr, "%s: Select from pg_class failed.\n", progname);
+ exit(RE_ERROR);
+ }
+
+ if ((n = PQntuples(pgLO->res)) == 0) {
+
+ fprintf(stderr, "%s: No large objects in the database.\n", progname);
+ exit(RE_ERROR);
+ }
+
+ pgLO->lolist = (LOlist *) malloc((n + 1) * sizeof(LOlist));
+
+ if (!pgLO->lolist) {
+ fprintf(stderr, "%s: can't allocate memory\n", progname);
+ exit(RE_ERROR);
+ }
+
+ for (i = 0, ll = pgLO->lolist; i < n; i++, ll++) {
+ ll->lo_table = strdup(PQgetvalue(pgLO->res, i, 0));
+ ll->lo_attr = strdup(PQgetvalue(pgLO->res, i, 1));
+ }
+
+ PQclear(pgLO->res);
+ ll++;
+ ll->lo_table = ll->lo_attr = (char *) NULL;
+}
+
+void
+pglo_export(LODumpMaster *pgLO)
+{
+ LOlist *ll;
+ int tuples;
+ char path[BUFSIZ],
+ Qbuff[QUERY_BUFSIZ];
+
+ if (pgLO->action != ACTION_SHOW) {
+ time_t t;
+ time(&t);
+ fprintf(pgLO->index, "#\n# This is the PostgreSQL large object dump index\n#\n");
+ fprintf(pgLO->index, "#\tDate: %s", ctime(&t));
+ fprintf(pgLO->index, "#\tHost: %s\n", pgLO->host);
+ fprintf(pgLO->index, "#\tDatabase: %s\n", pgLO->db);
+ fprintf(pgLO->index, "#\tUser: %s\n", pgLO->user);
+ fprintf(pgLO->index, "#\n# oid\ttable\tattribut\tinfile\n#\n");
+ }
+
+ pgLO->counter = 0;
+
+ for(ll=pgLO->lolist; ll->lo_table != NULL; ll++) {
+
+ /* ----------
+ * Query
+ * ----------
+ */
+ sprintf(Qbuff, "SELECT x.%s FROM %s x, pg_class c WHERE x.%s = c.oid and c.relkind = 'l'",
+ ll->lo_attr, ll->lo_table, ll->lo_attr);
+
+ /* puts(Qbuff); */
+
+ pgLO->res = PQexec(pgLO->conn, Qbuff);
+
+ if ((tuples = PQntuples(pgLO->res)) == 0) {
+
+ if (!pgLO->quiet && pgLO->action == ACTION_EXPORT_ATTR)
+ printf("%s: not large objets in '%s'\n", progname, ll->lo_table);
+ continue;
+
+ } else if (check_res(pgLO)) {
+
+ int t;
+ char *val;
+
+ /* ----------
+ * Create DIR/FILE
+ * ----------
+ */
+ if (tuples && pgLO->action != ACTION_SHOW) {
+
+ sprintf(path, "%s/%s/%s", pgLO->space, pgLO->db, ll->lo_table);
+
+ if (mkdir(path, DIR_UMASK) == -1) {
+ if (errno != EEXIST) {
+ perror(path);
+ exit(RE_ERROR);
+ }
+ }
+
+ sprintf(path, "%s/%s", path, ll->lo_attr);
+
+ if (mkdir(path, DIR_UMASK) == -1) {
+ if (errno != EEXIST) {
+ perror(path);
+ exit(RE_ERROR);
+ }
+ }
+
+ if (!pgLO->quiet)
+ printf("dump %s.%s (%d lagre obj)\n",
+ ll->lo_table, ll->lo_attr, tuples);
+ }
+
+ pgLO->counter += tuples;
+
+ for(t=0; t<tuples; t++) {
+
+ Oid lo = (Oid) 0;
+
+ val = PQgetvalue(pgLO->res, t, 0);
+
+ if (!val)
+ continue;
+ else
+ lo = (Oid) atol(val);
+
+ if (pgLO->action == ACTION_SHOW) {
+ printf("%s.%s: %ld\n", ll->lo_table,
+ ll->lo_attr, (long) lo);
+ continue;
+ }
+
+ sprintf(path, "%s/%s/%s/%s/%s", pgLO->space,
+ pgLO->db, ll->lo_table, ll->lo_attr, val);
+
+ if (lo_export(pgLO->conn, lo, path) < 0)
+ fprintf(stderr, "%s: %s\n", PQerrorMessage(pgLO->conn), progname);
+
+ else
+ fprintf(pgLO->index, "%s\t%s\t%s\t%s/%s/%s/%s\n", val,
+ ll->lo_table, ll->lo_attr, pgLO->db, ll->lo_table, ll->lo_attr, val);
+ }
+ }
+ }
+ }
+
diff --git a/contrib/pg_dumplo/lo_import.c b/contrib/pg_dumplo/lo_import.c
new file mode 100644
index 0000000000..98d81f19fa
--- /dev/null
+++ b/contrib/pg_dumplo/lo_import.c
@@ -0,0 +1,89 @@
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+
+#include <libpq-fe.h>
+#include <libpq/libpq-fs.h>
+
+#include "pg_dumplo.h"
+
+extern int errno;
+
+void
+pglo_import(LODumpMaster *pgLO)
+{
+ LOlist loa;
+ long new_oid;
+ char tab[MAX_TABLE_NAME], attr[MAX_ATTR_NAME],
+ path[BUFSIZ], lo_path[BUFSIZ],
+ Qbuff[QUERY_BUFSIZ];
+
+ while(fgets(Qbuff, QUERY_BUFSIZ, pgLO->index)) {
+
+ if (*Qbuff == '#')
+ continue;
+
+ if (! pgLO->remove && ! pgLO->quiet)
+ printf(Qbuff);
+
+ sscanf(Qbuff, "%ld\t%s\t%s\t%s\n", &loa.lo_oid, tab, attr, path);
+ loa.lo_table = tab;
+ loa.lo_attr = attr;
+
+ sprintf(lo_path, "%s/%s", pgLO->space, path);
+
+ /* ----------
+ * Import LO
+ * ----------
+ */
+ if ((new_oid = lo_import(pgLO->conn, lo_path)) <= 0) {
+
+ fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn));
+
+ PQexec(pgLO->conn, "ROLLBACK");
+ fprintf(stderr, "\n%s: ROLLBACK\n", progname);
+ exit(RE_ERROR);
+ }
+
+ if (pgLO->remove) {
+ notice(pgLO, FALSE);
+ if (lo_unlink(pgLO->conn, (Oid) loa.lo_oid) < 0)
+ fprintf(stderr, "%s: can't remove LO: %ld (%s)\n",
+ progname, loa.lo_oid, PQerrorMessage(pgLO->conn));
+
+ else if (!pgLO->quiet)
+ printf("remove old %ld and create new %ld\n",
+ loa.lo_oid, new_oid);
+ notice(pgLO, TRUE);
+ }
+
+ pgLO->counter++;
+
+ /* ----------
+ * UPDATE oid in tab
+ * ----------
+ */
+ sprintf(Qbuff, "UPDATE %s SET %s=%ld WHERE %s=%ld",
+ loa.lo_table, loa.lo_attr, new_oid, loa.lo_attr, loa.lo_oid);
+
+ /*fprintf(stderr, Qbuff);*/
+
+ pgLO->res = PQexec(pgLO->conn, Qbuff);
+
+ if (!pgLO->res && PQresultStatus(pgLO->res) != PGRES_COMMAND_OK) {
+
+ fprintf(stderr, "%s: %s\n",progname, PQerrorMessage(pgLO->conn));
+ PQclear(pgLO->res);
+ PQexec(pgLO->conn, "ROLLBACK");
+ fprintf(stderr, "\n%s: ROLLBACK\n", progname);
+ exit(RE_ERROR);
+ }
+ }
+ }
diff --git a/contrib/pg_dumplo/main.c b/contrib/pg_dumplo/main.c
new file mode 100644
index 0000000000..bc75476a1d
--- /dev/null
+++ b/contrib/pg_dumplo/main.c
@@ -0,0 +1,308 @@
+
+/* -------------------------------------------------------------------------
+ * pg_dumplo
+ *
+ * Portions Copyright (c) 1999-2000, PostgreSQL, Inc
+ *
+ * $Header: /cvsroot/pgsql/contrib/pg_dumplo/Attic/main.c,v 1.1 2000/06/15 19:05:08 momjian Exp $
+ *
+ * Karel Zak 1999-2000
+ * -------------------------------------------------------------------------
+ */
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef OUT_OF_PG
+ #include "postgres.h"
+#endif
+
+#include <libpq-fe.h>
+#include <libpq/libpq-fs.h>
+
+#ifdef HAVE_GETOPT_LONG
+ #include <getopt.h>
+ #define no_argument 0
+ #define required_argument 1
+#endif
+
+extern int errno;
+
+char *progname = NULL;
+
+#include "pg_dumplo.h"
+
+int main(int argc, char **argv);
+static void usage(void);
+static void parse_lolist (LODumpMaster *pgLO);
+
+
+/*-----
+ * The mother of all C functions
+ *-----
+ */
+int
+main(int argc, char **argv)
+{
+ LODumpMaster _pgLO, *pgLO = &_pgLO;
+ char *pwd = NULL;
+
+ pgLO->argv = argv;
+ pgLO->argc = argc;
+ pgLO->action = 0;
+ pgLO->lolist = NULL;
+ pgLO->user = NULL;
+ pgLO->db = NULL;
+ pgLO->host = NULL;
+ pgLO->space = NULL;
+ pgLO->index = NULL;
+ pgLO->remove = FALSE;
+ pgLO->quiet = FALSE;
+ pgLO->counter = 0;
+ pgLO->lolist_start = 0;
+
+ progname = argv[0];
+
+ /* ----------
+ * Parse ARGV
+ * ----------
+ */
+ if (argc > 1) {
+ int arg;
+ extern int optind;
+
+#ifdef HAVE_GETOPT_LONG
+ int l_index=0;
+ static struct option l_opt[] = {
+ { "help", no_argument, 0, 'h' },
+ { "user", required_argument, 0, 'u' },
+ { "pwd", required_argument, 0, 'p' },
+ { "db", required_argument, 0, 'd' },
+ { "host", required_argument, 0, 'h' },
+ { "space", required_argument, 0, 's' },
+ { "import", no_argument, 0, 'i' },
+ { "remove", no_argument, 0, 'r' },
+ { "quiet", no_argument, 0, 'q' },
+ { "all", no_argument, 0, 'a' },
+ { "show", no_argument, 0, 'w' },
+ { NULL, 0, 0, 0 }
+ };
+
+ while((arg = getopt_long(argc, argv, "?aehu:p:qd:l:t:irs:w", l_opt, &l_index)) != -1) {
+#else
+ while((arg = getopt(argc, argv, "?aehu:p:qd:l:t:irs:w")) != -1) {
+#endif
+ switch(arg) {
+ case '?':
+ case 'h':
+ usage();
+ exit(RE_OK);
+ case 'u':
+ pgLO->user = strdup(optarg);
+ break;
+ case 't':
+ pgLO->host = strdup(optarg);
+ break;
+ case 'p':
+ pwd = strdup(optarg);
+ break;
+ case 'd':
+ pgLO->db = strdup(optarg);
+ break;
+ case 's':
+ pgLO->space = strdup(optarg);
+ break;
+ case 'i':
+ pgLO->action = ACTION_IMPORT;
+ break;
+ case 'l':
+ pgLO->action = ACTION_EXPORT_ATTR;
+ pgLO->lolist_start = optind-1;
+ parse_lolist (pgLO);
+ break;
+ case 'e':
+ case 'a':
+ pgLO->action = ACTION_EXPORT_ALL;
+ break;
+ case 'w':
+ pgLO->action = ACTION_SHOW;
+ break;
+ case 'r':
+ pgLO->remove = TRUE;
+ break;
+ case 'q':
+ pgLO->quiet = TRUE;
+ break;
+ default:
+ fprintf(stderr, "%s: bad arg!\n", progname);
+ usage();
+ exit(RE_ERROR);
+ }
+ }
+ } else {
+ usage();
+ exit(RE_ERROR);
+ }
+
+ /* ----------
+ * Check space
+ * ----------
+ */
+ if (! pgLO->space) {
+ if (!(pgLO->space = getenv("PWD"))) {
+ fprintf(stderr, "%s: not set space for dump-tree (option '-s' or $PWD).\n", progname);
+ exit(RE_ERROR);
+ }
+ }
+
+ /* ----------
+ * Make connection
+ * ----------
+ */
+ pgLO->conn = PQsetdbLogin(pgLO->host, NULL, NULL, NULL, pgLO->db,
+ pgLO->user, pwd);
+
+ if (PQstatus(pgLO->conn) == CONNECTION_BAD) {
+ fprintf(stderr, "%s (connection): %s\n", progname, PQerrorMessage(pgLO->conn));
+ exit(RE_ERROR);
+ }
+ pgLO->host = PQhost(pgLO->conn) ? PQhost(pgLO->conn) : "localhost";
+ pgLO->db = PQdb(pgLO->conn);
+ pgLO->user = PQuser(pgLO->conn);
+
+
+ /* ----------
+ * Init index file
+ * ----------
+ */
+ if (pgLO->action) {
+ index_file(pgLO);
+ } else {
+ fprintf(stderr, "%s: What do you want - export or import?\n", progname);
+ exit(RE_ERROR);
+ }
+
+ PQexec(pgLO->conn, "BEGIN");
+
+ switch(pgLO->action) {
+
+ case ACTION_SHOW:
+ case ACTION_EXPORT_ALL:
+ load_lolist(pgLO);
+
+ case ACTION_EXPORT_ATTR:
+ pglo_export(pgLO);
+ if (!pgLO->quiet) {
+ if (pgLO->action == ACTION_SHOW)
+ printf("\nDatabase '%s' content %d large objects.\n\n", pgLO->db, pgLO->counter);
+ else
+ printf("\nExported %d large objects.\n\n", pgLO->counter);
+ }
+ break;
+
+ case ACTION_IMPORT:
+ pglo_import(pgLO);
+ if (!pgLO->quiet)
+ printf("\nImported %d large objects.\n\n", pgLO->counter);
+ break;
+ }
+
+ PQexec(pgLO->conn, "COMMIT");
+ PQfinish(pgLO->conn);
+
+ if (pgLO->action != ACTION_SHOW)
+ fclose(pgLO->index);
+
+ exit(RE_OK);
+}
+
+static void
+parse_lolist (LODumpMaster *pgLO)
+{
+ LOlist *ll;
+ char **d,
+ *loc,
+ buff[MAX_TABLE_NAME + MAX_ATTR_NAME +1];
+
+ pgLO->lolist = (LOlist *) malloc(pgLO->argc * sizeof(LOlist));
+
+ if (! pgLO->lolist) {
+ fprintf(stderr, "%s: can't allocate memory\n", progname);
+ exit(RE_ERROR);
+ }
+
+ for( d=pgLO->argv + pgLO->lolist_start, ll=pgLO->lolist;
+ *d != NULL;
+ d++, ll++) {
+
+ strncpy(buff, *d, MAX_TABLE_NAME + MAX_ATTR_NAME);
+
+ if ((loc = strchr(buff, '.')) == NULL) {
+ fprintf(stderr, "%s: '%s' is bad 'table.attr'\n", progname, buff);
+ exit(RE_ERROR);
+ }
+ *loc = '\0';
+ ll->lo_table = strdup(buff);
+ ll->lo_attr = strdup(++loc);
+ }
+ ll++;
+ ll->lo_table = ll->lo_attr = (char *) NULL;
+}
+
+
+static void
+usage()
+{
+ printf("\npg_dumplo %s - PostgreSQL large objects dump\n", VERSION);
+ puts("pg_dumplo [option]\n\n"
+
+#ifdef HAVE_GETOPT_LONG
+
+ "-h --help this help\n"
+ "-u --user=<username> username for connection to server\n"
+ "-p --password=<password> password for connection to server\n"
+ "-d --db=<database> database name\n"
+ "-t --host=<hostname> server hostname\n"
+ "-s --space=<dir> directory with dump tree (for export/import)\n"
+ "-i --import import large obj dump tree to DB\n"
+ "-e --export export (dump) large obj to dump tree\n"
+ "-l <table.attr ...> dump attribute (columns) with LO to dump tree\n"
+ "-a --all dump all LO in DB (default)\n"
+ "-r --remove if is set '-i' try remove old LO\n"
+ "-q --quiet run quietly\n"
+ "-w --show not dump, but show all LO in DB\n"
+ ); /* puts() */
+
+#else
+ "-h this help\n"
+ "-u <username> username for connection to server\n"
+ "-p <password> password for connection to server\n"
+ "-d <database> database name\n"
+ "-t <hostname> server hostname\n"
+ "-s <dir> directory with dump tree (for export/import)\n"
+ "-i import large obj dump tree to DB\n"
+ "-e export (dump) large obj to dump tree\n"
+ "-l <table.attr ...> dump attribute (columns) with LO to dump tree\n"
+ "-a dump all LO in DB (default)\n"
+ "-r if is set '-i' try remove old LO\n"
+ "-q run quietly\n"
+ "-w not dump, but show all LO in DB\n"
+ ); /* puts() */
+
+#endif
+
+ puts(
+ "Example (dump): pg_dumplo -d my_db -s /my_dump/dir -l t1.a t1.b t2.a\n"
+ " pg_dumplo -a -d my_db -s /my_dump/dir\n"
+ "Example (import): pg_dumplo -i -d my_db -s /my_dump/dir\n"
+ "Example (show): pg_dumplo -w -d my_db\n\n"
+ "Note: * option '-l' must be last option!\n"
+ " * option '-i' without option '-r' make new large obj in DB\n"
+ " not rewrite old, the '-i' UPDATE oid numbers in table.attr only!\n"
+ " * if is not set option -s, the pg_dumplo use $PWD\n"
+ ); /* puts()*/
+}
diff --git a/contrib/pg_dumplo/pg_dumplo.h b/contrib/pg_dumplo/pg_dumplo.h
new file mode 100644
index 0000000000..d9132ba059
--- /dev/null
+++ b/contrib/pg_dumplo/pg_dumplo.h
@@ -0,0 +1,68 @@
+
+#ifndef _PG_LODUMP_H_
+#define _PG_LODUMP_H_
+
+#define VERSION "0.0.5"
+
+/* ----------
+ * Define
+ * ----------
+ */
+#define QUERY_BUFSIZ (8*1024)
+#define DIR_UMASK 0755
+#define FILE_UMASK 0666
+
+#define TRUE 1
+#define FALSE 0
+#define RE_OK 0
+#define RE_ERROR 1
+
+#define MAX_TABLE_NAME 128
+#define MAX_ATTR_NAME 128
+
+extern char *progname;
+
+/* ----------
+ * LO struct
+ * ----------
+ */
+typedef struct {
+ char *lo_table,
+ *lo_attr;
+ long lo_oid;
+} LOlist;
+
+typedef struct {
+ int action;
+ LOlist *lolist;
+ char **argv,
+ *user,
+ *db,
+ *host,
+ *space;
+ FILE *index;
+ int counter,
+ argc,
+ lolist_start,
+ remove,
+ quiet;
+ PGresult *res;
+ PGconn *conn;
+} LODumpMaster;
+
+typedef enum {
+ ACTION_NONE,
+ ACTION_SHOW,
+ ACTION_EXPORT_ATTR,
+ ACTION_EXPORT_ALL,
+ ACTION_IMPORT
+} PGLODUMP_ACTIONS;
+
+extern void notice (LODumpMaster *pgLO, int set);
+extern int check_res (LODumpMaster *pgLO);
+extern void index_file (LODumpMaster *pgLO);
+extern void load_lolist (LODumpMaster *pgLO);
+extern void pglo_export (LODumpMaster *pgLO);
+extern void pglo_import (LODumpMaster *pgLO);
+
+#endif /* _PG_LODUMP_H */
diff --git a/contrib/pg_dumplo/utils.c b/contrib/pg_dumplo/utils.c
new file mode 100644
index 0000000000..70bfb8b5db
--- /dev/null
+++ b/contrib/pg_dumplo/utils.c
@@ -0,0 +1,94 @@
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+
+#include <libpq-fe.h>
+#include <libpq/libpq-fs.h>
+
+#include "pg_dumplo.h"
+
+extern int errno;
+
+static void Dummy_NoticeProcessor(void * arg, const char * message);
+static void Default_NoticeProcessor(void * arg, const char * message);
+
+
+void
+index_file(LODumpMaster *pgLO)
+{
+ char path[BUFSIZ];
+
+ if (pgLO->action == ACTION_SHOW)
+ return;
+
+ sprintf(path, "%s/%s", pgLO->space, pgLO->db);
+
+ if (pgLO->action == ACTION_EXPORT_ATTR ||
+ pgLO->action == ACTION_EXPORT_ALL) {
+
+ if (mkdir(path, DIR_UMASK) == -1) {
+ if (errno != EEXIST) {
+ perror(path);
+ exit(RE_ERROR);
+ }
+ }
+
+ sprintf(path, "%s/lo_dump.index", path);
+
+ if ((pgLO->index = fopen(path, "w")) == NULL) {
+ perror(path);
+ exit(RE_ERROR);
+ }
+
+ } else if (pgLO->action != ACTION_NONE ) {
+
+ sprintf(path, "%s/lo_dump.index", path);
+
+ if ((pgLO->index = fopen(path, "r")) == NULL) {
+ perror(path);
+ exit(RE_ERROR);
+ }
+ }
+}
+
+int
+check_res(LODumpMaster *pgLO)
+{
+ if (!pgLO->res && PQresultStatus(pgLO->res) != PGRES_COMMAND_OK) {
+ fprintf(stderr, "%s: %s\n", progname, PQerrorMessage(pgLO->conn));
+ PQclear(pgLO->res);
+ return FALSE;
+ }
+ if (PQresultStatus(pgLO->res) != PGRES_TUPLES_OK) {
+ fprintf(stderr, "%s: Tuples is not OK.\n", progname);
+ PQclear(pgLO->res);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static
+void Dummy_NoticeProcessor(void * arg, const char * message)
+{
+ ;
+}
+
+static
+void Default_NoticeProcessor(void * arg, const char * message)
+{
+ fprintf(stderr, "%s", message);
+}
+
+void
+notice(LODumpMaster *pgLO, int set)
+{
+ if (set)PQsetNoticeProcessor(pgLO->conn, Default_NoticeProcessor, NULL);
+ else PQsetNoticeProcessor(pgLO->conn, Dummy_NoticeProcessor, NULL);
+}