PostgreSQL Source Code  git master
walmethods.c File Reference
#include "postgres_fe.h"
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "common/file_perm.h"
#include "common/file_utils.h"
#include "pgtar.h"
#include "receivelog.h"
#include "streamutil.h"
Include dependency graph for walmethods.c:

Go to the source code of this file.

Data Structures

struct  DirectoryMethodData
 
struct  DirectoryMethodFile
 
struct  TarMethodFile
 
struct  TarMethodData
 

Macros

#define ZLIB_OUT_SIZE   4096
 
#define tar_clear_error()   tar_data->lasterror[0] = '\0'
 
#define tar_set_error(msg)   strlcpy(tar_data->lasterror, _(msg), sizeof(tar_data->lasterror))
 

Typedefs

typedef struct DirectoryMethodData DirectoryMethodData
 
typedef struct DirectoryMethodFile DirectoryMethodFile
 
typedef struct TarMethodFile TarMethodFile
 
typedef struct TarMethodData TarMethodData
 

Functions

static const char * dir_getlasterror (void)
 
static char * dir_get_file_name (const char *pathname, const char *temp_suffix)
 
static Walfile dir_open_for_write (const char *pathname, const char *temp_suffix, size_t pad_to_size)
 
static ssize_t dir_write (Walfile f, const void *buf, size_t count)
 
static off_t dir_get_current_pos (Walfile f)
 
static int dir_close (Walfile f, WalCloseMethod method)
 
static int dir_sync (Walfile f)
 
static ssize_t dir_get_file_size (const char *pathname)
 
static int dir_compression (void)
 
static bool dir_existsfile (const char *pathname)
 
static bool dir_finish (void)
 
WalWriteMethodCreateWalDirectoryMethod (const char *basedir, int compression, bool sync)
 
void FreeWalDirectoryMethod (void)
 
static const char * tar_getlasterror (void)
 
static ssize_t tar_write (Walfile f, const void *buf, size_t count)
 
static bool tar_write_padding_data (TarMethodFile *f, size_t bytes)
 
static char * tar_get_file_name (const char *pathname, const char *temp_suffix)
 
static Walfile tar_open_for_write (const char *pathname, const char *temp_suffix, size_t pad_to_size)
 
static ssize_t tar_get_file_size (const char *pathname)
 
static int tar_compression (void)
 
static off_t tar_get_current_pos (Walfile f)
 
static int tar_sync (Walfile f)
 
static int tar_close (Walfile f, WalCloseMethod method)
 
static bool tar_existsfile (const char *pathname)
 
static bool tar_finish (void)
 
WalWriteMethodCreateWalTarMethod (const char *tarbase, int compression, bool sync)
 
void FreeWalTarMethod (void)
 

Variables

static DirectoryMethodDatadir_data = NULL
 
static TarMethodDatatar_data = NULL
 

Macro Definition Documentation

◆ tar_clear_error

#define tar_clear_error ( )    tar_data->lasterror[0] = '\0'

◆ tar_set_error

#define tar_set_error (   msg)    strlcpy(tar_data->lasterror, _(msg), sizeof(tar_data->lasterror))

Definition at line 439 of file walmethods.c.

Referenced by tar_close(), tar_finish(), tar_getlasterror(), and tar_open_for_write().

◆ ZLIB_OUT_SIZE

#define ZLIB_OUT_SIZE   4096

Typedef Documentation

◆ DirectoryMethodData

◆ DirectoryMethodFile

◆ TarMethodData

typedef struct TarMethodData TarMethodData

◆ TarMethodFile

typedef struct TarMethodFile TarMethodFile

Function Documentation

◆ CreateWalDirectoryMethod()

WalWriteMethod* CreateWalDirectoryMethod ( const char *  basedir,
int  compression,
bool  sync 
)

Definition at line 376 of file walmethods.c.

References DirectoryMethodData::basedir, WalWriteMethod::close, DirectoryMethodData::compression, WalWriteMethod::compression, dir_close(), dir_compression(), dir_existsfile(), dir_finish(), dir_get_current_pos(), dir_get_file_name(), dir_get_file_size(), dir_getlasterror(), dir_open_for_write(), dir_sync(), dir_write(), WalWriteMethod::existsfile, WalWriteMethod::finish, WalWriteMethod::get_current_pos, WalWriteMethod::get_file_name, WalWriteMethod::get_file_size, WalWriteMethod::getlasterror, WalWriteMethod::open_for_write, pg_malloc0(), pg_strdup(), DirectoryMethodData::sync, WalWriteMethod::sync, and WalWriteMethod::write.

Referenced by LogStreamerMain(), and StreamLog().

377 {
378  WalWriteMethod *method;
379 
380  method = pg_malloc0(sizeof(WalWriteMethod));
382  method->write = dir_write;
386  method->compression = dir_compression;
387  method->close = dir_close;
388  method->sync = dir_sync;
389  method->existsfile = dir_existsfile;
390  method->finish = dir_finish;
391  method->getlasterror = dir_getlasterror;
392 
394  dir_data->compression = compression;
396  dir_data->sync = sync;
397 
398  return method;
399 }
char *(* get_file_name)(const char *pathname, const char *temp_suffix)
Definition: walmethods.h:59
static off_t dir_get_current_pos(Walfile f)
Definition: walmethods.c:218
int(* close)(Walfile f, WalCloseMethod method)
Definition: walmethods.h:47
int(* sync)(Walfile f)
Definition: walmethods.h:76
static char * basedir
const char *(* getlasterror)(void)
Definition: walmethods.h:87
static char * dir_get_file_name(const char *pathname, const char *temp_suffix)
Definition: walmethods.c:72
off_t(* get_current_pos)(Walfile f)
Definition: walmethods.h:71
static bool dir_finish(void)
Definition: walmethods.c:360
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
ssize_t(* write)(Walfile f, const void *buf, size_t count)
Definition: walmethods.h:68
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static ssize_t dir_write(Walfile f, const void *buf, size_t count)
Definition: walmethods.c:199
static DirectoryMethodData * dir_data
Definition: walmethods.c:47
static int dir_close(Walfile f, WalCloseMethod method)
Definition: walmethods.c:227
bool(* finish)(void)
Definition: walmethods.h:84
bool(* existsfile)(const char *pathname)
Definition: walmethods.h:50
static int dir_compression(void)
Definition: walmethods.c:338
int(* compression)(void)
Definition: walmethods.h:62
Walfile(* open_for_write)(const char *pathname, const char *temp_suffix, size_t pad_to_size)
Definition: walmethods.h:41
static Walfile dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_size)
Definition: walmethods.c:84
ssize_t(* get_file_size)(const char *pathname)
Definition: walmethods.h:53
static const char * dir_getlasterror(void)
Definition: walmethods.c:65
static ssize_t dir_get_file_size(const char *pathname)
Definition: walmethods.c:323
static bool dir_existsfile(const char *pathname)
Definition: walmethods.c:344
static int dir_sync(Walfile f)
Definition: walmethods.c:304

◆ CreateWalTarMethod()

WalWriteMethod* CreateWalTarMethod ( const char *  tarbase,
int  compression,
bool  sync 
)

Definition at line 1035 of file walmethods.c.

References WalWriteMethod::close, DirectoryMethodData::compression, WalWriteMethod::compression, TarMethodData::compression, WalWriteMethod::existsfile, TarMethodData::fd, WalWriteMethod::finish, WalWriteMethod::get_current_pos, WalWriteMethod::get_file_name, WalWriteMethod::get_file_size, WalWriteMethod::getlasterror, WalWriteMethod::open_for_write, pg_malloc(), pg_malloc0(), sprintf, DirectoryMethodData::sync, WalWriteMethod::sync, TarMethodData::sync, tar_close(), tar_compression(), tar_existsfile(), tar_finish(), tar_get_current_pos(), tar_get_file_name(), tar_get_file_size(), tar_getlasterror(), tar_open_for_write(), tar_sync(), tar_write(), TarMethodData::tarfilename, WalWriteMethod::write, and ZLIB_OUT_SIZE.

Referenced by LogStreamerMain().

1036 {
1037  WalWriteMethod *method;
1038  const char *suffix = (compression != 0) ? ".tar.gz" : ".tar";
1039 
1040  method = pg_malloc0(sizeof(WalWriteMethod));
1042  method->write = tar_write;
1044  method->get_file_size = tar_get_file_size;
1045  method->get_file_name = tar_get_file_name;
1046  method->compression = tar_compression;
1047  method->close = tar_close;
1048  method->sync = tar_sync;
1049  method->existsfile = tar_existsfile;
1050  method->finish = tar_finish;
1051  method->getlasterror = tar_getlasterror;
1052 
1053  tar_data = pg_malloc0(sizeof(TarMethodData));
1054  tar_data->tarfilename = pg_malloc0(strlen(tarbase) + strlen(suffix) + 1);
1055  sprintf(tar_data->tarfilename, "%s%s", tarbase, suffix);
1056  tar_data->fd = -1;
1057  tar_data->compression = compression;
1058  tar_data->sync = sync;
1059 #ifdef HAVE_LIBZ
1060  if (compression)
1061  tar_data->zlibOut = (char *) pg_malloc(ZLIB_OUT_SIZE + 1);
1062 #endif
1063 
1064  return method;
1065 }
char *(* get_file_name)(const char *pathname, const char *temp_suffix)
Definition: walmethods.h:59
static char * tar_get_file_name(const char *pathname, const char *temp_suffix)
Definition: walmethods.c:560
int(* close)(Walfile f, WalCloseMethod method)
Definition: walmethods.h:47
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
static bool tar_finish(void)
Definition: walmethods.c:938
int(* sync)(Walfile f)
Definition: walmethods.h:76
static ssize_t tar_write(Walfile f, const void *buf, size_t count)
Definition: walmethods.c:509
const char *(* getlasterror)(void)
Definition: walmethods.h:87
static int tar_close(Walfile f, WalCloseMethod method)
Definition: walmethods.c:769
off_t(* get_current_pos)(Walfile f)
Definition: walmethods.h:71
#define sprintf
Definition: port.h:218
static const char * tar_getlasterror(void)
Definition: walmethods.c:442
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
static Walfile tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_size)
Definition: walmethods.c:571
ssize_t(* write)(Walfile f, const void *buf, size_t count)
Definition: walmethods.h:68
static ssize_t tar_get_file_size(const char *pathname)
Definition: walmethods.c:725
static bool tar_existsfile(const char *pathname)
Definition: walmethods.c:930
static off_t tar_get_current_pos(Walfile f)
Definition: walmethods.c:741
char * tarfilename
Definition: walmethods.c:425
static int tar_compression(void)
Definition: walmethods.c:735
#define ZLIB_OUT_SIZE
Definition: walmethods.c:31
bool(* finish)(void)
Definition: walmethods.h:84
bool(* existsfile)(const char *pathname)
Definition: walmethods.h:50
int(* compression)(void)
Definition: walmethods.h:62
Walfile(* open_for_write)(const char *pathname, const char *temp_suffix, size_t pad_to_size)
Definition: walmethods.h:41
ssize_t(* get_file_size)(const char *pathname)
Definition: walmethods.h:53
static TarMethodData * tar_data
Definition: walmethods.c:436
static int tar_sync(Walfile f)
Definition: walmethods.c:750

◆ dir_close()

static int dir_close ( Walfile  f,
WalCloseMethod  method 
)
static

Definition at line 227 of file walmethods.c.

References Assert, DirectoryMethodData::basedir, close, CLOSE_NORMAL, CLOSE_UNLINK, DirectoryMethodData::compression, dir_get_file_name(), durable_rename(), DirectoryMethodFile::fd, filename, fsync_fname(), fsync_parent_path(), DirectoryMethodFile::fullpath, MAXPGPATH, DirectoryMethodFile::pathname, pg_free(), snprintf, DirectoryMethodData::sync, and DirectoryMethodFile::temp_suffix.

Referenced by CreateWalDirectoryMethod().

228 {
229  int r;
231  static char tmppath[MAXPGPATH];
232  static char tmppath2[MAXPGPATH];
233 
234  Assert(f != NULL);
235 
236 #ifdef HAVE_LIBZ
237  if (dir_data->compression > 0)
238  r = gzclose(df->gzfp);
239  else
240 #endif
241  r = close(df->fd);
242 
243  if (r == 0)
244  {
245  /* Build path to the current version of the file */
246  if (method == CLOSE_NORMAL && df->temp_suffix)
247  {
248  char *filename;
249  char *filename2;
250 
251  /*
252  * If we have a temp prefix, normal operation is to rename the
253  * file.
254  */
255  filename = dir_get_file_name(df->pathname, df->temp_suffix);
256  snprintf(tmppath, sizeof(tmppath), "%s/%s",
257  dir_data->basedir, filename);
258  pg_free(filename);
259 
260  /* permanent name, so no need for the prefix */
261  filename2 = dir_get_file_name(df->pathname, NULL);
262  snprintf(tmppath2, sizeof(tmppath2), "%s/%s",
263  dir_data->basedir, filename2);
264  pg_free(filename2);
265  r = durable_rename(tmppath, tmppath2);
266  }
267  else if (method == CLOSE_UNLINK)
268  {
269  char *filename;
270 
271  /* Unlink the file once it's closed */
272  filename = dir_get_file_name(df->pathname, df->temp_suffix);
273  snprintf(tmppath, sizeof(tmppath), "%s/%s",
274  dir_data->basedir, filename);
275  pg_free(filename);
276  r = unlink(tmppath);
277  }
278  else
279  {
280  /*
281  * Else either CLOSE_NORMAL and no temp suffix, or
282  * CLOSE_NO_RENAME. In this case, fsync the file and containing
283  * directory if sync mode is requested.
284  */
285  if (dir_data->sync)
286  {
287  r = fsync_fname(df->fullpath, false);
288  if (r == 0)
289  r = fsync_parent_path(df->fullpath);
290  }
291  }
292  }
293 
294  pg_free(df->pathname);
295  pg_free(df->fullpath);
296  if (df->temp_suffix)
297  pg_free(df->temp_suffix);
298  pg_free(df);
299 
300  return r;
301 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:671
static char * dir_get_file_name(const char *pathname, const char *temp_suffix)
Definition: walmethods.c:72
#define MAXPGPATH
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:697
static DirectoryMethodData * dir_data
Definition: walmethods.c:47
#define Assert(condition)
Definition: c.h:804
void pg_free(void *ptr)
Definition: fe_memutils.c:105
static char * filename
Definition: pg_dumpall.c:92
#define close(a)
Definition: win32.h:12
#define snprintf
Definition: port.h:216
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3742

◆ dir_compression()

static int dir_compression ( void  )
static

Definition at line 338 of file walmethods.c.

References DirectoryMethodData::compression.

Referenced by CreateWalDirectoryMethod().

339 {
340  return dir_data->compression;
341 }
static DirectoryMethodData * dir_data
Definition: walmethods.c:47

◆ dir_existsfile()

static bool dir_existsfile ( const char *  pathname)
static

Definition at line 344 of file walmethods.c.

References DirectoryMethodData::basedir, close, fd(), MAXPGPATH, PG_BINARY, and snprintf.

Referenced by CreateWalDirectoryMethod().

345 {
346  static char tmppath[MAXPGPATH];
347  int fd;
348 
349  snprintf(tmppath, sizeof(tmppath), "%s/%s",
350  dir_data->basedir, pathname);
351 
352  fd = open(tmppath, O_RDONLY | PG_BINARY, 0);
353  if (fd < 0)
354  return false;
355  close(fd);
356  return true;
357 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1271
#define MAXPGPATH
static DirectoryMethodData * dir_data
Definition: walmethods.c:47
#define close(a)
Definition: win32.h:12
#define snprintf
Definition: port.h:216

◆ dir_finish()

static bool dir_finish ( void  )
static

Definition at line 360 of file walmethods.c.

References DirectoryMethodData::basedir, fsync_fname(), and DirectoryMethodData::sync.

Referenced by CreateWalDirectoryMethod().

361 {
362  if (dir_data->sync)
363  {
364  /*
365  * Files are fsynced when they are closed, but we need to fsync the
366  * directory entry here as well.
367  */
368  if (fsync_fname(dir_data->basedir, true) != 0)
369  return false;
370  }
371  return true;
372 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:671
static DirectoryMethodData * dir_data
Definition: walmethods.c:47

◆ dir_get_current_pos()

static off_t dir_get_current_pos ( Walfile  f)
static

Definition at line 218 of file walmethods.c.

References Assert.

Referenced by CreateWalDirectoryMethod().

219 {
220  Assert(f != NULL);
221 
222  /* Use a cached value to prevent lots of reseeks */
223  return ((DirectoryMethodFile *) f)->currpos;
224 }
#define Assert(condition)
Definition: c.h:804

◆ dir_get_file_name()

static char* dir_get_file_name ( const char *  pathname,
const char *  temp_suffix 
)
static

Definition at line 72 of file walmethods.c.

References DirectoryMethodData::compression, filename, MAXPGPATH, pg_malloc0(), and snprintf.

Referenced by CreateWalDirectoryMethod(), dir_close(), and dir_open_for_write().

73 {
74  char *filename = pg_malloc0(MAXPGPATH * sizeof(char));
75 
76  snprintf(filename, MAXPGPATH, "%s%s%s",
77  pathname, dir_data->compression > 0 ? ".gz" : "",
78  temp_suffix ? temp_suffix : "");
79 
80  return filename;
81 }
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
#define MAXPGPATH
static DirectoryMethodData * dir_data
Definition: walmethods.c:47
static char * filename
Definition: pg_dumpall.c:92
#define snprintf
Definition: port.h:216

◆ dir_get_file_size()

static ssize_t dir_get_file_size ( const char *  pathname)
static

Definition at line 323 of file walmethods.c.

References DirectoryMethodData::basedir, MAXPGPATH, snprintf, stat::st_size, and stat.

Referenced by CreateWalDirectoryMethod().

324 {
325  struct stat statbuf;
326  static char tmppath[MAXPGPATH];
327 
328  snprintf(tmppath, sizeof(tmppath), "%s/%s",
329  dir_data->basedir, pathname);
330 
331  if (stat(tmppath, &statbuf) != 0)
332  return -1;
333 
334  return statbuf.st_size;
335 }
#define MAXPGPATH
static DirectoryMethodData * dir_data
Definition: walmethods.c:47
#define snprintf
Definition: port.h:216
#define stat
Definition: win32_port.h:275

◆ dir_getlasterror()

static const char* dir_getlasterror ( void  )
static

Definition at line 65 of file walmethods.c.

References strerror.

Referenced by CreateWalDirectoryMethod().

66 {
67  /* Directory method always sets errno, so just use strerror */
68  return strerror(errno);
69 }
#define strerror
Definition: port.h:229

◆ dir_open_for_write()

static Walfile dir_open_for_write ( const char *  pathname,
const char *  temp_suffix,
size_t  pad_to_size 
)
static

Definition at line 84 of file walmethods.c.

References DirectoryMethodData::basedir, generate_unaccent_rules::bytes(), close, DirectoryMethodData::compression, DirectoryMethodFile::currpos, PGAlignedXLogBlock::data, dir_get_file_name(), DirectoryMethodFile::fd, fd(), filename, fsync_fname(), fsync_parent_path(), DirectoryMethodFile::fullpath, MAXPGPATH, DirectoryMethodFile::pathname, PG_BINARY, pg_file_create_mode, pg_free(), pg_malloc0(), pg_strdup(), snprintf, DirectoryMethodData::sync, DirectoryMethodFile::temp_suffix, and write.

Referenced by CreateWalDirectoryMethod().

85 {
86  static char tmppath[MAXPGPATH];
87  char *filename;
88  int fd;
90 #ifdef HAVE_LIBZ
91  gzFile gzfp = NULL;
92 #endif
93 
94  filename = dir_get_file_name(pathname, temp_suffix);
95  snprintf(tmppath, sizeof(tmppath), "%s/%s",
96  dir_data->basedir, filename);
97  pg_free(filename);
98 
99  /*
100  * Open a file for non-compressed as well as compressed files. Tracking
101  * the file descriptor is important for dir_sync() method as gzflush()
102  * does not do any system calls to fsync() to make changes permanent on
103  * disk.
104  */
105  fd = open(tmppath, O_WRONLY | O_CREAT | PG_BINARY, pg_file_create_mode);
106  if (fd < 0)
107  return NULL;
108 
109 #ifdef HAVE_LIBZ
110  if (dir_data->compression > 0)
111  {
112  gzfp = gzdopen(fd, "wb");
113  if (gzfp == NULL)
114  {
115  close(fd);
116  return NULL;
117  }
118 
119  if (gzsetparams(gzfp, dir_data->compression,
120  Z_DEFAULT_STRATEGY) != Z_OK)
121  {
122  gzclose(gzfp);
123  return NULL;
124  }
125  }
126 #endif
127 
128  /* Do pre-padding on non-compressed files */
129  if (pad_to_size && dir_data->compression == 0)
130  {
131  PGAlignedXLogBlock zerobuf;
132  int bytes;
133 
134  memset(zerobuf.data, 0, XLOG_BLCKSZ);
135  for (bytes = 0; bytes < pad_to_size; bytes += XLOG_BLCKSZ)
136  {
137  errno = 0;
138  if (write(fd, zerobuf.data, XLOG_BLCKSZ) != XLOG_BLCKSZ)
139  {
140  int save_errno = errno;
141 
142  close(fd);
143 
144  /*
145  * If write didn't set errno, assume problem is no disk space.
146  */
147  errno = save_errno ? save_errno : ENOSPC;
148  return NULL;
149  }
150  }
151 
152  if (lseek(fd, 0, SEEK_SET) != 0)
153  {
154  int save_errno = errno;
155 
156  close(fd);
157  errno = save_errno;
158  return NULL;
159  }
160  }
161 
162  /*
163  * fsync WAL file and containing directory, to ensure the file is
164  * persistently created and zeroed (if padded). That's particularly
165  * important when using synchronous mode, where the file is modified and
166  * fsynced in-place, without a directory fsync.
167  */
168  if (dir_data->sync)
169  {
170  if (fsync_fname(tmppath, false) != 0 ||
171  fsync_parent_path(tmppath) != 0)
172  {
173 #ifdef HAVE_LIBZ
174  if (dir_data->compression > 0)
175  gzclose(gzfp);
176  else
177 #endif
178  close(fd);
179  return NULL;
180  }
181  }
182 
183  f = pg_malloc0(sizeof(DirectoryMethodFile));
184 #ifdef HAVE_LIBZ
185  if (dir_data->compression > 0)
186  f->gzfp = gzfp;
187 #endif
188  f->fd = fd;
189  f->currpos = 0;
190  f->pathname = pg_strdup(pathname);
191  f->fullpath = pg_strdup(tmppath);
192  if (temp_suffix)
193  f->temp_suffix = pg_strdup(temp_suffix);
194 
195  return f;
196 }
int pg_file_create_mode
Definition: file_perm.c:19
#define write(a, b, c)
Definition: win32.h:14
def bytes(source, encoding='ascii', errors='strict')
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:671
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1271
static char * dir_get_file_name(const char *pathname, const char *temp_suffix)
Definition: walmethods.c:72
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
#define MAXPGPATH
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static DirectoryMethodData * dir_data
Definition: walmethods.c:47
void pg_free(void *ptr)
Definition: fe_memutils.c:105
static char * filename
Definition: pg_dumpall.c:92
#define close(a)
Definition: win32.h:12
char data[XLOG_BLCKSZ]
Definition: c.h:1149
#define snprintf
Definition: port.h:216
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3742

◆ dir_sync()

static int dir_sync ( Walfile  f)
static

Definition at line 304 of file walmethods.c.

References Assert, DirectoryMethodData::compression, fd(), fsync, and DirectoryMethodData::sync.

Referenced by CreateWalDirectoryMethod().

305 {
306  Assert(f != NULL);
307 
308  if (!dir_data->sync)
309  return 0;
310 
311 #ifdef HAVE_LIBZ
312  if (dir_data->compression > 0)
313  {
314  if (gzflush(((DirectoryMethodFile *) f)->gzfp, Z_SYNC_FLUSH) != Z_OK)
315  return -1;
316  }
317 #endif
318 
319  return fsync(((DirectoryMethodFile *) f)->fd);
320 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define fsync(fd)
Definition: win32_port.h:68
static DirectoryMethodData * dir_data
Definition: walmethods.c:47
#define Assert(condition)
Definition: c.h:804

◆ dir_write()

static ssize_t dir_write ( Walfile  f,
const void *  buf,
size_t  count 
)
static

Definition at line 199 of file walmethods.c.

References Assert, DirectoryMethodData::compression, DirectoryMethodFile::currpos, DirectoryMethodFile::fd, and write.

Referenced by CreateWalDirectoryMethod().

200 {
201  ssize_t r;
203 
204  Assert(f != NULL);
205 
206 #ifdef HAVE_LIBZ
207  if (dir_data->compression > 0)
208  r = (ssize_t) gzwrite(df->gzfp, buf, count);
209  else
210 #endif
211  r = write(df->fd, buf, count);
212  if (r > 0)
213  df->currpos += r;
214  return r;
215 }
#define write(a, b, c)
Definition: win32.h:14
static char * buf
Definition: pg_test_fsync.c:68
static DirectoryMethodData * dir_data
Definition: walmethods.c:47
#define Assert(condition)
Definition: c.h:804

◆ FreeWalDirectoryMethod()

void FreeWalDirectoryMethod ( void  )

Definition at line 402 of file walmethods.c.

References DirectoryMethodData::basedir, and pg_free().

Referenced by LogStreamerMain(), and StreamLog().

403 {
405  pg_free(dir_data);
406 }
static DirectoryMethodData * dir_data
Definition: walmethods.c:47
void pg_free(void *ptr)
Definition: fe_memutils.c:105

◆ FreeWalTarMethod()

void FreeWalTarMethod ( void  )

Definition at line 1068 of file walmethods.c.

References TarMethodData::compression, pg_free(), and TarMethodData::tarfilename.

Referenced by LogStreamerMain().

1069 {
1071 #ifdef HAVE_LIBZ
1072  if (tar_data->compression)
1073  pg_free(tar_data->zlibOut);
1074 #endif
1075  pg_free(tar_data);
1076 }
char * tarfilename
Definition: walmethods.c:425
void pg_free(void *ptr)
Definition: fe_memutils.c:105
static TarMethodData * tar_data
Definition: walmethods.c:436

◆ tar_close()

static int tar_close ( Walfile  f,
WalCloseMethod  method 
)
static

Definition at line 769 of file walmethods.c.

References Assert, CLOSE_NORMAL, CLOSE_UNLINK, TarMethodData::compression, TarMethodData::currentfile, TarMethodFile::currpos, TarMethodData::fd, ftruncate, header(), TarMethodFile::header, MemSet, TarMethodFile::ofs_start, TarMethodFile::pad_to_size, TarMethodFile::pathname, pg_free(), print_tar_number(), strlcpy(), TAR_BLOCK_SIZE, tar_clear_error, tar_get_current_pos(), tar_set_error, tar_sync(), tar_write(), tar_write_padding_data(), tarChecksum(), tarPaddingBytesRequired(), and write.

Referenced by CreateWalTarMethod(), and tar_finish().

770 {
771  ssize_t filesize;
772  int padding;
773  TarMethodFile *tf = (TarMethodFile *) f;
774 
775  Assert(f != NULL);
776  tar_clear_error();
777 
778  if (method == CLOSE_UNLINK)
779  {
780  if (tar_data->compression)
781  {
782  tar_set_error("unlink not supported with compression");
783  return -1;
784  }
785 
786  /*
787  * Unlink the file that we just wrote to the tar. We do this by
788  * truncating it to the start of the header. This is safe as we only
789  * allow writing of the very last file.
790  */
791  if (ftruncate(tar_data->fd, tf->ofs_start) != 0)
792  return -1;
793 
794  pg_free(tf->pathname);
795  pg_free(tf);
796  tar_data->currentfile = NULL;
797 
798  return 0;
799  }
800 
801  /*
802  * Pad the file itself with zeroes if necessary. Note that this is
803  * different from the tar format padding -- this is the padding we asked
804  * for when the file was opened.
805  */
806  if (tf->pad_to_size)
807  {
808  if (tar_data->compression)
809  {
810  /*
811  * A compressed tarfile is padded on close since we cannot know
812  * the size of the compressed output until the end.
813  */
814  size_t sizeleft = tf->pad_to_size - tf->currpos;
815 
816  if (sizeleft)
817  {
818  if (!tar_write_padding_data(tf, sizeleft))
819  return -1;
820  }
821  }
822  else
823  {
824  /*
825  * An uncompressed tarfile was padded on creation, so just adjust
826  * the current position as if we seeked to the end.
827  */
828  tf->currpos = tf->pad_to_size;
829  }
830  }
831 
832  /*
833  * Get the size of the file, and pad out to a multiple of the tar block
834  * size.
835  */
836  filesize = tar_get_current_pos(f);
837  padding = tarPaddingBytesRequired(filesize);
838  if (padding)
839  {
840  char zerobuf[TAR_BLOCK_SIZE];
841 
842  MemSet(zerobuf, 0, padding);
843  if (tar_write(f, zerobuf, padding) != padding)
844  return -1;
845  }
846 
847 
848 #ifdef HAVE_LIBZ
849  if (tar_data->compression)
850  {
851  /* Flush the current buffer */
852  if (!tar_write_compressed_data(NULL, 0, true))
853  {
854  errno = EINVAL;
855  return -1;
856  }
857  }
858 #endif
859 
860  /*
861  * Now go back and update the header with the correct filesize and
862  * possibly also renaming the file. We overwrite the entire current header
863  * when done, including the checksum.
864  */
865  print_tar_number(&(tf->header[124]), 12, filesize);
866 
867  if (method == CLOSE_NORMAL)
868 
869  /*
870  * We overwrite it with what it was before if we have no tempname,
871  * since we're going to write the buffer anyway.
872  */
873  strlcpy(&(tf->header[0]), tf->pathname, 100);
874 
875  print_tar_number(&(tf->header[148]), 8, tarChecksum(((TarMethodFile *) f)->header));
876  if (lseek(tar_data->fd, tf->ofs_start, SEEK_SET) != ((TarMethodFile *) f)->ofs_start)
877  return -1;
878  if (!tar_data->compression)
879  {
880  errno = 0;
882  {
883  /* if write didn't set errno, assume problem is no disk space */
884  if (errno == 0)
885  errno = ENOSPC;
886  return -1;
887  }
888  }
889 #ifdef HAVE_LIBZ
890  else
891  {
892  /* Turn off compression */
893  if (deflateParams(tar_data->zp, 0, 0) != Z_OK)
894  {
895  tar_set_error("could not change compression parameters");
896  return -1;
897  }
898 
899  /* Overwrite the header, assuming the size will be the same */
900  if (!tar_write_compressed_data(tar_data->currentfile->header,
901  TAR_BLOCK_SIZE, true))
902  return -1;
903 
904  /* Turn compression back on */
905  if (deflateParams(tar_data->zp, tar_data->compression, 0) != Z_OK)
906  {
907  tar_set_error("could not change compression parameters");
908  return -1;
909  }
910  }
911 #endif
912 
913  /* Move file pointer back down to end, so we can write the next file */
914  if (lseek(tar_data->fd, 0, SEEK_END) < 0)
915  return -1;
916 
917  /* Always fsync on close, so the padding gets fsynced */
918  if (tar_sync(f) < 0)
919  exit(1);
920 
921  /* Clean up and done */
922  pg_free(tf->pathname);
923  pg_free(tf);
924  tar_data->currentfile = NULL;
925 
926  return 0;
927 }
#define write(a, b, c)
Definition: win32.h:14
char * pathname
Definition: walmethods.c:419
#define MemSet(start, val, len)
Definition: c.h:1008
static ssize_t tar_write(Walfile f, const void *buf, size_t count)
Definition: walmethods.c:509
size_t pad_to_size
Definition: walmethods.c:420
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
#define tar_set_error(msg)
Definition: walmethods.c:439
static bool tar_write_padding_data(TarMethodFile *f, size_t bytes)
Definition: walmethods.c:540
static size_t tarPaddingBytesRequired(size_t len)
Definition: pgtar.h:40
static off_t tar_get_current_pos(Walfile f)
Definition: walmethods.c:741
int tarChecksum(char *header)
Definition: tar.c:90
TarMethodFile * currentfile
Definition: walmethods.c:429
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define Assert(condition)
Definition: c.h:804
char header[TAR_BLOCK_SIZE]
Definition: walmethods.c:418
void print_tar_number(char *s, int len, uint64 val)
Definition: tar.c:22
#define tar_clear_error()
Definition: walmethods.c:438
void pg_free(void *ptr)
Definition: fe_memutils.c:105
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:210
off_t ofs_start
Definition: walmethods.c:416
static TarMethodData * tar_data
Definition: walmethods.c:436
static int tar_sync(Walfile f)
Definition: walmethods.c:750
#define ftruncate(a, b)
Definition: win32_port.h:65

◆ tar_compression()

static int tar_compression ( void  )
static

Definition at line 735 of file walmethods.c.

References TarMethodData::compression.

Referenced by CreateWalTarMethod().

736 {
737  return tar_data->compression;
738 }
static TarMethodData * tar_data
Definition: walmethods.c:436

◆ tar_existsfile()

static bool tar_existsfile ( const char *  pathname)
static

Definition at line 930 of file walmethods.c.

References tar_clear_error.

Referenced by CreateWalTarMethod().

931 {
932  tar_clear_error();
933  /* We only deal with new tarfiles, so nothing externally created exists */
934  return false;
935 }
#define tar_clear_error()
Definition: walmethods.c:438

◆ tar_finish()

static bool tar_finish ( void  )
static

Definition at line 938 of file walmethods.c.

References close, CLOSE_NORMAL, TarMethodData::compression, TarMethodData::currentfile, TarMethodData::fd, fsync, fsync_fname(), fsync_parent_path(), MemSet, TarMethodData::sync, tar_clear_error, tar_close(), tar_set_error, TarMethodData::tarfilename, write, and ZLIB_OUT_SIZE.

Referenced by CreateWalTarMethod().

939 {
940  char zerobuf[1024];
941 
942  tar_clear_error();
943 
944  if (tar_data->currentfile)
945  {
947  return false;
948  }
949 
950  /* A tarfile always ends with two empty blocks */
951  MemSet(zerobuf, 0, sizeof(zerobuf));
952  if (!tar_data->compression)
953  {
954  errno = 0;
955  if (write(tar_data->fd, zerobuf, sizeof(zerobuf)) != sizeof(zerobuf))
956  {
957  /* if write didn't set errno, assume problem is no disk space */
958  if (errno == 0)
959  errno = ENOSPC;
960  return false;
961  }
962  }
963 #ifdef HAVE_LIBZ
964  else
965  {
966  if (!tar_write_compressed_data(zerobuf, sizeof(zerobuf), false))
967  return false;
968 
969  /* Also flush all data to make sure the gzip stream is finished */
970  tar_data->zp->next_in = NULL;
971  tar_data->zp->avail_in = 0;
972  while (true)
973  {
974  int r;
975 
976  r = deflate(tar_data->zp, Z_FINISH);
977 
978  if (r == Z_STREAM_ERROR)
979  {
980  tar_set_error("could not compress data");
981  return false;
982  }
983  if (tar_data->zp->avail_out < ZLIB_OUT_SIZE)
984  {
985  size_t len = ZLIB_OUT_SIZE - tar_data->zp->avail_out;
986 
987  errno = 0;
988  if (write(tar_data->fd, tar_data->zlibOut, len) != len)
989  {
990  /*
991  * If write didn't set errno, assume problem is no disk
992  * space.
993  */
994  if (errno == 0)
995  errno = ENOSPC;
996  return false;
997  }
998  }
999  if (r == Z_STREAM_END)
1000  break;
1001  }
1002 
1003  if (deflateEnd(tar_data->zp) != Z_OK)
1004  {
1005  tar_set_error("could not close compression stream");
1006  return false;
1007  }
1008  }
1009 #endif
1010 
1011  /* sync the empty blocks as well, since they're after the last file */
1012  if (tar_data->sync)
1013  {
1014  if (fsync(tar_data->fd) != 0)
1015  return false;
1016  }
1017 
1018  if (close(tar_data->fd) != 0)
1019  return false;
1020 
1021  tar_data->fd = -1;
1022 
1023  if (tar_data->sync)
1024  {
1025  if (fsync_fname(tar_data->tarfilename, false) != 0)
1026  return false;
1028  return false;
1029  }
1030 
1031  return true;
1032 }
#define write(a, b, c)
Definition: win32.h:14
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:671
#define MemSet(start, val, len)
Definition: c.h:1008
static int tar_close(Walfile f, WalCloseMethod method)
Definition: walmethods.c:769
#define fsync(fd)
Definition: win32_port.h:68
#define tar_set_error(msg)
Definition: walmethods.c:439
char * tarfilename
Definition: walmethods.c:425
TarMethodFile * currentfile
Definition: walmethods.c:429
#define tar_clear_error()
Definition: walmethods.c:438
#define ZLIB_OUT_SIZE
Definition: walmethods.c:31
#define close(a)
Definition: win32.h:12
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3742
static TarMethodData * tar_data
Definition: walmethods.c:436

◆ tar_get_current_pos()

static off_t tar_get_current_pos ( Walfile  f)
static

Definition at line 741 of file walmethods.c.

References Assert, and tar_clear_error.

Referenced by CreateWalTarMethod(), and tar_close().

742 {
743  Assert(f != NULL);
744  tar_clear_error();
745 
746  return ((TarMethodFile *) f)->currpos;
747 }
#define Assert(condition)
Definition: c.h:804
#define tar_clear_error()
Definition: walmethods.c:438

◆ tar_get_file_name()

static char* tar_get_file_name ( const char *  pathname,
const char *  temp_suffix 
)
static

Definition at line 560 of file walmethods.c.

References filename, MAXPGPATH, pg_malloc0(), and snprintf.

Referenced by CreateWalTarMethod(), and tar_open_for_write().

561 {
562  char *filename = pg_malloc0(MAXPGPATH * sizeof(char));
563 
564  snprintf(filename, MAXPGPATH, "%s%s",
565  pathname, temp_suffix ? temp_suffix : "");
566 
567  return filename;
568 }
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
#define MAXPGPATH
static char * filename
Definition: pg_dumpall.c:92
#define snprintf
Definition: port.h:216

◆ tar_get_file_size()

static ssize_t tar_get_file_size ( const char *  pathname)
static

Definition at line 725 of file walmethods.c.

References tar_clear_error.

Referenced by CreateWalTarMethod().

726 {
727  tar_clear_error();
728 
729  /* Currently not used, so not supported */
730  errno = ENOSYS;
731  return -1;
732 }
#define tar_clear_error()
Definition: walmethods.c:438

◆ tar_getlasterror()

static const char* tar_getlasterror ( void  )
static

Definition at line 442 of file walmethods.c.

References buf, TarMethodData::fd, TarMethodData::lasterror, strerror, tar_set_error, write, and ZLIB_OUT_SIZE.

Referenced by CreateWalTarMethod().

443 {
444  /*
445  * If a custom error is set, return that one. Otherwise, assume errno is
446  * set and return that one.
447  */
448  if (tar_data->lasterror[0])
449  return tar_data->lasterror;
450  return strerror(errno);
451 }
#define strerror
Definition: port.h:229
char lasterror[1024]
Definition: walmethods.c:430
static TarMethodData * tar_data
Definition: walmethods.c:436

◆ tar_open_for_write()

static Walfile tar_open_for_write ( const char *  pathname,
const char *  temp_suffix,
size_t  pad_to_size 
)
static

Definition at line 571 of file walmethods.c.

References Assert, TarMethodData::compression, TarMethodData::currentfile, TarMethodFile::currpos, TarMethodData::fd, TarMethodFile::header, TarMethodFile::ofs_start, TarMethodFile::pad_to_size, TarMethodFile::pathname, PG_BINARY, pg_file_create_mode, pg_free(), pg_malloc(), pg_malloc0(), pg_strdup(), S_IRUSR, S_IWUSR, TAR_BLOCK_SIZE, tar_clear_error, tar_get_file_name(), TAR_OK, tar_set_error, tar_write_padding_data(), tarCreateHeader(), TarMethodData::tarfilename, write, and ZLIB_OUT_SIZE.

Referenced by CreateWalTarMethod().

572 {
573  int save_errno;
574  char *tmppath;
575 
576  tar_clear_error();
577 
578  if (tar_data->fd < 0)
579  {
580  /*
581  * We open the tar file only when we first try to write to it.
582  */
583  tar_data->fd = open(tar_data->tarfilename,
584  O_WRONLY | O_CREAT | PG_BINARY,
586  if (tar_data->fd < 0)
587  return NULL;
588 
589 #ifdef HAVE_LIBZ
590  if (tar_data->compression)
591  {
592  tar_data->zp = (z_streamp) pg_malloc(sizeof(z_stream));
593  tar_data->zp->zalloc = Z_NULL;
594  tar_data->zp->zfree = Z_NULL;
595  tar_data->zp->opaque = Z_NULL;
596  tar_data->zp->next_out = tar_data->zlibOut;
597  tar_data->zp->avail_out = ZLIB_OUT_SIZE;
598 
599  /*
600  * Initialize deflation library. Adding the magic value 16 to the
601  * default 15 for the windowBits parameter makes the output be
602  * gzip instead of zlib.
603  */
604  if (deflateInit2(tar_data->zp, tar_data->compression, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK)
605  {
606  pg_free(tar_data->zp);
607  tar_data->zp = NULL;
608  tar_set_error("could not initialize compression library");
609  return NULL;
610  }
611  }
612 #endif
613 
614  /* There's no tar header itself, the file starts with regular files */
615  }
616 
617  Assert(tar_data->currentfile == NULL);
618  if (tar_data->currentfile != NULL)
619  {
620  tar_set_error("implementation error: tar files can't have more than one open file");
621  return NULL;
622  }
623 
625 
626  tmppath = tar_get_file_name(pathname, temp_suffix);
627 
628  /* Create a header with size set to 0 - we will fill out the size on close */
629  if (tarCreateHeader(tar_data->currentfile->header, tmppath, NULL, 0, S_IRUSR | S_IWUSR, 0, 0, time(NULL)) != TAR_OK)
630  {
632  pg_free(tmppath);
633  tar_data->currentfile = NULL;
634  tar_set_error("could not create tar header");
635  return NULL;
636  }
637 
638  pg_free(tmppath);
639 
640 #ifdef HAVE_LIBZ
641  if (tar_data->compression)
642  {
643  /* Flush existing data */
644  if (!tar_write_compressed_data(NULL, 0, true))
645  return NULL;
646 
647  /* Turn off compression for header */
648  if (deflateParams(tar_data->zp, 0, 0) != Z_OK)
649  {
650  tar_set_error("could not change compression parameters");
651  return NULL;
652  }
653  }
654 #endif
655 
656  tar_data->currentfile->ofs_start = lseek(tar_data->fd, 0, SEEK_CUR);
657  if (tar_data->currentfile->ofs_start == -1)
658  {
659  save_errno = errno;
661  tar_data->currentfile = NULL;
662  errno = save_errno;
663  return NULL;
664  }
666 
667  if (!tar_data->compression)
668  {
669  errno = 0;
672  {
673  save_errno = errno;
675  tar_data->currentfile = NULL;
676  /* if write didn't set errno, assume problem is no disk space */
677  errno = save_errno ? save_errno : ENOSPC;
678  return NULL;
679  }
680  }
681 #ifdef HAVE_LIBZ
682  else
683  {
684  /* Write header through the zlib APIs but with no compression */
685  if (!tar_write_compressed_data(tar_data->currentfile->header,
686  TAR_BLOCK_SIZE, true))
687  return NULL;
688 
689  /* Re-enable compression for the rest of the file */
690  if (deflateParams(tar_data->zp, tar_data->compression, 0) != Z_OK)
691  {
692  tar_set_error("could not change compression parameters");
693  return NULL;
694  }
695  }
696 #endif
697 
698  tar_data->currentfile->pathname = pg_strdup(pathname);
699 
700  /*
701  * Uncompressed files are padded on creation, but for compression we can't
702  * do that
703  */
704  if (pad_to_size)
705  {
706  tar_data->currentfile->pad_to_size = pad_to_size;
707  if (!tar_data->compression)
708  {
709  /* Uncompressed, so pad now */
711  /* Seek back to start */
712  if (lseek(tar_data->fd,
714  SEEK_SET) != tar_data->currentfile->ofs_start + TAR_BLOCK_SIZE)
715  return NULL;
716 
718  }
719  }
720 
721  return tar_data->currentfile;
722 }
int pg_file_create_mode
Definition: file_perm.c:19
static char * tar_get_file_name(const char *pathname, const char *temp_suffix)
Definition: walmethods.c:560
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
#define write(a, b, c)
Definition: win32.h:14
char * pathname
Definition: walmethods.c:419
Definition: pgtar.h:21
#define PG_BINARY
Definition: c.h:1271
size_t pad_to_size
Definition: walmethods.c:420
#define S_IWUSR
Definition: win32_port.h:283
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
z_stream * z_streamp
#define tar_set_error(msg)
Definition: walmethods.c:439
static bool tar_write_padding_data(TarMethodFile *f, size_t bytes)
Definition: walmethods.c:540
enum tarError tarCreateHeader(char *h, const char *filename, const char *linktarget, pgoff_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime)
Definition: tar.c:114
char * tarfilename
Definition: walmethods.c:425
TarMethodFile * currentfile
Definition: walmethods.c:429
#define Assert(condition)
Definition: c.h:804
char header[TAR_BLOCK_SIZE]
Definition: walmethods.c:418
#define tar_clear_error()
Definition: walmethods.c:438
void pg_free(void *ptr)
Definition: fe_memutils.c:105
#define ZLIB_OUT_SIZE
Definition: walmethods.c:31
#define S_IRUSR
Definition: win32_port.h:280
off_t ofs_start
Definition: walmethods.c:416
static TarMethodData * tar_data
Definition: walmethods.c:436

◆ tar_sync()

static int tar_sync ( Walfile  f)
static

Definition at line 750 of file walmethods.c.

References Assert, TarMethodData::compression, TarMethodData::fd, fsync, TarMethodData::sync, and tar_clear_error.

Referenced by CreateWalTarMethod(), and tar_close().

751 {
752  Assert(f != NULL);
753  tar_clear_error();
754 
755  if (!tar_data->sync)
756  return 0;
757 
758  /*
759  * Always sync the whole tarfile, because that's all we can do. This makes
760  * no sense on compressed files, so just ignore those.
761  */
762  if (tar_data->compression)
763  return 0;
764 
765  return fsync(tar_data->fd);
766 }
#define fsync(fd)
Definition: win32_port.h:68
#define Assert(condition)
Definition: c.h:804
#define tar_clear_error()
Definition: walmethods.c:438
static TarMethodData * tar_data
Definition: walmethods.c:436

◆ tar_write()

static ssize_t tar_write ( Walfile  f,
const void *  buf,
size_t  count 
)
static

Definition at line 509 of file walmethods.c.

References Assert, TarMethodData::compression, TarMethodData::fd, tar_clear_error, unconstify, and write.

Referenced by CreateWalTarMethod(), tar_close(), and tar_write_padding_data().

510 {
511  ssize_t r;
512 
513  Assert(f != NULL);
514  tar_clear_error();
515 
516  /* Tarfile will always be positioned at the end */
517  if (!tar_data->compression)
518  {
519  r = write(tar_data->fd, buf, count);
520  if (r > 0)
521  ((TarMethodFile *) f)->currpos += r;
522  return r;
523  }
524 #ifdef HAVE_LIBZ
525  else
526  {
527  if (!tar_write_compressed_data(unconstify(void *, buf), count, false))
528  return -1;
529  ((TarMethodFile *) f)->currpos += count;
530  return count;
531  }
532 #else
533  else
534  /* Can't happen - compression enabled with no libz */
535  return -1;
536 #endif
537 }
#define write(a, b, c)
Definition: win32.h:14
static char * buf
Definition: pg_test_fsync.c:68
#define unconstify(underlying_type, expr)
Definition: c.h:1243
#define Assert(condition)
Definition: c.h:804
#define tar_clear_error()
Definition: walmethods.c:438
static TarMethodData * tar_data
Definition: walmethods.c:436

◆ tar_write_padding_data()

static bool tar_write_padding_data ( TarMethodFile f,
size_t  bytes 
)
static

Definition at line 540 of file walmethods.c.

References generate_unaccent_rules::bytes(), PGAlignedXLogBlock::data, Min, and tar_write().

Referenced by tar_close(), and tar_open_for_write().

541 {
542  PGAlignedXLogBlock zerobuf;
543  size_t bytesleft = bytes;
544 
545  memset(zerobuf.data, 0, XLOG_BLCKSZ);
546  while (bytesleft)
547  {
548  size_t bytestowrite = Min(bytesleft, XLOG_BLCKSZ);
549  ssize_t r = tar_write(f, zerobuf.data, bytestowrite);
550 
551  if (r < 0)
552  return false;
553  bytesleft -= r;
554  }
555 
556  return true;
557 }
def bytes(source, encoding='ascii', errors='strict')
#define Min(x, y)
Definition: c.h:986
static ssize_t tar_write(Walfile f, const void *buf, size_t count)
Definition: walmethods.c:509
char data[XLOG_BLCKSZ]
Definition: c.h:1149

Variable Documentation

◆ dir_data

DirectoryMethodData* dir_data = NULL
static

Definition at line 47 of file walmethods.c.

◆ tar_data

TarMethodData* tar_data = NULL
static

Definition at line 436 of file walmethods.c.