Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
e95703ea
Commit
e95703ea
authored
May 30, 2006
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Un-DOS-ify newly added files.
parent
e60cb3a3
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
448 additions
and
446 deletions
+448
-446
contrib/adminpack/Makefile
contrib/adminpack/Makefile
+15
-15
contrib/adminpack/adminpack.c
contrib/adminpack/adminpack.c
+392
-390
contrib/adminpack/adminpack.sql.in
contrib/adminpack/adminpack.sql.in
+41
-41
No files found.
contrib/adminpack/Makefile
View file @
e95703ea
MODULE_big
=
adminpack
PG_CPPFLAGS
=
-I
$(libpq_srcdir)
DATA_built
=
adminpack.sql
DOCS
=
README.adminpack
OBJS
=
adminpack.o
ifdef
USE_PGXS
PGXS
:=
$(
shell
pg_config
--pgxs
)
include
$(PGXS)
else
subdir
=
contrib/adminpack
top_builddir
=
../..
include
$(top_builddir)/src/Makefile.global
include
$(top_srcdir)/contrib/contrib-global.mk
endif
MODULE_big
=
adminpack
PG_CPPFLAGS
=
-I
$(libpq_srcdir)
DATA_built
=
adminpack.sql
DOCS
=
README.adminpack
OBJS
=
adminpack.o
ifdef
USE_PGXS
PGXS
:=
$(
shell
pg_config
--pgxs
)
include
$(PGXS)
else
subdir
=
contrib/adminpack
top_builddir
=
../..
include
$(top_builddir)/src/Makefile.global
include
$(top_srcdir)/contrib/contrib-global.mk
endif
contrib/adminpack/adminpack.c
View file @
e95703ea
/*-------------------------------------------------------------------------
*
* admin81.c
*
*
* Copyright (c) 2002 - 2006, PostgreSQL Global Development Group
*
* Author: Andreas Pflug <pgadmin@pse-consulting.de>
*
* IDENTIFICATION
* $PostgreSQL: pgsql/contrib/adminpack/adminpack.c,v 1.1 2006/05/30 12:07:31 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "miscadmin.h"
#include "storage/fd.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "utils/datetime.h"
#ifdef WIN32
#ifdef rename
#undef rename
#endif
#ifdef unlink
#undef unlink
#endif
#endif
extern
DLLIMPORT
char
*
DataDir
;
extern
DLLIMPORT
char
*
Log_directory
;
extern
DLLIMPORT
char
*
Log_filename
;
Datum
pg_file_write
(
PG_FUNCTION_ARGS
);
Datum
pg_file_rename
(
PG_FUNCTION_ARGS
);
Datum
pg_file_unlink
(
PG_FUNCTION_ARGS
);
Datum
pg_logdir_ls
(
PG_FUNCTION_ARGS
);
PG_FUNCTION_INFO_V1
(
pg_file_write
);
PG_FUNCTION_INFO_V1
(
pg_file_rename
);
PG_FUNCTION_INFO_V1
(
pg_file_unlink
);
PG_FUNCTION_INFO_V1
(
pg_logdir_ls
);
typedef
struct
{
char
*
location
;
DIR
*
dirdesc
;
}
directory_fctx
;
/*-----------------------
* some helper functions
*/
/*
* Return an absolute path. Argument may be absolute or
* relative to the DataDir.
*/
static
char
*
absClusterPath
(
text
*
arg
,
bool
logAllowed
)
{
char
*
filename
;
int
len
=
VARSIZE
(
arg
)
-
VARHDRSZ
;
int
dlen
=
strlen
(
DataDir
);
filename
=
palloc
(
len
+
1
);
memcpy
(
filename
,
VARDATA
(
arg
),
len
);
filename
[
len
]
=
0
;
if
(
strstr
(
filename
,
".."
)
!=
NULL
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"No .. allowed in filenames"
))));
if
(
is_absolute_path
(
filename
))
{
if
(
logAllowed
&&
!
strncmp
(
filename
,
Log_directory
,
strlen
(
Log_directory
)))
return
filename
;
if
(
strncmp
(
filename
,
DataDir
,
dlen
))
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"Absolute path not allowed"
))));
return
filename
;
}
else
{
char
*
absname
=
palloc
(
dlen
+
len
+
2
);
sprintf
(
absname
,
"%s/%s"
,
DataDir
,
filename
);
pfree
(
filename
);
return
absname
;
}
}
/*
* check for superuser, bark if not.
*/
static
void
requireSuperuser
(
void
)
{
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"only superuser may access generic file functions"
))));
}
/* ------------------------------------
* generic file handling functions
*/
Datum
pg_file_write
(
PG_FUNCTION_ARGS
)
{
FILE
*
f
;
char
*
filename
;
text
*
data
;
int64
count
=
0
;
requireSuperuser
();
filename
=
absClusterPath
(
PG_GETARG_TEXT_P
(
0
),
false
);
data
=
PG_GETARG_TEXT_P
(
1
);
if
(
PG_ARGISNULL
(
2
)
||
!
PG_GETARG_BOOL
(
2
))
{
struct
stat
fst
;
if
(
stat
(
filename
,
&
fst
)
>=
0
)
ereport
(
ERROR
,
(
ERRCODE_DUPLICATE_FILE
,
errmsg
(
"file %s exists"
,
filename
)));
f
=
fopen
(
filename
,
"wb"
);
}
else
f
=
fopen
(
filename
,
"ab"
);
if
(
!
f
)
{
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"could open file %s for writing: %m"
,
filename
)));
}
if
(
VARSIZE
(
data
)
!=
0
)
{
count
=
fwrite
(
VARDATA
(
data
),
1
,
VARSIZE
(
data
)
-
VARHDRSZ
,
f
);
if
(
count
!=
VARSIZE
(
data
)
-
VARHDRSZ
)
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"error writing file %s: %m"
,
filename
)));
}
fclose
(
f
);
PG_RETURN_INT64
(
count
);
}
Datum
pg_file_rename
(
PG_FUNCTION_ARGS
)
{
char
*
fn1
,
*
fn2
,
*
fn3
;
int
rc
;
requireSuperuser
();
if
(
PG_ARGISNULL
(
0
)
||
PG_ARGISNULL
(
1
))
PG_RETURN_NULL
();
fn1
=
absClusterPath
(
PG_GETARG_TEXT_P
(
0
),
false
);
fn2
=
absClusterPath
(
PG_GETARG_TEXT_P
(
1
),
false
);
if
(
PG_ARGISNULL
(
2
))
fn3
=
0
;
else
fn3
=
absClusterPath
(
PG_GETARG_TEXT_P
(
2
),
false
);
if
(
access
(
fn1
,
W_OK
)
<
0
)
{
ereport
(
WARNING
,
(
errcode_for_file_access
(),
errmsg
(
"file %s not accessible: %m"
,
fn1
)));
PG_RETURN_BOOL
(
false
);
}
if
(
fn3
&&
access
(
fn2
,
W_OK
)
<
0
)
{
ereport
(
WARNING
,
(
errcode_for_file_access
(),
errmsg
(
"file %s not accessible: %m"
,
fn2
)));
PG_RETURN_BOOL
(
false
);
}
rc
=
access
(
fn3
?
fn3
:
fn2
,
2
);
if
(
rc
>=
0
||
errno
!=
ENOENT
)
{
ereport
(
ERROR
,
(
ERRCODE_DUPLICATE_FILE
,
errmsg
(
"cannot rename to target file %s"
,
fn3
?
fn3
:
fn2
)));
}
if
(
fn3
)
{
if
(
rename
(
fn2
,
fn3
)
!=
0
)
{
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"could not rename %s to %s: %m"
,
fn2
,
fn3
)));
}
if
(
rename
(
fn1
,
fn2
)
!=
0
)
{
ereport
(
WARNING
,
(
errcode_for_file_access
(),
errmsg
(
"could not rename %s to %s: %m"
,
fn1
,
fn2
)));
if
(
rename
(
fn3
,
fn2
)
!=
0
)
{
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"could not rename %s back to %s: %m"
,
fn3
,
fn2
)));
}
else
{
ereport
(
ERROR
,
(
ERRCODE_UNDEFINED_FILE
,
errmsg
(
"renaming %s to %s was reverted"
,
fn2
,
fn3
)));
}
}
}
else
if
(
rename
(
fn1
,
fn2
)
!=
0
)
{
ereport
(
WARNING
,
(
errcode_for_file_access
(),
errmsg
(
"renaming %s to %s %m"
,
fn1
,
fn2
)));
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"could not rename %s to %s: %m"
,
fn1
,
fn2
)));
}
PG_RETURN_BOOL
(
true
);
}
Datum
pg_file_unlink
(
PG_FUNCTION_ARGS
)
{
char
*
filename
;
requireSuperuser
();
filename
=
absClusterPath
(
PG_GETARG_TEXT_P
(
0
),
false
);
if
(
access
(
filename
,
W_OK
)
<
0
)
{
if
(
errno
==
ENOENT
)
PG_RETURN_BOOL
(
false
);
else
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"file %s not accessible: %m"
,
filename
)));
}
if
(
unlink
(
filename
)
<
0
)
{
ereport
(
WARNING
,
(
errcode_for_file_access
(),
errmsg
(
"could not unlink file %s: %m"
,
filename
)));
PG_RETURN_BOOL
(
false
);
}
PG_RETURN_BOOL
(
true
);
}
Datum
pg_logdir_ls
(
PG_FUNCTION_ARGS
)
{
FuncCallContext
*
funcctx
;
struct
dirent
*
de
;
directory_fctx
*
fctx
;
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"only superuser can list the log directory"
))));
if
(
memcmp
(
Log_filename
,
"postgresql-%Y-%m-%d_%H%M%S.log"
,
30
)
!=
0
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
(
errmsg
(
"the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'"
))));
if
(
SRF_IS_FIRSTCALL
())
{
MemoryContext
oldcontext
;
TupleDesc
tupdesc
;
funcctx
=
SRF_FIRSTCALL_INIT
();
oldcontext
=
MemoryContextSwitchTo
(
funcctx
->
multi_call_memory_ctx
);
fctx
=
palloc
(
sizeof
(
directory_fctx
));
if
(
is_absolute_path
(
Log_directory
))
fctx
->
location
=
Log_directory
;
else
{
fctx
->
location
=
palloc
(
strlen
(
DataDir
)
+
strlen
(
Log_directory
)
+
2
);
sprintf
(
fctx
->
location
,
"%s/%s"
,
DataDir
,
Log_directory
);
}
tupdesc
=
CreateTemplateTupleDesc
(
2
,
false
);
TupleDescInitEntry
(
tupdesc
,
(
AttrNumber
)
1
,
"starttime"
,
TIMESTAMPOID
,
-
1
,
0
);
TupleDescInitEntry
(
tupdesc
,
(
AttrNumber
)
2
,
"filename"
,
TEXTOID
,
-
1
,
0
);
funcctx
->
attinmeta
=
TupleDescGetAttInMetadata
(
tupdesc
);
fctx
->
dirdesc
=
AllocateDir
(
fctx
->
location
);
if
(
!
fctx
->
dirdesc
)
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"%s is not browsable: %m"
,
fctx
->
location
)));
funcctx
->
user_fctx
=
fctx
;
MemoryContextSwitchTo
(
oldcontext
);
}
funcctx
=
SRF_PERCALL_SETUP
();
fctx
=
(
directory_fctx
*
)
funcctx
->
user_fctx
;
if
(
!
fctx
->
dirdesc
)
/* not a readable directory */
SRF_RETURN_DONE
(
funcctx
);
while
((
de
=
readdir
(
fctx
->
dirdesc
))
!=
NULL
)
{
char
*
values
[
2
];
HeapTuple
tuple
;
char
*
field
[
MAXDATEFIELDS
];
char
lowstr
[
MAXDATELEN
+
1
];
int
dtype
;
int
nf
,
ftype
[
MAXDATEFIELDS
];
fsec_t
fsec
;
int
tz
=
0
;
struct
pg_tm
date
;
/*
* Default format:
* postgresql-YYYY-MM-DD_HHMMSS.log
*/
if
(
strlen
(
de
->
d_name
)
!=
32
||
memcmp
(
de
->
d_name
,
"postgresql-"
,
11
)
||
de
->
d_name
[
21
]
!=
'_'
||
strcmp
(
de
->
d_name
+
28
,
".log"
))
continue
;
values
[
1
]
=
palloc
(
strlen
(
fctx
->
location
)
+
strlen
(
de
->
d_name
)
+
2
);
sprintf
(
values
[
1
],
"%s/%s"
,
fctx
->
location
,
de
->
d_name
);
values
[
0
]
=
de
->
d_name
+
11
;
/* timestamp */
values
[
0
][
17
]
=
0
;
/* parse and decode expected timestamp */
if
(
ParseDateTime
(
values
[
0
],
lowstr
,
MAXDATELEN
,
field
,
ftype
,
MAXDATEFIELDS
,
&
nf
))
continue
;
if
(
DecodeDateTime
(
field
,
ftype
,
nf
,
&
dtype
,
&
date
,
&
fsec
,
&
tz
))
continue
;
/* Seems the format fits the expected format; feed it into the tuple */
tuple
=
BuildTupleFromCStrings
(
funcctx
->
attinmeta
,
values
);
SRF_RETURN_NEXT
(
funcctx
,
HeapTupleGetDatum
(
tuple
));
}
FreeDir
(
fctx
->
dirdesc
);
SRF_RETURN_DONE
(
funcctx
);
}
/*-------------------------------------------------------------------------
*
* admin81.c
*
*
* Copyright (c) 2002 - 2006, PostgreSQL Global Development Group
*
* Author: Andreas Pflug <pgadmin@pse-consulting.de>
*
* IDENTIFICATION
* $PostgreSQL: pgsql/contrib/adminpack/adminpack.c,v 1.2 2006/05/30 21:34:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "miscadmin.h"
#include "storage/fd.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "utils/datetime.h"
#ifdef WIN32
#ifdef rename
#undef rename
#endif
#ifdef unlink
#undef unlink
#endif
#endif
extern
DLLIMPORT
char
*
DataDir
;
extern
DLLIMPORT
char
*
Log_directory
;
extern
DLLIMPORT
char
*
Log_filename
;
PG_MODULE_MAGIC
;
Datum
pg_file_write
(
PG_FUNCTION_ARGS
);
Datum
pg_file_rename
(
PG_FUNCTION_ARGS
);
Datum
pg_file_unlink
(
PG_FUNCTION_ARGS
);
Datum
pg_logdir_ls
(
PG_FUNCTION_ARGS
);
PG_FUNCTION_INFO_V1
(
pg_file_write
);
PG_FUNCTION_INFO_V1
(
pg_file_rename
);
PG_FUNCTION_INFO_V1
(
pg_file_unlink
);
PG_FUNCTION_INFO_V1
(
pg_logdir_ls
);
typedef
struct
{
char
*
location
;
DIR
*
dirdesc
;
}
directory_fctx
;
/*-----------------------
* some helper functions
*/
/*
* Return an absolute path. Argument may be absolute or
* relative to the DataDir.
*/
static
char
*
absClusterPath
(
text
*
arg
,
bool
logAllowed
)
{
char
*
filename
;
int
len
=
VARSIZE
(
arg
)
-
VARHDRSZ
;
int
dlen
=
strlen
(
DataDir
);
filename
=
palloc
(
len
+
1
);
memcpy
(
filename
,
VARDATA
(
arg
),
len
);
filename
[
len
]
=
0
;
if
(
strstr
(
filename
,
".."
)
!=
NULL
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"No .. allowed in filenames"
))));
if
(
is_absolute_path
(
filename
))
{
if
(
logAllowed
&&
!
strncmp
(
filename
,
Log_directory
,
strlen
(
Log_directory
)))
return
filename
;
if
(
strncmp
(
filename
,
DataDir
,
dlen
))
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"Absolute path not allowed"
))));
return
filename
;
}
else
{
char
*
absname
=
palloc
(
dlen
+
len
+
2
);
sprintf
(
absname
,
"%s/%s"
,
DataDir
,
filename
);
pfree
(
filename
);
return
absname
;
}
}
/*
* check for superuser, bark if not.
*/
static
void
requireSuperuser
(
void
)
{
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"only superuser may access generic file functions"
))));
}
/* ------------------------------------
* generic file handling functions
*/
Datum
pg_file_write
(
PG_FUNCTION_ARGS
)
{
FILE
*
f
;
char
*
filename
;
text
*
data
;
int64
count
=
0
;
requireSuperuser
();
filename
=
absClusterPath
(
PG_GETARG_TEXT_P
(
0
),
false
);
data
=
PG_GETARG_TEXT_P
(
1
);
if
(
PG_ARGISNULL
(
2
)
||
!
PG_GETARG_BOOL
(
2
))
{
struct
stat
fst
;
if
(
stat
(
filename
,
&
fst
)
>=
0
)
ereport
(
ERROR
,
(
ERRCODE_DUPLICATE_FILE
,
errmsg
(
"file %s exists"
,
filename
)));
f
=
fopen
(
filename
,
"wb"
);
}
else
f
=
fopen
(
filename
,
"ab"
);
if
(
!
f
)
{
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"could open file %s for writing: %m"
,
filename
)));
}
if
(
VARSIZE
(
data
)
!=
0
)
{
count
=
fwrite
(
VARDATA
(
data
),
1
,
VARSIZE
(
data
)
-
VARHDRSZ
,
f
);
if
(
count
!=
VARSIZE
(
data
)
-
VARHDRSZ
)
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"error writing file %s: %m"
,
filename
)));
}
fclose
(
f
);
PG_RETURN_INT64
(
count
);
}
Datum
pg_file_rename
(
PG_FUNCTION_ARGS
)
{
char
*
fn1
,
*
fn2
,
*
fn3
;
int
rc
;
requireSuperuser
();
if
(
PG_ARGISNULL
(
0
)
||
PG_ARGISNULL
(
1
))
PG_RETURN_NULL
();
fn1
=
absClusterPath
(
PG_GETARG_TEXT_P
(
0
),
false
);
fn2
=
absClusterPath
(
PG_GETARG_TEXT_P
(
1
),
false
);
if
(
PG_ARGISNULL
(
2
))
fn3
=
0
;
else
fn3
=
absClusterPath
(
PG_GETARG_TEXT_P
(
2
),
false
);
if
(
access
(
fn1
,
W_OK
)
<
0
)
{
ereport
(
WARNING
,
(
errcode_for_file_access
(),
errmsg
(
"file %s not accessible: %m"
,
fn1
)));
PG_RETURN_BOOL
(
false
);
}
if
(
fn3
&&
access
(
fn2
,
W_OK
)
<
0
)
{
ereport
(
WARNING
,
(
errcode_for_file_access
(),
errmsg
(
"file %s not accessible: %m"
,
fn2
)));
PG_RETURN_BOOL
(
false
);
}
rc
=
access
(
fn3
?
fn3
:
fn2
,
2
);
if
(
rc
>=
0
||
errno
!=
ENOENT
)
{
ereport
(
ERROR
,
(
ERRCODE_DUPLICATE_FILE
,
errmsg
(
"cannot rename to target file %s"
,
fn3
?
fn3
:
fn2
)));
}
if
(
fn3
)
{
if
(
rename
(
fn2
,
fn3
)
!=
0
)
{
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"could not rename %s to %s: %m"
,
fn2
,
fn3
)));
}
if
(
rename
(
fn1
,
fn2
)
!=
0
)
{
ereport
(
WARNING
,
(
errcode_for_file_access
(),
errmsg
(
"could not rename %s to %s: %m"
,
fn1
,
fn2
)));
if
(
rename
(
fn3
,
fn2
)
!=
0
)
{
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"could not rename %s back to %s: %m"
,
fn3
,
fn2
)));
}
else
{
ereport
(
ERROR
,
(
ERRCODE_UNDEFINED_FILE
,
errmsg
(
"renaming %s to %s was reverted"
,
fn2
,
fn3
)));
}
}
}
else
if
(
rename
(
fn1
,
fn2
)
!=
0
)
{
ereport
(
WARNING
,
(
errcode_for_file_access
(),
errmsg
(
"renaming %s to %s %m"
,
fn1
,
fn2
)));
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"could not rename %s to %s: %m"
,
fn1
,
fn2
)));
}
PG_RETURN_BOOL
(
true
);
}
Datum
pg_file_unlink
(
PG_FUNCTION_ARGS
)
{
char
*
filename
;
requireSuperuser
();
filename
=
absClusterPath
(
PG_GETARG_TEXT_P
(
0
),
false
);
if
(
access
(
filename
,
W_OK
)
<
0
)
{
if
(
errno
==
ENOENT
)
PG_RETURN_BOOL
(
false
);
else
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"file %s not accessible: %m"
,
filename
)));
}
if
(
unlink
(
filename
)
<
0
)
{
ereport
(
WARNING
,
(
errcode_for_file_access
(),
errmsg
(
"could not unlink file %s: %m"
,
filename
)));
PG_RETURN_BOOL
(
false
);
}
PG_RETURN_BOOL
(
true
);
}
Datum
pg_logdir_ls
(
PG_FUNCTION_ARGS
)
{
FuncCallContext
*
funcctx
;
struct
dirent
*
de
;
directory_fctx
*
fctx
;
if
(
!
superuser
())
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INSUFFICIENT_PRIVILEGE
),
(
errmsg
(
"only superuser can list the log directory"
))));
if
(
memcmp
(
Log_filename
,
"postgresql-%Y-%m-%d_%H%M%S.log"
,
30
)
!=
0
)
ereport
(
ERROR
,
(
errcode
(
ERRCODE_INVALID_PARAMETER_VALUE
),
(
errmsg
(
"the log_filename parameter must equal 'postgresql-%%Y-%%m-%%d_%%H%%M%%S.log'"
))));
if
(
SRF_IS_FIRSTCALL
())
{
MemoryContext
oldcontext
;
TupleDesc
tupdesc
;
funcctx
=
SRF_FIRSTCALL_INIT
();
oldcontext
=
MemoryContextSwitchTo
(
funcctx
->
multi_call_memory_ctx
);
fctx
=
palloc
(
sizeof
(
directory_fctx
));
if
(
is_absolute_path
(
Log_directory
))
fctx
->
location
=
Log_directory
;
else
{
fctx
->
location
=
palloc
(
strlen
(
DataDir
)
+
strlen
(
Log_directory
)
+
2
);
sprintf
(
fctx
->
location
,
"%s/%s"
,
DataDir
,
Log_directory
);
}
tupdesc
=
CreateTemplateTupleDesc
(
2
,
false
);
TupleDescInitEntry
(
tupdesc
,
(
AttrNumber
)
1
,
"starttime"
,
TIMESTAMPOID
,
-
1
,
0
);
TupleDescInitEntry
(
tupdesc
,
(
AttrNumber
)
2
,
"filename"
,
TEXTOID
,
-
1
,
0
);
funcctx
->
attinmeta
=
TupleDescGetAttInMetadata
(
tupdesc
);
fctx
->
dirdesc
=
AllocateDir
(
fctx
->
location
);
if
(
!
fctx
->
dirdesc
)
ereport
(
ERROR
,
(
errcode_for_file_access
(),
errmsg
(
"%s is not browsable: %m"
,
fctx
->
location
)));
funcctx
->
user_fctx
=
fctx
;
MemoryContextSwitchTo
(
oldcontext
);
}
funcctx
=
SRF_PERCALL_SETUP
();
fctx
=
(
directory_fctx
*
)
funcctx
->
user_fctx
;
if
(
!
fctx
->
dirdesc
)
/* not a readable directory */
SRF_RETURN_DONE
(
funcctx
);
while
((
de
=
readdir
(
fctx
->
dirdesc
))
!=
NULL
)
{
char
*
values
[
2
];
HeapTuple
tuple
;
char
*
field
[
MAXDATEFIELDS
];
char
lowstr
[
MAXDATELEN
+
1
];
int
dtype
;
int
nf
,
ftype
[
MAXDATEFIELDS
];
fsec_t
fsec
;
int
tz
=
0
;
struct
pg_tm
date
;
/*
* Default format:
* postgresql-YYYY-MM-DD_HHMMSS.log
*/
if
(
strlen
(
de
->
d_name
)
!=
32
||
memcmp
(
de
->
d_name
,
"postgresql-"
,
11
)
||
de
->
d_name
[
21
]
!=
'_'
||
strcmp
(
de
->
d_name
+
28
,
".log"
))
continue
;
values
[
1
]
=
palloc
(
strlen
(
fctx
->
location
)
+
strlen
(
de
->
d_name
)
+
2
);
sprintf
(
values
[
1
],
"%s/%s"
,
fctx
->
location
,
de
->
d_name
);
values
[
0
]
=
de
->
d_name
+
11
;
/* timestamp */
values
[
0
][
17
]
=
0
;
/* parse and decode expected timestamp */
if
(
ParseDateTime
(
values
[
0
],
lowstr
,
MAXDATELEN
,
field
,
ftype
,
MAXDATEFIELDS
,
&
nf
))
continue
;
if
(
DecodeDateTime
(
field
,
ftype
,
nf
,
&
dtype
,
&
date
,
&
fsec
,
&
tz
))
continue
;
/* Seems the format fits the expected format; feed it into the tuple */
tuple
=
BuildTupleFromCStrings
(
funcctx
->
attinmeta
,
values
);
SRF_RETURN_NEXT
(
funcctx
,
HeapTupleGetDatum
(
tuple
));
}
FreeDir
(
fctx
->
dirdesc
);
SRF_RETURN_DONE
(
funcctx
);
}
contrib/adminpack/adminpack.sql.in
View file @
e95703ea
/* ***********************************************
* Administrative functions for PostgreSQL
* *********************************************** */
/* generic file access functions */
CREATE FUNCTION pg_catalog.pg_file_write(text, text, bool) RETURNS bigint
AS 'MODULE_PATHNAME', 'pg_file_write'
LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION pg_catalog.pg_file_rename(text, text, text) RETURNS bool
AS 'MODULE_PATHNAME', 'pg_file_rename'
LANGUAGE C VOLATILE;
CREATE FUNCTION pg_catalog.pg_file_unlink(text) RETURNS bool
AS 'MODULE_PATHNAME', 'pg_file_unlink'
LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION pg_catalog.pg_file_rename(text, text) RETURNS bool
AS 'SELECT pg_file_rename($1, $2, NULL); '
LANGUAGE SQL VOLATILE STRICT;
CREATE FUNCTION pg_catalog.pg_logdir_ls() RETURNS setof record
AS 'MODULE_PATHNAME', 'pg_logdir_ls'
LANGUAGE C VOLATILE STRICT;
/* compatibility redefines */
CREATE FUNCTION pg_catalog.pg_logfile_rotate() RETURNS int4
AS 'pg_rotate_logfile'
LANGUAGE INTERNAL VOLATILE STRICT;
CREATE FUNCTION pg_catalog.pg_file_read(text, bigint, bigint) RETURNS text
AS 'pg_read_file'
LANGUAGE INTERNAL VOLATILE STRICT;
CREATE FUNCTION pg_catalog.pg_file_length(text) RETURNS bigint
AS 'SELECT size FROM pg_stat_file($1)'
LANGUAGE SQL VOLATILE STRICT;
/* ***********************************************
* Administrative functions for PostgreSQL
* *********************************************** */
/* generic file access functions */
CREATE FUNCTION pg_catalog.pg_file_write(text, text, bool) RETURNS bigint
AS 'MODULE_PATHNAME', 'pg_file_write'
LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION pg_catalog.pg_file_rename(text, text, text) RETURNS bool
AS 'MODULE_PATHNAME', 'pg_file_rename'
LANGUAGE C VOLATILE;
CREATE FUNCTION pg_catalog.pg_file_unlink(text) RETURNS bool
AS 'MODULE_PATHNAME', 'pg_file_unlink'
LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION pg_catalog.pg_file_rename(text, text) RETURNS bool
AS 'SELECT pg_file_rename($1, $2, NULL); '
LANGUAGE SQL VOLATILE STRICT;
CREATE FUNCTION pg_catalog.pg_logdir_ls() RETURNS setof record
AS 'MODULE_PATHNAME', 'pg_logdir_ls'
LANGUAGE C VOLATILE STRICT;
/* compatibility redefines */
CREATE FUNCTION pg_catalog.pg_logfile_rotate() RETURNS int4
AS 'pg_rotate_logfile'
LANGUAGE INTERNAL VOLATILE STRICT;
CREATE FUNCTION pg_catalog.pg_file_read(text, bigint, bigint) RETURNS text
AS 'pg_read_file'
LANGUAGE INTERNAL VOLATILE STRICT;
CREATE FUNCTION pg_catalog.pg_file_length(text) RETURNS bigint
AS 'SELECT size FROM pg_stat_file($1)'
LANGUAGE SQL VOLATILE STRICT;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment