00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include <sys/param.h>
00018 #include <signal.h>
00019 #include <sys/file.h>
00020 #include <sys/stat.h>
00021 #include <sys/time.h>
00022 #include <fcntl.h>
00023 #include <unistd.h>
00024 #include <grp.h>
00025 #include <pwd.h>
00026 #include <netinet/in.h>
00027 #include <arpa/inet.h>
00028 #ifdef HAVE_UTIME_H
00029 #include <utime.h>
00030 #endif
00031
00032 #include "access/htup_details.h"
00033 #include "catalog/pg_authid.h"
00034 #include "mb/pg_wchar.h"
00035 #include "miscadmin.h"
00036 #include "postmaster/autovacuum.h"
00037 #include "postmaster/postmaster.h"
00038 #include "storage/fd.h"
00039 #include "storage/ipc.h"
00040 #include "storage/pg_shmem.h"
00041 #include "storage/proc.h"
00042 #include "storage/procarray.h"
00043 #include "utils/builtins.h"
00044 #include "utils/guc.h"
00045 #include "utils/memutils.h"
00046 #include "utils/syscache.h"
00047
00048
00049 #define DIRECTORY_LOCK_FILE "postmaster.pid"
00050
00051 ProcessingMode Mode = InitProcessing;
00052
00053
00054 static List *lock_files = NIL;
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 bool IgnoreSystemIndexes = false;
00068
00069
00070
00071
00072
00073
00074
00075 void
00076 SetDatabasePath(const char *path)
00077 {
00078
00079 Assert(!DatabasePath);
00080 DatabasePath = MemoryContextStrdup(TopMemoryContext, path);
00081 }
00082
00083
00084
00085
00086
00087 void
00088 SetDataDir(const char *dir)
00089 {
00090 char *new;
00091
00092 AssertArg(dir);
00093
00094
00095 new = make_absolute_path(dir);
00096
00097 if (DataDir)
00098 free(DataDir);
00099 DataDir = new;
00100 }
00101
00102
00103
00104
00105
00106
00107
00108 void
00109 ChangeToDataDir(void)
00110 {
00111 AssertState(DataDir);
00112
00113 if (chdir(DataDir) < 0)
00114 ereport(FATAL,
00115 (errcode_for_file_access(),
00116 errmsg("could not change directory to \"%s\": %m",
00117 DataDir)));
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 char *
00131 make_absolute_path(const char *path)
00132 {
00133 char *new;
00134
00135
00136 if (path == NULL)
00137 return NULL;
00138
00139 if (!is_absolute_path(path))
00140 {
00141 char *buf;
00142 size_t buflen;
00143
00144 buflen = MAXPGPATH;
00145 for (;;)
00146 {
00147 buf = malloc(buflen);
00148 if (!buf)
00149 ereport(FATAL,
00150 (errcode(ERRCODE_OUT_OF_MEMORY),
00151 errmsg("out of memory")));
00152
00153 if (getcwd(buf, buflen))
00154 break;
00155 else if (errno == ERANGE)
00156 {
00157 free(buf);
00158 buflen *= 2;
00159 continue;
00160 }
00161 else
00162 {
00163 free(buf);
00164 elog(FATAL, "could not get current working directory: %m");
00165 }
00166 }
00167
00168 new = malloc(strlen(buf) + strlen(path) + 2);
00169 if (!new)
00170 ereport(FATAL,
00171 (errcode(ERRCODE_OUT_OF_MEMORY),
00172 errmsg("out of memory")));
00173 sprintf(new, "%s/%s", buf, path);
00174 free(buf);
00175 }
00176 else
00177 {
00178 new = strdup(path);
00179 if (!new)
00180 ereport(FATAL,
00181 (errcode(ERRCODE_OUT_OF_MEMORY),
00182 errmsg("out of memory")));
00183 }
00184
00185
00186 canonicalize_path(new);
00187
00188 return new;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 static Oid AuthenticatedUserId = InvalidOid;
00221 static Oid SessionUserId = InvalidOid;
00222 static Oid OuterUserId = InvalidOid;
00223 static Oid CurrentUserId = InvalidOid;
00224
00225
00226 static bool AuthenticatedUserIsSuperuser = false;
00227 static bool SessionUserIsSuperuser = false;
00228
00229 static int SecurityRestrictionContext = 0;
00230
00231
00232 static bool SetRoleIsActive = false;
00233
00234
00235
00236
00237
00238
00239
00240 Oid
00241 GetUserId(void)
00242 {
00243 AssertState(OidIsValid(CurrentUserId));
00244 return CurrentUserId;
00245 }
00246
00247
00248
00249
00250
00251 Oid
00252 GetOuterUserId(void)
00253 {
00254 AssertState(OidIsValid(OuterUserId));
00255 return OuterUserId;
00256 }
00257
00258
00259 static void
00260 SetOuterUserId(Oid userid)
00261 {
00262 AssertState(SecurityRestrictionContext == 0);
00263 AssertArg(OidIsValid(userid));
00264 OuterUserId = userid;
00265
00266
00267 CurrentUserId = userid;
00268 }
00269
00270
00271
00272
00273
00274 Oid
00275 GetSessionUserId(void)
00276 {
00277 AssertState(OidIsValid(SessionUserId));
00278 return SessionUserId;
00279 }
00280
00281
00282 static void
00283 SetSessionUserId(Oid userid, bool is_superuser)
00284 {
00285 AssertState(SecurityRestrictionContext == 0);
00286 AssertArg(OidIsValid(userid));
00287 SessionUserId = userid;
00288 SessionUserIsSuperuser = is_superuser;
00289 SetRoleIsActive = false;
00290
00291
00292 OuterUserId = userid;
00293 CurrentUserId = userid;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 void
00329 GetUserIdAndSecContext(Oid *userid, int *sec_context)
00330 {
00331 *userid = CurrentUserId;
00332 *sec_context = SecurityRestrictionContext;
00333 }
00334
00335 void
00336 SetUserIdAndSecContext(Oid userid, int sec_context)
00337 {
00338 CurrentUserId = userid;
00339 SecurityRestrictionContext = sec_context;
00340 }
00341
00342
00343
00344
00345
00346 bool
00347 InLocalUserIdChange(void)
00348 {
00349 return (SecurityRestrictionContext & SECURITY_LOCAL_USERID_CHANGE) != 0;
00350 }
00351
00352
00353
00354
00355 bool
00356 InSecurityRestrictedOperation(void)
00357 {
00358 return (SecurityRestrictionContext & SECURITY_RESTRICTED_OPERATION) != 0;
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368 void
00369 GetUserIdAndContext(Oid *userid, bool *sec_def_context)
00370 {
00371 *userid = CurrentUserId;
00372 *sec_def_context = InLocalUserIdChange();
00373 }
00374
00375 void
00376 SetUserIdAndContext(Oid userid, bool sec_def_context)
00377 {
00378
00379 if (InSecurityRestrictedOperation())
00380 ereport(ERROR,
00381 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00382 errmsg("cannot set parameter \"%s\" within security-restricted operation",
00383 "role")));
00384 CurrentUserId = userid;
00385 if (sec_def_context)
00386 SecurityRestrictionContext |= SECURITY_LOCAL_USERID_CHANGE;
00387 else
00388 SecurityRestrictionContext &= ~SECURITY_LOCAL_USERID_CHANGE;
00389 }
00390
00391
00392
00393
00394
00395 bool
00396 has_rolreplication(Oid roleid)
00397 {
00398 bool result = false;
00399 HeapTuple utup;
00400
00401 utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
00402 if (HeapTupleIsValid(utup))
00403 {
00404 result = ((Form_pg_authid) GETSTRUCT(utup))->rolreplication;
00405 ReleaseSysCache(utup);
00406 }
00407 return result;
00408 }
00409
00410
00411
00412
00413 void
00414 InitializeSessionUserId(const char *rolename)
00415 {
00416 HeapTuple roleTup;
00417 Form_pg_authid rform;
00418 Oid roleid;
00419
00420
00421
00422
00423
00424 AssertState(!IsBootstrapProcessingMode());
00425
00426
00427 AssertState(!OidIsValid(AuthenticatedUserId));
00428
00429 roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename));
00430 if (!HeapTupleIsValid(roleTup))
00431 ereport(FATAL,
00432 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00433 errmsg("role \"%s\" does not exist", rolename)));
00434
00435 rform = (Form_pg_authid) GETSTRUCT(roleTup);
00436 roleid = HeapTupleGetOid(roleTup);
00437
00438 AuthenticatedUserId = roleid;
00439 AuthenticatedUserIsSuperuser = rform->rolsuper;
00440
00441
00442 SetSessionUserId(roleid, AuthenticatedUserIsSuperuser);
00443
00444
00445
00446 MyProc->roleId = roleid;
00447
00448
00449
00450
00451
00452
00453 if (IsUnderPostmaster)
00454 {
00455
00456
00457
00458 if (!rform->rolcanlogin)
00459 ereport(FATAL,
00460 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
00461 errmsg("role \"%s\" is not permitted to log in",
00462 rolename)));
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 if (rform->rolconnlimit >= 0 &&
00475 !AuthenticatedUserIsSuperuser &&
00476 CountUserBackends(roleid) > rform->rolconnlimit)
00477 ereport(FATAL,
00478 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
00479 errmsg("too many connections for role \"%s\"",
00480 rolename)));
00481 }
00482
00483
00484 SetConfigOption("session_authorization", rolename,
00485 PGC_BACKEND, PGC_S_OVERRIDE);
00486 SetConfigOption("is_superuser",
00487 AuthenticatedUserIsSuperuser ? "on" : "off",
00488 PGC_INTERNAL, PGC_S_OVERRIDE);
00489
00490 ReleaseSysCache(roleTup);
00491 }
00492
00493
00494
00495
00496
00497 void
00498 InitializeSessionUserIdStandalone(void)
00499 {
00500
00501
00502
00503
00504 AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess() || IsBackgroundWorker);
00505
00506
00507 AssertState(!OidIsValid(AuthenticatedUserId));
00508
00509 AuthenticatedUserId = BOOTSTRAP_SUPERUSERID;
00510 AuthenticatedUserIsSuperuser = true;
00511
00512 SetSessionUserId(BOOTSTRAP_SUPERUSERID, true);
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 void
00530 SetSessionAuthorization(Oid userid, bool is_superuser)
00531 {
00532
00533 AssertState(OidIsValid(AuthenticatedUserId));
00534
00535 if (userid != AuthenticatedUserId &&
00536 !AuthenticatedUserIsSuperuser)
00537 ereport(ERROR,
00538 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00539 errmsg("permission denied to set session authorization")));
00540
00541 SetSessionUserId(userid, is_superuser);
00542
00543 SetConfigOption("is_superuser",
00544 is_superuser ? "on" : "off",
00545 PGC_INTERNAL, PGC_S_OVERRIDE);
00546 }
00547
00548
00549
00550
00551
00552
00553
00554 Oid
00555 GetCurrentRoleId(void)
00556 {
00557 if (SetRoleIsActive)
00558 return OuterUserId;
00559 else
00560 return InvalidOid;
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 void
00576 SetCurrentRoleId(Oid roleid, bool is_superuser)
00577 {
00578
00579
00580
00581
00582
00583
00584
00585 if (!OidIsValid(roleid))
00586 {
00587 if (!OidIsValid(SessionUserId))
00588 return;
00589
00590 roleid = SessionUserId;
00591 is_superuser = SessionUserIsSuperuser;
00592
00593 SetRoleIsActive = false;
00594 }
00595 else
00596 SetRoleIsActive = true;
00597
00598 SetOuterUserId(roleid);
00599
00600 SetConfigOption("is_superuser",
00601 is_superuser ? "on" : "off",
00602 PGC_INTERNAL, PGC_S_OVERRIDE);
00603 }
00604
00605
00606
00607
00608
00609 char *
00610 GetUserNameFromId(Oid roleid)
00611 {
00612 HeapTuple tuple;
00613 char *result;
00614
00615 tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
00616 if (!HeapTupleIsValid(tuple))
00617 ereport(ERROR,
00618 (errcode(ERRCODE_UNDEFINED_OBJECT),
00619 errmsg("invalid role OID: %u", roleid)));
00620
00621 result = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
00622
00623 ReleaseSysCache(tuple);
00624 return result;
00625 }
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646 static void
00647 UnlinkLockFiles(int status, Datum arg)
00648 {
00649 ListCell *l;
00650
00651 foreach(l, lock_files)
00652 {
00653 char *curfile = (char *) lfirst(l);
00654
00655 unlink(curfile);
00656
00657 }
00658
00659 lock_files = NIL;
00660 }
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 static void
00671 CreateLockFile(const char *filename, bool amPostmaster,
00672 const char *socketDir,
00673 bool isDDLock, const char *refName)
00674 {
00675 int fd;
00676 char buffer[MAXPGPATH * 2 + 256];
00677 int ntries;
00678 int len;
00679 int encoded_pid;
00680 pid_t other_pid;
00681 pid_t my_pid,
00682 my_p_pid,
00683 my_gp_pid;
00684 const char *envvar;
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 my_pid = getpid();
00705
00706 #ifndef WIN32
00707 my_p_pid = getppid();
00708 #else
00709
00710
00711
00712
00713
00714 my_p_pid = 0;
00715 #endif
00716
00717 envvar = getenv("PG_GRANDPARENT_PID");
00718 if (envvar)
00719 my_gp_pid = atoi(envvar);
00720 else
00721 my_gp_pid = 0;
00722
00723
00724
00725
00726
00727
00728 for (ntries = 0;; ntries++)
00729 {
00730
00731
00732
00733
00734
00735
00736 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
00737 if (fd >= 0)
00738 break;
00739
00740
00741
00742
00743 if ((errno != EEXIST && errno != EACCES) || ntries > 100)
00744 ereport(FATAL,
00745 (errcode_for_file_access(),
00746 errmsg("could not create lock file \"%s\": %m",
00747 filename)));
00748
00749
00750
00751
00752
00753 fd = open(filename, O_RDONLY, 0600);
00754 if (fd < 0)
00755 {
00756 if (errno == ENOENT)
00757 continue;
00758 ereport(FATAL,
00759 (errcode_for_file_access(),
00760 errmsg("could not open lock file \"%s\": %m",
00761 filename)));
00762 }
00763 if ((len = read(fd, buffer, sizeof(buffer) - 1)) < 0)
00764 ereport(FATAL,
00765 (errcode_for_file_access(),
00766 errmsg("could not read lock file \"%s\": %m",
00767 filename)));
00768 close(fd);
00769
00770 if (len == 0)
00771 {
00772 ereport(FATAL,
00773 (errcode(ERRCODE_LOCK_FILE_EXISTS),
00774 errmsg("lock file \"%s\" is empty", filename),
00775 errhint("Either another server is starting, or the lock file is the remnant of a previous server startup crash.")));
00776 }
00777
00778 buffer[len] = '\0';
00779 encoded_pid = atoi(buffer);
00780
00781
00782 other_pid = (pid_t) (encoded_pid < 0 ? -encoded_pid : encoded_pid);
00783
00784 if (other_pid <= 0)
00785 elog(FATAL, "bogus data in lock file \"%s\": \"%s\"",
00786 filename, buffer);
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813 if (other_pid != my_pid && other_pid != my_p_pid &&
00814 other_pid != my_gp_pid)
00815 {
00816 if (kill(other_pid, 0) == 0 ||
00817 (errno != ESRCH && errno != EPERM))
00818 {
00819
00820 ereport(FATAL,
00821 (errcode(ERRCODE_LOCK_FILE_EXISTS),
00822 errmsg("lock file \"%s\" already exists",
00823 filename),
00824 isDDLock ?
00825 (encoded_pid < 0 ?
00826 errhint("Is another postgres (PID %d) running in data directory \"%s\"?",
00827 (int) other_pid, refName) :
00828 errhint("Is another postmaster (PID %d) running in data directory \"%s\"?",
00829 (int) other_pid, refName)) :
00830 (encoded_pid < 0 ?
00831 errhint("Is another postgres (PID %d) using socket file \"%s\"?",
00832 (int) other_pid, refName) :
00833 errhint("Is another postmaster (PID %d) using socket file \"%s\"?",
00834 (int) other_pid, refName))));
00835 }
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 if (isDDLock)
00850 {
00851 char *ptr = buffer;
00852 unsigned long id1,
00853 id2;
00854 int lineno;
00855
00856 for (lineno = 1; lineno < LOCK_FILE_LINE_SHMEM_KEY; lineno++)
00857 {
00858 if ((ptr = strchr(ptr, '\n')) == NULL)
00859 break;
00860 ptr++;
00861 }
00862
00863 if (ptr != NULL &&
00864 sscanf(ptr, "%lu %lu", &id1, &id2) == 2)
00865 {
00866 if (PGSharedMemoryIsInUse(id1, id2))
00867 ereport(FATAL,
00868 (errcode(ERRCODE_LOCK_FILE_EXISTS),
00869 errmsg("pre-existing shared memory block "
00870 "(key %lu, ID %lu) is still in use",
00871 id1, id2),
00872 errhint("If you're sure there are no old "
00873 "server processes still running, remove "
00874 "the shared memory block "
00875 "or just delete the file \"%s\".",
00876 filename)));
00877 }
00878 }
00879
00880
00881
00882
00883
00884
00885 if (unlink(filename) < 0)
00886 ereport(FATAL,
00887 (errcode_for_file_access(),
00888 errmsg("could not remove old lock file \"%s\": %m",
00889 filename),
00890 errhint("The file seems accidentally left over, but "
00891 "it could not be removed. Please remove the file "
00892 "by hand and try again.")));
00893 }
00894
00895
00896
00897
00898
00899
00900
00901 snprintf(buffer, sizeof(buffer), "%d\n%s\n%ld\n%d\n%s\n",
00902 amPostmaster ? (int) my_pid : -((int) my_pid),
00903 DataDir,
00904 (long) MyStartTime,
00905 PostPortNumber,
00906 socketDir);
00907
00908
00909
00910
00911
00912 if (isDDLock && !amPostmaster)
00913 strlcat(buffer, "\n", sizeof(buffer));
00914
00915 errno = 0;
00916 if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
00917 {
00918 int save_errno = errno;
00919
00920 close(fd);
00921 unlink(filename);
00922
00923 errno = save_errno ? save_errno : ENOSPC;
00924 ereport(FATAL,
00925 (errcode_for_file_access(),
00926 errmsg("could not write lock file \"%s\": %m", filename)));
00927 }
00928 if (pg_fsync(fd) != 0)
00929 {
00930 int save_errno = errno;
00931
00932 close(fd);
00933 unlink(filename);
00934 errno = save_errno;
00935 ereport(FATAL,
00936 (errcode_for_file_access(),
00937 errmsg("could not write lock file \"%s\": %m", filename)));
00938 }
00939 if (close(fd) != 0)
00940 {
00941 int save_errno = errno;
00942
00943 unlink(filename);
00944 errno = save_errno;
00945 ereport(FATAL,
00946 (errcode_for_file_access(),
00947 errmsg("could not write lock file \"%s\": %m", filename)));
00948 }
00949
00950
00951
00952
00953
00954
00955 if (lock_files == NIL)
00956 on_proc_exit(UnlinkLockFiles, 0);
00957
00958 lock_files = lappend(lock_files, pstrdup(filename));
00959 }
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 void
00972 CreateDataDirLockFile(bool amPostmaster)
00973 {
00974 CreateLockFile(DIRECTORY_LOCK_FILE, amPostmaster, "", true, DataDir);
00975 }
00976
00977
00978
00979
00980 void
00981 CreateSocketLockFile(const char *socketfile, bool amPostmaster,
00982 const char *socketDir)
00983 {
00984 char lockfile[MAXPGPATH];
00985
00986 snprintf(lockfile, sizeof(lockfile), "%s.lock", socketfile);
00987 CreateLockFile(lockfile, amPostmaster, socketDir, false, socketfile);
00988 }
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998 void
00999 TouchSocketLockFiles(void)
01000 {
01001 ListCell *l;
01002
01003 foreach(l, lock_files)
01004 {
01005 char *socketLockFile = (char *) lfirst(l);
01006
01007
01008 if (strcmp(socketLockFile, DIRECTORY_LOCK_FILE) == 0)
01009 continue;
01010
01011
01012
01013
01014
01015
01016
01017 #ifdef HAVE_UTIME
01018 utime(socketLockFile, NULL);
01019 #else
01020 #ifdef HAVE_UTIMES
01021 utimes(socketLockFile, NULL);
01022 #else
01023 int fd;
01024 char buffer[1];
01025
01026 fd = open(socketLockFile, O_RDONLY | PG_BINARY, 0);
01027 if (fd >= 0)
01028 {
01029 read(fd, buffer, sizeof(buffer));
01030 close(fd);
01031 }
01032 #endif
01033 #endif
01034 }
01035 }
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047 void
01048 AddToDataDirLockFile(int target_line, const char *str)
01049 {
01050 int fd;
01051 int len;
01052 int lineno;
01053 char *srcptr;
01054 char *destptr;
01055 char srcbuffer[BLCKSZ];
01056 char destbuffer[BLCKSZ];
01057
01058 fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
01059 if (fd < 0)
01060 {
01061 ereport(LOG,
01062 (errcode_for_file_access(),
01063 errmsg("could not open file \"%s\": %m",
01064 DIRECTORY_LOCK_FILE)));
01065 return;
01066 }
01067 len = read(fd, srcbuffer, sizeof(srcbuffer) - 1);
01068 if (len < 0)
01069 {
01070 ereport(LOG,
01071 (errcode_for_file_access(),
01072 errmsg("could not read from file \"%s\": %m",
01073 DIRECTORY_LOCK_FILE)));
01074 close(fd);
01075 return;
01076 }
01077 srcbuffer[len] = '\0';
01078
01079
01080
01081
01082
01083 srcptr = srcbuffer;
01084 for (lineno = 1; lineno < target_line; lineno++)
01085 {
01086 if ((srcptr = strchr(srcptr, '\n')) == NULL)
01087 {
01088 elog(LOG, "incomplete data in \"%s\": found only %d newlines while trying to add line %d",
01089 DIRECTORY_LOCK_FILE, lineno - 1, target_line);
01090 close(fd);
01091 return;
01092 }
01093 srcptr++;
01094 }
01095 memcpy(destbuffer, srcbuffer, srcptr - srcbuffer);
01096 destptr = destbuffer + (srcptr - srcbuffer);
01097
01098
01099
01100
01101 snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s\n", str);
01102 destptr += strlen(destptr);
01103
01104
01105
01106
01107 if ((srcptr = strchr(srcptr, '\n')) != NULL)
01108 {
01109 srcptr++;
01110 snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s",
01111 srcptr);
01112 }
01113
01114
01115
01116
01117
01118 len = strlen(destbuffer);
01119 errno = 0;
01120 if (lseek(fd, (off_t) 0, SEEK_SET) != 0 ||
01121 (int) write(fd, destbuffer, len) != len)
01122 {
01123
01124 if (errno == 0)
01125 errno = ENOSPC;
01126 ereport(LOG,
01127 (errcode_for_file_access(),
01128 errmsg("could not write to file \"%s\": %m",
01129 DIRECTORY_LOCK_FILE)));
01130 close(fd);
01131 return;
01132 }
01133 if (pg_fsync(fd) != 0)
01134 {
01135 ereport(LOG,
01136 (errcode_for_file_access(),
01137 errmsg("could not write to file \"%s\": %m",
01138 DIRECTORY_LOCK_FILE)));
01139 }
01140 if (close(fd) != 0)
01141 {
01142 ereport(LOG,
01143 (errcode_for_file_access(),
01144 errmsg("could not write to file \"%s\": %m",
01145 DIRECTORY_LOCK_FILE)));
01146 }
01147 }
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161 void
01162 ValidatePgVersion(const char *path)
01163 {
01164 char full_path[MAXPGPATH];
01165 FILE *file;
01166 int ret;
01167 long file_major,
01168 file_minor;
01169 long my_major = 0,
01170 my_minor = 0;
01171 char *endptr;
01172 const char *version_string = PG_VERSION;
01173
01174 my_major = strtol(version_string, &endptr, 10);
01175 if (*endptr == '.')
01176 my_minor = strtol(endptr + 1, NULL, 10);
01177
01178 snprintf(full_path, sizeof(full_path), "%s/PG_VERSION", path);
01179
01180 file = AllocateFile(full_path, "r");
01181 if (!file)
01182 {
01183 if (errno == ENOENT)
01184 ereport(FATAL,
01185 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01186 errmsg("\"%s\" is not a valid data directory",
01187 path),
01188 errdetail("File \"%s\" is missing.", full_path)));
01189 else
01190 ereport(FATAL,
01191 (errcode_for_file_access(),
01192 errmsg("could not open file \"%s\": %m", full_path)));
01193 }
01194
01195 ret = fscanf(file, "%ld.%ld", &file_major, &file_minor);
01196 if (ret != 2)
01197 ereport(FATAL,
01198 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01199 errmsg("\"%s\" is not a valid data directory",
01200 path),
01201 errdetail("File \"%s\" does not contain valid data.",
01202 full_path),
01203 errhint("You might need to initdb.")));
01204
01205 FreeFile(file);
01206
01207 if (my_major != file_major || my_minor != file_minor)
01208 ereport(FATAL,
01209 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01210 errmsg("database files are incompatible with server"),
01211 errdetail("The data directory was initialized by PostgreSQL version %ld.%ld, "
01212 "which is not compatible with this version %s.",
01213 file_major, file_minor, version_string)));
01214 }
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 char *shared_preload_libraries_string = NULL;
01226 char *local_preload_libraries_string = NULL;
01227
01228
01229 bool process_shared_preload_libraries_in_progress = false;
01230
01231
01232
01233
01234
01235
01236
01237 static void
01238 load_libraries(const char *libraries, const char *gucname, bool restricted)
01239 {
01240 char *rawstring;
01241 List *elemlist;
01242 int elevel;
01243 ListCell *l;
01244
01245 if (libraries == NULL || libraries[0] == '\0')
01246 return;
01247
01248
01249 rawstring = pstrdup(libraries);
01250
01251
01252 if (!SplitIdentifierString(rawstring, ',', &elemlist))
01253 {
01254
01255 pfree(rawstring);
01256 list_free(elemlist);
01257 ereport(LOG,
01258 (errcode(ERRCODE_SYNTAX_ERROR),
01259 errmsg("invalid list syntax in parameter \"%s\"",
01260 gucname)));
01261 return;
01262 }
01263
01264
01265
01266
01267
01268
01269 #ifdef EXEC_BACKEND
01270 if (IsUnderPostmaster && process_shared_preload_libraries_in_progress)
01271 elevel = DEBUG2;
01272 else
01273 #endif
01274 elevel = LOG;
01275
01276 foreach(l, elemlist)
01277 {
01278 char *tok = (char *) lfirst(l);
01279 char *filename;
01280
01281 filename = pstrdup(tok);
01282 canonicalize_path(filename);
01283
01284 if (restricted && first_dir_separator(filename) == NULL)
01285 {
01286 char *expanded;
01287
01288 expanded = palloc(strlen("$libdir/plugins/") + strlen(filename) + 1);
01289 strcpy(expanded, "$libdir/plugins/");
01290 strcat(expanded, filename);
01291 pfree(filename);
01292 filename = expanded;
01293 }
01294 load_file(filename, restricted);
01295 ereport(elevel,
01296 (errmsg("loaded library \"%s\"", filename)));
01297 pfree(filename);
01298 }
01299
01300 pfree(rawstring);
01301 list_free(elemlist);
01302 }
01303
01304
01305
01306
01307 void
01308 process_shared_preload_libraries(void)
01309 {
01310 process_shared_preload_libraries_in_progress = true;
01311 load_libraries(shared_preload_libraries_string,
01312 "shared_preload_libraries",
01313 false);
01314 process_shared_preload_libraries_in_progress = false;
01315 }
01316
01317
01318
01319
01320 void
01321 process_local_preload_libraries(void)
01322 {
01323 load_libraries(local_preload_libraries_string,
01324 "local_preload_libraries",
01325 true);
01326 }
01327
01328 void
01329 pg_bindtextdomain(const char *domain)
01330 {
01331 #ifdef ENABLE_NLS
01332 if (my_exec_path[0] != '\0')
01333 {
01334 char locale_path[MAXPGPATH];
01335
01336 get_locale_path(my_exec_path, locale_path);
01337 bindtextdomain(domain, locale_path);
01338 pg_bind_textdomain_codeset(domain);
01339 }
01340 #endif
01341 }