|
| 1 | +/*------------------------------------------------------------------------- |
| 2 | + * |
| 3 | + * version.c-- |
| 4 | + * Routines to handle Postgres version number. |
| 5 | + * |
| 6 | + * Copyright (c) 1994, Regents of the University of California |
| 7 | + * |
| 8 | + * |
| 9 | + * IDENTIFICATION |
| 10 | + * $Header: /cvsroot/pgsql/src/utils/Attic/version.c,v 1.1 1996/11/11 13:51:57 bryanh Exp $ |
| 11 | + * |
| 12 | + * NOTES |
| 13 | + *XXX eventually, should be able to handle version identifiers |
| 14 | + *of length != 4. |
| 15 | + * |
| 16 | + * STANDALONE CODE - do not use error routines as this code is linked with |
| 17 | + * stuff that does not cinterface.a |
| 18 | + *------------------------------------------------------------------------- |
| 19 | + */ |
| 20 | +#include<sys/file.h> |
| 21 | +#include<sys/types.h> |
| 22 | +#include<sys/stat.h> |
| 23 | +#include<ctype.h> |
| 24 | +#include<string.h> |
| 25 | +#include<stdio.h> |
| 26 | +#include<unistd.h> |
| 27 | + |
| 28 | +#include"postgres.h" |
| 29 | + |
| 30 | +#include"storage/fd.h"/* for O_ */ |
| 31 | + |
| 32 | +#include"version.h" |
| 33 | + |
| 34 | + |
| 35 | +staticvoid |
| 36 | +PathSetVersionFilePath(constchar*path,char*filepathbuf) { |
| 37 | +/*---------------------------------------------------------------------------- |
| 38 | + PathSetVersionFilePath |
| 39 | +
|
| 40 | + Destructively change "filepathbuf" to contain the concatenation of "path" |
| 41 | + and the name of the version file name. |
| 42 | +----------------------------------------------------------------------------*/ |
| 43 | +if (strlen(path)> (MAXPGPATH-sizeof(PG_VERFILE)-1)) |
| 44 | +*filepathbuf='\0'; |
| 45 | +else |
| 46 | +sprintf(filepathbuf,"%s%c%s",path,SEP_CHAR,PG_VERFILE); |
| 47 | +} |
| 48 | + |
| 49 | + |
| 50 | + |
| 51 | +void |
| 52 | +ValidatePgVersion(constchar*path,char**reason_p) { |
| 53 | +/*---------------------------------------------------------------------------- |
| 54 | + Determine whether the PG_VERSION file in directory <path> indicates |
| 55 | + a data version compatible with the version of this program. |
| 56 | +
|
| 57 | + If compatible, return <*reason_p> == NULL. Otherwise, malloc space, |
| 58 | + fill it with a text string explaining how it isn't compatible (or why |
| 59 | + we can't tell), and return a pointer to that space as <*reason_p>. |
| 60 | +-----------------------------------------------------------------------------*/ |
| 61 | +intfd; |
| 62 | +charversion[4]; |
| 63 | +charfull_path[MAXPGPATH+1]; |
| 64 | +#ifndefWIN32 |
| 65 | +structstatstatbuf; |
| 66 | +#else |
| 67 | +struct_statstatbuf; |
| 68 | +#endif |
| 69 | +PathSetVersionFilePath(path,full_path); |
| 70 | + |
| 71 | +if (stat(full_path,&statbuf)<0) { |
| 72 | +*reason_p=malloc(200); |
| 73 | +sprintf(*reason_p,"File '%s' does not exist.",full_path); |
| 74 | + }else { |
| 75 | +fd=open(full_path,O_RDONLY,0); |
| 76 | +if (fd<0) { |
| 77 | +*reason_p=malloc(200); |
| 78 | +sprintf(*reason_p,"Unable to open file '%s'. Errno = %s (%d).", |
| 79 | +full_path,strerror(errno),errno); |
| 80 | + }else { |
| 81 | +if (read(fd,version,4)<4|| |
| 82 | + !isascii(version[0])|| !isdigit(version[0])|| |
| 83 | +version[1]!='.'|| |
| 84 | + !isascii(version[2])|| !isdigit(version[2])|| |
| 85 | +version[3]!='\n') { |
| 86 | + |
| 87 | +*reason_p=malloc(200); |
| 88 | +sprintf(*reason_p,"File '%s' does not have a valid format " |
| 89 | +"for a PG_VERSION file.",full_path); |
| 90 | + }else { |
| 91 | +if (version[2]!='0'+PG_VERSION|| |
| 92 | +version[0]!='0'+PG_RELEASE) { |
| 93 | +*reason_p=malloc(200); |
| 94 | +sprintf(*reason_p, |
| 95 | +"Version number in file '%s' should be %d.%d, " |
| 96 | +"not %c.%c.", |
| 97 | +full_path, |
| 98 | +PG_RELEASE,PG_VERSION,version[0],version[2]); |
| 99 | + }else*reason_p=NULL; |
| 100 | + } |
| 101 | +close(fd); |
| 102 | + } |
| 103 | + } |
| 104 | +} |
| 105 | + |
| 106 | + |
| 107 | + |
| 108 | +void |
| 109 | +SetPgVersion(constchar*path,char**reason_p) { |
| 110 | +/*--------------------------------------------------------------------------- |
| 111 | + Create the PG_VERSION file in the directory <path>. |
| 112 | +
|
| 113 | + If we fail, allocate storage, fill it with a text string explaining why, |
| 114 | + and return a pointer to that storage as <*reason_p>. If we succeed, |
| 115 | + return *reason_p = NULL. |
| 116 | +---------------------------------------------------------------------------*/ |
| 117 | +intfd; |
| 118 | +charversion[4]; |
| 119 | +charfull_path[MAXPGPATH+1]; |
| 120 | + |
| 121 | +PathSetVersionFilePath(path,full_path); |
| 122 | + |
| 123 | +fd=open(full_path,O_WRONLY|O_CREAT|O_EXCL,0666); |
| 124 | +if (fd<0) { |
| 125 | +*reason_p=malloc(100+strlen(full_path)); |
| 126 | +sprintf(*reason_p, |
| 127 | +"Unable to create file '%s', errno from open(): %s (%d).", |
| 128 | +full_path,strerror(errno),errno); |
| 129 | + }else { |
| 130 | +intrc;/* return code from some function we call */ |
| 131 | + |
| 132 | +version[0]='0'+PG_RELEASE; |
| 133 | +version[1]='.'; |
| 134 | +version[2]='0'+PG_VERSION; |
| 135 | +version[3]='\n'; |
| 136 | +rc=write(fd,version,4); |
| 137 | +if (rc!=4) { |
| 138 | +*reason_p=malloc(100+strlen(full_path)); |
| 139 | +sprintf(*reason_p, |
| 140 | +"Failed to write to file '%s', after it was already " |
| 141 | +"open. Errno from write(): %s (%d)", |
| 142 | +full_path,strerror(errno),errno); |
| 143 | + }else*reason_p=NULL; |
| 144 | +close(fd); |
| 145 | + } |
| 146 | +} |