version.c 4.09 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * version.c
4
 *	  Routines to handle Postgres version number.
5
 *
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
6 7
 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $Header: /cvsroot/pgsql/src/utils/Attic/version.c,v 1.16 2000/06/02 15:57:44 momjian Exp $
12
 *
13 14
 *	STANDALONE CODE - do not use error routines as this code is not linked
 *	with any...
15 16
 *-------------------------------------------------------------------------
 */
17
#include <sys/types.h>
18
#include <sys/file.h>
19
#include <fcntl.h>				/* For open() flags */
20 21 22
#include <sys/stat.h>
#include <ctype.h>
#include <unistd.h>
23
#include <errno.h>
24 25 26

#include "postgres.h"

27
#include "storage/fd.h"			/* for O_ */
28

29
#include "version.h"
30 31 32


static void
33 34
PathSetVersionFilePath(const char *path, char *filepathbuf)
{
35 36
/*----------------------------------------------------------------------------
  PathSetVersionFilePath
37

38 39 40
  Destructively change "filepathbuf" to contain the concatenation of "path"
  and the name of the version file name.
----------------------------------------------------------------------------*/
41
	if ((strlen(path) + 1 + strlen(PG_VERFILE)) >= MAXPGPATH)
42 43 44
		*filepathbuf = '\0';
	else
		sprintf(filepathbuf, "%s%c%s", path, SEP_CHAR, PG_VERFILE);
45 46 47 48 49
}



void
50 51
ValidatePgVersion(const char *path, char **reason_p)
{
52
/*----------------------------------------------------------------------------
53 54 55 56 57 58
	Determine whether the PG_VERSION file in directory <path> indicates
	a data version compatible with the version of this program.

	If compatible, return <*reason_p> == NULL.	Otherwise, malloc space,
	fill it with a text string explaining how it isn't compatible (or why
	we can't tell), and return a pointer to that space as <*reason_p>.
59
-----------------------------------------------------------------------------*/
60
	int			fd;
61 62 63 64
	int			nread;
	char		myversion[32];
	char		version[32];
	char		full_path[MAXPGPATH];
65 66 67

	PathSetVersionFilePath(path, full_path);

68 69
	sprintf(myversion, "%s.%s\n", PG_RELEASE, PG_VERSION);

70
	if ((fd = open(full_path, O_RDONLY | PG_BINARY, 0)) == -1)
71
	{
72
		*reason_p = malloc(100 + strlen(full_path));
73 74 75 76
		sprintf(*reason_p, "File '%s' does not exist or no read permission.", full_path);
	}
	else
	{
77
		nread = read(fd, version, sizeof(version) - 1);
78 79
		if (nread < 4 ||
			!isdigit(version[0]) ||
80
			version[nread - 1] != '\n')
81
		{
82
			*reason_p = malloc(100 + strlen(full_path));
83 84 85 86 87
			sprintf(*reason_p, "File '%s' does not have a valid format "
					"for a PG_VERSION file.", full_path);
		}
		else
		{
88 89
			version[nread] = '\0';
			if (strcmp(version, myversion) != 0)
90
			{
91
				*reason_p = malloc(200 + strlen(full_path));
92
				sprintf(*reason_p,
93 94 95
						"Version number in file '%s' should be %s, "
						"not %s.",
						full_path, myversion, version);
96 97 98 99 100 101
			}
			else
				*reason_p = NULL;
		}
		close(fd);
	}
102 103 104 105 106
}



void
107 108
SetPgVersion(const char *path, char **reason_p)
{
109 110
/*---------------------------------------------------------------------------
  Create the PG_VERSION file in the directory <path>.
111

112
  If we fail, allocate storage, fill it with a text string explaining why,
113
  and return a pointer to that storage as <*reason_p>.	If we succeed,
114 115
  return *reason_p = NULL.
---------------------------------------------------------------------------*/
116
	int			fd;
117 118
	char		version[32];
	char		full_path[MAXPGPATH];
119 120 121

	PathSetVersionFilePath(path, full_path);

122 123
	sprintf(version, "%s.%s\n", PG_RELEASE, PG_VERSION);

124
	fd = open(full_path, O_WRONLY | O_CREAT | O_EXCL | PG_BINARY, 0666);
125 126 127 128 129 130 131 132 133
	if (fd < 0)
	{
		*reason_p = malloc(100 + strlen(full_path));
		sprintf(*reason_p,
				"Unable to create file '%s', errno from open(): %s (%d).",
				full_path, strerror(errno), errno);
	}
	else
	{
134
		int			rc;			/* return code from some function we call */
135

136 137
		rc = write(fd, version, strlen(version));
		if (rc != strlen(version))
138 139 140 141 142 143 144 145 146 147 148
		{
			*reason_p = malloc(100 + strlen(full_path));
			sprintf(*reason_p,
					"Failed to write to file '%s', after it was already "
					"open.  Errno from write(): %s (%d)",
					full_path, strerror(errno), errno);
		}
		else
			*reason_p = NULL;
		close(fd);
	}
149
}