PostgreSQL Source Code  git master
bbstreamer_file.c File Reference
#include "postgres_fe.h"
#include <unistd.h>
#include "bbstreamer.h"
#include "common/file_perm.h"
#include "common/logging.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 *))
 
static bool should_allow_existing_directory (const char *pathname)
 

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);
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:238
tree context
Definition: radixtree.h:1797
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, context, 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 378 of file bbstreamer_file.c.

379 {
381  = (bbstreamer_extractor *) streamer;
382 
383  Assert(mystreamer->file == NULL);
384 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:169

References Assert(), and PG_USED_FOR_ASSERTS_ONLY.

◆ bbstreamer_extractor_free()

static void bbstreamer_extractor_free ( bbstreamer streamer)
static

Definition at line 390 of file bbstreamer_file.c.

391 {
392  bbstreamer_extractor *mystreamer = (bbstreamer_extractor *) streamer;
393 
394  pfree(mystreamer->basepath);
395  pfree(mystreamer);
396 }
void pfree(void *pointer)
Definition: mcxt.c:1508

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:1683
void * palloc0(Size size)
Definition: mcxt.c:1334
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 355 of file bbstreamer_file.c.

356 {
357  FILE *file;
358 
359  file = fopen(filename, "wb");
360  if (file == NULL)
361  pg_fatal("could not create file \"%s\": %m", filename);
362 
363 #ifndef WIN32
364  if (chmod(filename, mode))
365  pg_fatal("could not set permissions on file \"%s\": %m",
366  filename);
367 #endif
368 
369  return file;
370 }
static PgChecksumMode mode
Definition: pg_checksums.c:56
static char * filename
Definition: pg_dumpall.c:121

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 317 of file bbstreamer_file.c.

318 {
319  if (mkdir(filename, pg_dir_create_mode) != 0 &&
320  (errno != EEXIST || !should_allow_existing_directory(filename)))
321  pg_fatal("could not create directory \"%s\": %m",
322  filename);
323 
324 #ifndef WIN32
325  if (chmod(filename, mode))
326  pg_fatal("could not set permissions on directory \"%s\": %m",
327  filename);
328 #endif
329 }
static bool should_allow_existing_directory(const char *pathname)
int pg_dir_create_mode
Definition: file_perm.c:18
#define mkdir(a, b)
Definition: win32_port.h:80

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

Referenced by bbstreamer_extractor_content().

◆ extract_link()

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

Definition at line 342 of file bbstreamer_file.c.

343 {
344  if (symlink(linktarget, filename) != 0)
345  pg_fatal("could not create symbolic link from \"%s\" to \"%s\": %m",
346  filename, linktarget);
347 }
#define symlink(oldpath, newpath)
Definition: win32_port.h:235

References filename, pg_fatal, and symlink.

Referenced by bbstreamer_extractor_content().

◆ should_allow_existing_directory()

static bool should_allow_existing_directory ( const char *  pathname)
static

Definition at line 292 of file bbstreamer_file.c.

293 {
294  const char *filename = last_dir_separator(pathname) + 1;
295 
296  if (strcmp(filename, "pg_wal") == 0 ||
297  strcmp(filename, "pg_xlog") == 0 ||
298  strcmp(filename, "archive_status") == 0 ||
299  strcmp(filename, "summaries") == 0 ||
300  strcmp(filename, "pg_tblspc") == 0)
301  return true;
302 
303  if (strspn(filename, "0123456789") == strlen(filename))
304  {
305  const char *pg_tblspc = strstr(pathname, "/pg_tblspc/");
306 
307  return pg_tblspc != NULL && pg_tblspc + 11 == filename;
308  }
309 
310  return false;
311 }
char * last_dir_separator(const char *filename)
Definition: path.c:139

References filename, and last_dir_separator().

Referenced by extract_directory().

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().