⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fe-lobj.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * fe-lobj.c *	  Front-end large object interface * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.20 1999/05/10 00:46:26 momjian Exp $ * *------------------------------------------------------------------------- */#include "libpq-fe.h"#include "libpq-int.h"#include "postgres.h"#ifdef WIN32#include "win32.h"#include <io.h>#else#if !defined(NO_UNISTD_H)#include <unistd.h>#endif#endif#include <string.h>#include <fcntl.h>#include <sys/stat.h>#include "libpq/libpq-fs.h"		/* must come after sys/stat.h */#define LO_BUFSIZE		  1024static int	lo_initialize(PGconn *conn);/* * lo_open *	  opens an existing large object * * returns the file descriptor for use in later lo_* calls * return -1 upon failure. */intlo_open(PGconn *conn, Oid lobjId, int mode){	int			fd;	int			result_len;	PQArgBlock	argv[2];	PGresult   *res;	argv[0].isint = 1;	argv[0].len = 4;	argv[0].u.integer = lobjId;	argv[1].isint = 1;	argv[1].len = 4;	argv[1].u.integer = mode;	if (conn->lobjfuncs == (PGlobjfuncs *) NULL)	{		if (lo_initialize(conn) < 0)			return -1;	}	res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2);	if (PQresultStatus(res) == PGRES_COMMAND_OK)	{		PQclear(res);		/* have to do this to reset offset in shared fd cache */		/* but only if fd is valid */		if (fd >= 0 && lo_lseek(conn, fd, 0L, SEEK_SET) < 0)			return -1;		return fd;	}	else	{		PQclear(res);		return -1;	}}/* * lo_close *	  closes an existing large object * * returns 0 upon success * returns -1 upon failure. */intlo_close(PGconn *conn, int fd){	PQArgBlock	argv[1];	PGresult   *res;	int			retval;	int			result_len;	if (conn->lobjfuncs == (PGlobjfuncs *) NULL)	{		if (lo_initialize(conn) < 0)			return -1;	}	argv[0].isint = 1;	argv[0].len = 4;	argv[0].u.integer = fd;	res = PQfn(conn, conn->lobjfuncs->fn_lo_close,			   &retval, &result_len, 1, argv, 1);	if (PQresultStatus(res) == PGRES_COMMAND_OK)	{		PQclear(res);		return retval;	}	else	{		PQclear(res);		return -1;	}}/* * lo_read *	  read len bytes of the large object into buf * * returns the length of bytes read. * the CALLER must have allocated enough space to hold the result returned */intlo_read(PGconn *conn, int fd, char *buf, int len){	PQArgBlock	argv[2];	PGresult   *res;	int			result_len;	if (conn->lobjfuncs == (PGlobjfuncs *) NULL)	{		if (lo_initialize(conn) < 0)			return -1;	}	argv[0].isint = 1;	argv[0].len = 4;	argv[0].u.integer = fd;	argv[1].isint = 1;	argv[1].len = 4;	argv[1].u.integer = len;	res = PQfn(conn, conn->lobjfuncs->fn_lo_read,			   (int *) buf, &result_len, 0, argv, 2);	if (PQresultStatus(res) == PGRES_COMMAND_OK)	{		PQclear(res);		return result_len;	}	else	{		PQclear(res);		return -1;	}}/* * lo_write *	  write len bytes of buf into the large object fd * */intlo_write(PGconn *conn, int fd, char *buf, int len){	PQArgBlock	argv[2];	PGresult   *res;	int			result_len;	int			retval;	if (conn->lobjfuncs == (PGlobjfuncs *) NULL)	{		if (lo_initialize(conn) < 0)			return -1;	}	if (len <= 0)		return 0;	argv[0].isint = 1;	argv[0].len = 4;	argv[0].u.integer = fd;	argv[1].isint = 0;	argv[1].len = len;	argv[1].u.ptr = (int *) buf;	res = PQfn(conn, conn->lobjfuncs->fn_lo_write,			   &retval, &result_len, 1, argv, 2);	if (PQresultStatus(res) == PGRES_COMMAND_OK)	{		PQclear(res);		return retval;	}	else	{		PQclear(res);		return -1;	}}/* * lo_lseek *	  change the current read or write location on a large object * currently, only L_SET is a legal value for whence * */intlo_lseek(PGconn *conn, int fd, int offset, int whence){	PQArgBlock	argv[3];	PGresult   *res;	int			retval;	int			result_len;	if (conn->lobjfuncs == (PGlobjfuncs *) NULL)	{		if (lo_initialize(conn) < 0)			return -1;	}	argv[0].isint = 1;	argv[0].len = 4;	argv[0].u.integer = fd;	argv[1].isint = 1;	argv[1].len = 4;	argv[1].u.integer = offset;	argv[2].isint = 1;	argv[2].len = 4;	argv[2].u.integer = whence;	res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek,			   &retval, &result_len, 1, argv, 3);	if (PQresultStatus(res) == PGRES_COMMAND_OK)	{		PQclear(res);		return retval;	}	else	{		PQclear(res);		return -1;	}}/* * lo_creat *	  create a new large object * the mode is a bitmask describing different attributes of the new object * * returns the oid of the large object created or * InvalidOid upon failure */Oidlo_creat(PGconn *conn, int mode){	PQArgBlock	argv[1];	PGresult   *res;	int			retval;	int			result_len;	if (conn->lobjfuncs == (PGlobjfuncs *) NULL)	{		if (lo_initialize(conn) < 0)			return -1;	}	argv[0].isint = 1;	argv[0].len = 4;	argv[0].u.integer = mode;	res = PQfn(conn, conn->lobjfuncs->fn_lo_creat,			   &retval, &result_len, 1, argv, 1);	if (PQresultStatus(res) == PGRES_COMMAND_OK)	{		PQclear(res);		return (Oid) retval;	}	else	{		PQclear(res);		return InvalidOid;	}}/* * lo_tell *	  returns the current seek location of the large object * */intlo_tell(PGconn *conn, int fd){	int			retval;	PQArgBlock	argv[1];	PGresult   *res;	int			result_len;	if (conn->lobjfuncs == (PGlobjfuncs *) NULL)	{		if (lo_initialize(conn) < 0)			return -1;	}	argv[0].isint = 1;	argv[0].len = 4;	argv[0].u.integer = fd;	res = PQfn(conn, conn->lobjfuncs->fn_lo_tell,			   &retval, &result_len, 1, argv, 1);	if (PQresultStatus(res) == PGRES_COMMAND_OK)	{		PQclear(res);		return retval;	}	else	{		PQclear(res);		return -1;	}}/* * lo_unlink *	  delete a file * */intlo_unlink(PGconn *conn, Oid lobjId){	PQArgBlock	argv[1];	PGresult   *res;	int			result_len;	int			retval;	if (conn->lobjfuncs == (PGlobjfuncs *) NULL)	{		if (lo_initialize(conn) < 0)			return -1;	}	argv[0].isint = 1;	argv[0].len = 4;	argv[0].u.integer = lobjId;	res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink,			   &retval, &result_len, 1, argv, 1);	if (PQresultStatus(res) == PGRES_COMMAND_OK)	{		PQclear(res);		return retval;	}	else	{		PQclear(res);		return -1;	}}/* * lo_import - *	  imports a file as an (inversion) large object. *		returns the oid of that object upon success, * returns InvalidOid upon failure * */Oidlo_import(PGconn *conn, char *filename){	int			fd;	int			nbytes,				tmp;	char		buf[LO_BUFSIZE];	Oid			lobjOid;	int			lobj;	/*	 * open the file to be read in	 */#ifndef __CYGWIN32__	fd = open(filename, O_RDONLY, 0666);#else	fd = open(filename, O_RDONLY | O_BINARY, 0666);#endif	if (fd < 0)	{							/* error */		sprintf(conn->errorMessage,				"lo_import: can't open unix file\"%s\"\n", filename);		return InvalidOid;	}	/*	 * create an inversion "object"	 */	lobjOid = lo_creat(conn, INV_READ | INV_WRITE);	if (lobjOid == InvalidOid)	{		sprintf(conn->errorMessage,			  "lo_import: can't create inv object for \"%s\"", filename);		return InvalidOid;	}	lobj = lo_open(conn, lobjOid, INV_WRITE);	if (lobj == -1)	{		sprintf(conn->errorMessage,				"lo_import: could not open inv object oid %u", lobjOid);		return InvalidOid;	}	/*	 * read in from the Unix file and write to the inversion file	 */	while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0)	{		tmp = lo_write(conn, lobj, buf, nbytes);		if (tmp < nbytes)		{			sprintf(conn->errorMessage,					"lo_import: error while reading \"%s\"", filename);			return InvalidOid;		}	}	(void) close(fd);	(void) lo_close(conn, lobj);	return lobjOid;}/* * lo_export - *	  exports an (inversion) large object. * returns -1 upon failure, 1 otherwise */intlo_export(PGconn *conn, Oid lobjId, char *filename){	int			fd;	int			nbytes,				tmp;	char		buf[LO_BUFSIZE];	int			lobj;	/*	 * create an inversion "object"	 */	lobj = lo_open(conn, lobjId, INV_READ);	if (lobj == -1)	{		sprintf(conn->errorMessage,				"lo_export: can't open inv object %u", lobjId);		return -1;	}	/*	 * open the file to be written to	 */#ifndef __CYGWIN32__	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);#else	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0666);#endif	if (fd < 0)	{							/* error */		sprintf(conn->errorMessage,				"lo_export: can't open unix file\"%s\"", filename);		return 0;	}	/*	 * read in from the Unix file and write to the inversion file	 */	while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0)	{		tmp = write(fd, buf, nbytes);		if (tmp < nbytes)		{			sprintf(conn->errorMessage,					"lo_export: error while writing \"%s\"",					filename);			return -1;		}	}	(void) lo_close(conn, lobj);	(void) close(fd);	return 1;}/* ---------------- * lo_initialize * * Initialize the large object interface for an existing connection. * We ask the backend about the functions OID's in pg_proc for all * functions that are required for large object operations. * ---------------- */static intlo_initialize(PGconn *conn){	PGresult   *res;	PGlobjfuncs *lobjfuncs;	int			n;	char	   *fname;	Oid			foid;	/* ----------------	 * Allocate the structure to hold the functions OID's	 * ----------------	 */	lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs));	if (lobjfuncs == (PGlobjfuncs *) NULL)	{		strcpy(conn->errorMessage,			   "FATAL: malloc() failed in lo_initialize()\n");		return -1;	}	MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));	/* ----------------	 * Execute the query to get all the functions at once	 * ----------------	 */	res = PQexec(conn, "select proname, oid from pg_proc	\    		where proname = 'lo_open'	\		   or proname = 'lo_close'	\		   or proname = 'lo_creat'	\		   or proname = 'lo_unlink'	\		   or proname = 'lo_lseek'	\		   or proname = 'lo_tell'	\		   or proname = 'loread'	\		   or proname = 'lowrite'");	if (res == (PGresult *) NULL)	{		free(lobjfuncs);		return -1;	}	if (res->resultStatus != PGRES_TUPLES_OK)	{		free(lobjfuncs);		PQclear(res);		strcpy(conn->errorMessage,			   "ERROR: SELECT didn't return data in lo_initialize()\n");		return -1;	}	/* ----------------	 * Examine the result and put the OID's into the struct	 * ----------------	 */	for (n = 0; n < PQntuples(res); n++)	{		fname = PQgetvalue(res, n, 0);		foid = (Oid) atoi(PQgetvalue(res, n, 1));		if (!strcmp(fname, "lo_open"))			lobjfuncs->fn_lo_open = foid;		else if (!strcmp(fname, "lo_close"))			lobjfuncs->fn_lo_close = foid;		else if (!strcmp(fname, "lo_creat"))			lobjfuncs->fn_lo_creat = foid;		else if (!strcmp(fname, "lo_unlink"))			lobjfuncs->fn_lo_unlink = foid;		else if (!strcmp(fname, "lo_lseek"))			lobjfuncs->fn_lo_lseek = foid;		else if (!strcmp(fname, "lo_tell"))			lobjfuncs->fn_lo_tell = foid;		else if (!strcmp(fname, "loread"))			lobjfuncs->fn_lo_read = foid;		else if (!strcmp(fname, "lowrite"))			lobjfuncs->fn_lo_write = foid;	}	PQclear(res);	/* ----------------	 * Finally check that we really got all large object	 * interface functions.	 * ----------------	 */	if (lobjfuncs->fn_lo_open == 0)	{		strcpy(conn->errorMessage,			   "ERROR: Cannot determine OID for function lo_open\n");		free(lobjfuncs);		return -1;	}	if (lobjfuncs->fn_lo_close == 0)	{		strcpy(conn->errorMessage,			   "ERROR: Cannot determine OID for function lo_close\n");		free(lobjfuncs);		return -1;	}	if (lobjfuncs->fn_lo_creat == 0)	{		strcpy(conn->errorMessage,			   "ERROR: Cannot determine OID for function lo_creat\n");		free(lobjfuncs);		return -1;	}	if (lobjfuncs->fn_lo_unlink == 0)	{		strcpy(conn->errorMessage,			   "ERROR: Cannot determine OID for function lo_unlink\n");		free(lobjfuncs);		return -1;	}	if (lobjfuncs->fn_lo_lseek == 0)	{		strcpy(conn->errorMessage,			   "ERROR: Cannot determine OID for function lo_lseek\n");		free(lobjfuncs);		return -1;	}	if (lobjfuncs->fn_lo_tell == 0)	{		strcpy(conn->errorMessage,			   "ERROR: Cannot determine OID for function lo_tell\n");		free(lobjfuncs);		return -1;	}	if (lobjfuncs->fn_lo_read == 0)	{		strcpy(conn->errorMessage,			   "ERROR: Cannot determine OID for function loread\n");		free(lobjfuncs);		return -1;	}	if (lobjfuncs->fn_lo_write == 0)	{		strcpy(conn->errorMessage,			   "ERROR: Cannot determine OID for function lowrite\n");		free(lobjfuncs);		return -1;	}	/* ----------------	 * Put the structure into the connection control	 * ----------------	 */	conn->lobjfuncs = lobjfuncs;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -