PostgreSQL Source Code  git master
bbstreamer_file.c File Reference
#include "postgres_fe.h"
#include <unistd.h>
#include "bbstreamer.h"
#include "common/logging.h"
#include "common/file_perm.h"
#include "common/string.h"
Include dependency graph for bbstreamer_file.c:

Go to the source code of this file.

Data Structures

struct  bbstreamer_plain_writer
 
struct  bbstreamer_extractor
 

Typedefs

typedef struct bbstreamer_plain_writer bbstreamer_plain_writer
 
typedef struct bbstreamer_extractor bbstreamer_extractor
 

Functions

static void bbstreamer_plain_writer_content (bbstreamer *streamer, bbstreamer_member *member, const char *data, int len, bbstreamer_archive_context context)
 
static void bbstreamer_plain_writer_finalize (bbstreamer *streamer)
 
static void bbstreamer_plain_writer_free (bbstreamer *streamer)
 
static void bbstreamer_extractor_content (bbstreamer *streamer, bbstreamer_member *member, const char *data, int len, bbstreamer_archive_context context)
 
static void bbstreamer_extractor_finalize (bbstreamer *streamer)
 
static void bbstreamer_extractor_free (bbstreamer *streamer)
 
static void extract_directory (const char *filename, mode_t mode)
 
static void extract_link (const char *filename, const char *linktarget)
 
static FILE * create_file_for_extract (const char *filename, mode_t mode)
 
bbstreamerbbstreamer_plain_writer_new (char *pathname, FILE *file)
 
bbstreamerbbstreamer_extractor_new (const char *basepath, const char *(*link_map)(const char *), void(*report_output_file)(const char *))
 

Variables

const bbstreamer_ops bbstreamer_plain_writer_ops
 
const bbstreamer_ops bbstreamer_extractor_ops
 

Typedef Documentation

◆ bbstreamer_extractor

◆ bbstreamer_plain_writer

Function Documentation

◆ bbstreamer_extractor_content()

static void bbstreamer_extractor_content ( bbstreamer streamer,
bbstreamer_member member,
const char *  data,
int  len,
bbstreamer_archive_context  context 
)
static

Definition at line 203 of file bbstreamer_file.c.

206 {
207  bbstreamer_extractor *mystreamer = (bbstreamer_extractor *) streamer;
208  int fnamelen;
209 
210  Assert(member != NULL || context == BBSTREAMER_ARCHIVE_TRAILER);
211  Assert(context != BBSTREAMER_UNKNOWN);
212 
213  switch (context)
214  {
216  Assert(mystreamer->file == NULL);
217 
218  /* Prepend basepath. */
219  snprintf(mystreamer->filename, sizeof(mystreamer->filename),
220  "%s/%s", mystreamer->basepath, member->pathname);
221 
222  /* Remove any trailing slash. */
223  fnamelen = strlen(mystreamer->filename);
224  if (mystreamer->filename[fnamelen - 1] == '/')
225  mystreamer->filename[fnamelen - 1] = '\0';
226 
227  /* Dispatch based on file type. */
228  if (member->is_directory)
229  extract_directory(mystreamer->filename, member->mode);
230  else if (member->is_link)
231  {
232  const char *linktarget = member->linktarget;
233 
234  if (mystreamer->link_map)
235  linktarget = mystreamer->link_map(linktarget);
236  extract_link(mystreamer->filename, linktarget);
237  }
238  else
239  mystreamer->file =
240  create_file_for_extract(mystreamer->filename,
241  member->mode);
242 
243  /* Report output file change. */
244  if (mystreamer->report_output_file)
245  mystreamer->report_output_file(mystreamer->filename);
246  break;
247 
249  if (mystreamer->file == NULL)
250  break;
251 
252  errno = 0;
253  if (len > 0 && fwrite(data, len, 1, mystreamer->file) != 1)
254  {
255  /* if write didn't set errno, assume problem is no disk space */
256  if (errno == 0)
257  errno = ENOSPC;
258  pg_fatal("could not write to file \"%s\": %m",
259  mystreamer->filename);
260  }
261  break;
262 
264  if (mystreamer->file == NULL)
265  break;
266  fclose(mystreamer->file);
267  mystreamer->file = NULL;
268  break;
269 
271  break;
272 
273  default:
274  /* Shouldn't happen. */
275  pg_fatal("unexpected state while extracting archive");
276  }
277 }
@ BBSTREAMER_ARCHIVE_TRAILER
Definition: bbstreamer.h:59
@ BBSTREAMER_MEMBER_HEADER
Definition: bbstreamer.h:56
@ BBSTREAMER_MEMBER_TRAILER
Definition: bbstreamer.h:58
@ BBSTREAMER_UNKNOWN
Definition: bbstreamer.h:55
@ BBSTREAMER_MEMBER_CONTENTS
Definition: bbstreamer.h:57
static void extract_directory(const char *filename, mode_t mode)
static FILE * create_file_for_extract(const char *filename, mode_t mode)
static void extract_link(const char *filename, const char *linktarget)
Assert(fmt[strlen(fmt) - 1] !='\n')
#define pg_fatal(...)
const void size_t len
const void * data
#define snprintf
Definition: port.h:225
const char *(* link_map)(const char *)
void(* report_output_file)(const char *)
char filename[MAXPGPATH]
char pathname[MAXPGPATH]
Definition: bbstreamer.h:72
char linktarget[MAXPGPATH]
Definition: bbstreamer.h:79

References Assert(), bbstreamer_extractor::basepath, BBSTREAMER_ARCHIVE_TRAILER, BBSTREAMER_MEMBER_CONTENTS, BBSTREAMER_MEMBER_HEADER, BBSTREAMER_MEMBER_TRAILER, BBSTREAMER_UNKNOWN, create_file_for_extract(), data, extract_directory(), extract_link(), bbstreamer_extractor::file, bbstreamer_extractor::filename, bbstreamer_member::is_directory, bbstreamer_member::is_link, len, bbstreamer_extractor::link_map, bbstreamer_member::linktarget, bbstreamer_member::mode, bbstreamer_member::pathname, pg_fatal, bbstreamer_extractor::report_output_file, and snprintf.

◆ bbstreamer_extractor_finalize()

static void bbstreamer_extractor_finalize ( bbstreamer streamer)
static

Definition at line 356 of file bbstreamer_file.c.

357 {
359  = (bbstreamer_extractor *) streamer;
360 
361  Assert(mystreamer->file == NULL);
362 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:155

References Assert(), and PG_USED_FOR_ASSERTS_ONLY.

◆ bbstreamer_extractor_free()

static void bbstreamer_extractor_free ( bbstreamer streamer)
static

Definition at line 368 of file bbstreamer_file.c.

369 {
370  bbstreamer_extractor *mystreamer = (bbstreamer_extractor *) streamer;
371 
372  pfree(mystreamer->basepath);
373  pfree(mystreamer);
374 }
void pfree(void *pointer)
Definition: mcxt.c:1175

References bbstreamer_extractor::basepath, and pfree().

◆ bbstreamer_extractor_new()

bbstreamer* bbstreamer_extractor_new ( const char *  basepath,
const char *(*)(const char *)  link_map,
void(*)(const char *)  report_output_file 
)

Definition at line 183 of file bbstreamer_file.c.

186 {
187  bbstreamer_extractor *streamer;
188 
189  streamer = palloc0(sizeof(bbstreamer_extractor));
190  *((const bbstreamer_ops **) &streamer->base.bbs_ops) =
192  streamer->basepath = pstrdup(basepath);
193  streamer->link_map = link_map;
194  streamer->report_output_file = report_output_file;
195 
196  return &streamer->base;
197 }
const bbstreamer_ops bbstreamer_extractor_ops
char * pstrdup(const char *in)
Definition: mcxt.c:1305
void * palloc0(Size size)
Definition: mcxt.c:1099
const bbstreamer_ops * bbs_ops
Definition: bbstreamer.h:100

References bbstreamer_extractor::base, bbstreamer_extractor::basepath, bbstreamer::bbs_ops, bbstreamer_extractor_ops, bbstreamer_extractor::link_map, palloc0(), pstrdup(), and bbstreamer_extractor::report_output_file.

Referenced by CreateBackupStreamer().

◆ bbstreamer_plain_writer_content()

static void bbstreamer_plain_writer_content ( bbstreamer streamer,
bbstreamer_member member,
const char *  data,
int  len,
bbstreamer_archive_context  context 
)
static

Definition at line 104 of file bbstreamer_file.c.

107 {
108  bbstreamer_plain_writer *mystreamer;
109 
110  mystreamer = (bbstreamer_plain_writer *) streamer;
111 
112  if (len == 0)
113  return;
114 
115  errno = 0;
116  if (fwrite(data, len, 1, mystreamer->file) != 1)
117  {
118  /* if write didn't set errno, assume problem is no disk space */
119  if (errno == 0)
120  errno = ENOSPC;
121  pg_fatal("could not write to file \"%s\": %m",
122  mystreamer->pathname);
123  }
124 }

References data, bbstreamer_plain_writer::file, len, bbstreamer_plain_writer::pathname, and pg_fatal.

◆ bbstreamer_plain_writer_finalize()

static void bbstreamer_plain_writer_finalize ( bbstreamer streamer)
static

Definition at line 131 of file bbstreamer_file.c.

132 {
133  bbstreamer_plain_writer *mystreamer;
134 
135  mystreamer = (bbstreamer_plain_writer *) streamer;
136 
137  if (mystreamer->should_close_file && fclose(mystreamer->file) != 0)
138  pg_fatal("could not close file \"%s\": %m",
139  mystreamer->pathname);
140 
141  mystreamer->file = NULL;
142  mystreamer->should_close_file = false;
143 }

References bbstreamer_plain_writer::file, bbstreamer_plain_writer::pathname, pg_fatal, and bbstreamer_plain_writer::should_close_file.

◆ bbstreamer_plain_writer_free()

static void bbstreamer_plain_writer_free ( bbstreamer streamer)
static

Definition at line 149 of file bbstreamer_file.c.

150 {
151  bbstreamer_plain_writer *mystreamer;
152 
153  mystreamer = (bbstreamer_plain_writer *) streamer;
154 
155  Assert(!mystreamer->should_close_file);
156  Assert(mystreamer->base.bbs_next == NULL);
157 
158  pfree(mystreamer->pathname);
159  pfree(mystreamer);
160 }
bbstreamer * bbs_next
Definition: bbstreamer.h:101

References Assert(), bbstreamer_plain_writer::base, bbstreamer::bbs_next, bbstreamer_plain_writer::pathname, pfree(), and bbstreamer_plain_writer::should_close_file.

◆ bbstreamer_plain_writer_new()

bbstreamer* bbstreamer_plain_writer_new ( char *  pathname,
FILE *  file 
)

Definition at line 78 of file bbstreamer_file.c.

79 {
80  bbstreamer_plain_writer *streamer;
81 
82  streamer = palloc0(sizeof(bbstreamer_plain_writer));
83  *((const bbstreamer_ops **) &streamer->base.bbs_ops) =
85 
86  streamer->pathname = pstrdup(pathname);
87  streamer->file = file;
88 
89  if (file == NULL)
90  {
91  streamer->file = fopen(pathname, "wb");
92  if (streamer->file == NULL)
93  pg_fatal("could not create file \"%s\": %m", pathname);
94  streamer->should_close_file = true;
95  }
96 
97  return &streamer->base;
98 }
const bbstreamer_ops bbstreamer_plain_writer_ops

References bbstreamer_plain_writer::base, bbstreamer::bbs_ops, bbstreamer_plain_writer_ops, bbstreamer_plain_writer::file, palloc0(), bbstreamer_plain_writer::pathname, pg_fatal, pstrdup(), and bbstreamer_plain_writer::should_close_file.

Referenced by CreateBackupStreamer().

◆ create_file_for_extract()

static FILE * create_file_for_extract ( const char *  filename,
mode_t  mode 
)
static

Definition at line 333 of file bbstreamer_file.c.

334 {
335  FILE *file;
336 
337  file = fopen(filename, "wb");
338  if (file == NULL)
339  pg_fatal("could not create file \"%s\": %m", filename);
340 
341 #ifndef WIN32
342  if (chmod(filename, mode))
343  pg_fatal("could not set permissions on file \"%s\": %m",
344  filename);
345 #endif
346 
347  return file;
348 }
static PgChecksumMode mode
Definition: pg_checksums.c:65
static char * filename
Definition: pg_dumpall.c:94

References filename, mode, and pg_fatal.

Referenced by bbstreamer_extractor_content().

◆ extract_directory()

static void extract_directory ( const char *  filename,
mode_t  mode 
)
static

Definition at line 283 of file bbstreamer_file.c.

284 {
285  if (mkdir(filename, pg_dir_create_mode) != 0)
286  {
287  /*
288  * When streaming WAL, pg_wal (or pg_xlog for pre-9.6 clusters) will
289  * have been created by the wal receiver process. Also, when the WAL
290  * directory location was specified, pg_wal (or pg_xlog) has already
291  * been created as a symbolic link before starting the actual backup.
292  * So just ignore creation failures on related directories.
293  */
294  if (!((pg_str_endswith(filename, "/pg_wal") ||
295  pg_str_endswith(filename, "/pg_xlog") ||
296  pg_str_endswith(filename, "/archive_status")) &&
297  errno == EEXIST))
298  pg_fatal("could not create directory \"%s\": %m",
299  filename);
300  }
301 
302 #ifndef WIN32
303  if (chmod(filename, mode))
304  pg_fatal("could not set permissions on directory \"%s\": %m",
305  filename);
306 #endif
307 }
int pg_dir_create_mode
Definition: file_perm.c:18
bool pg_str_endswith(const char *str, const char *end)
Definition: string.c:31
#define mkdir(a, b)
Definition: win32_port.h:71

References filename, mkdir, mode, pg_dir_create_mode, pg_fatal, and pg_str_endswith().

Referenced by bbstreamer_extractor_content().

◆ extract_link()

static void extract_link ( const char *  filename,
const char *  linktarget 
)
static

Definition at line 320 of file bbstreamer_file.c.

321 {
322  if (symlink(linktarget, filename) != 0)
323  pg_fatal("could not create symbolic link from \"%s\" to \"%s\": %m",
324  filename, linktarget);
325 }
#define symlink(oldpath, newpath)
Definition: win32_port.h:235

References filename, pg_fatal, and symlink.

Referenced by bbstreamer_extractor_content().

Variable Documentation

◆ bbstreamer_extractor_ops

const bbstreamer_ops bbstreamer_extractor_ops
Initial value:
= {
}
static void bbstreamer_extractor_free(bbstreamer *streamer)
static void bbstreamer_extractor_finalize(bbstreamer *streamer)
static void bbstreamer_extractor_content(bbstreamer *streamer, bbstreamer_member *member, const char *data, int len, bbstreamer_archive_context context)

Definition at line 62 of file bbstreamer_file.c.

Referenced by bbstreamer_extractor_new().

◆ bbstreamer_plain_writer_ops

const bbstreamer_ops bbstreamer_plain_writer_ops
Initial value:
= {
}
static void bbstreamer_plain_writer_free(bbstreamer *streamer)
static void bbstreamer_plain_writer_content(bbstreamer *streamer, bbstreamer_member *member, const char *data, int len, bbstreamer_archive_context context)
static void bbstreamer_plain_writer_finalize(bbstreamer *streamer)

Definition at line 46 of file bbstreamer_file.c.

Referenced by bbstreamer_plain_writer_new().