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

Go to the source code of this file.

Data Structures

struct  astreamer_plain_writer
 
struct  astreamer_extractor
 

Typedefs

typedef struct astreamer_plain_writer astreamer_plain_writer
 
typedef struct astreamer_extractor astreamer_extractor
 

Functions

static void astreamer_plain_writer_content (astreamer *streamer, astreamer_member *member, const char *data, int len, astreamer_archive_context context)
 
static void astreamer_plain_writer_finalize (astreamer *streamer)
 
static void astreamer_plain_writer_free (astreamer *streamer)
 
static void astreamer_extractor_content (astreamer *streamer, astreamer_member *member, const char *data, int len, astreamer_archive_context context)
 
static void astreamer_extractor_finalize (astreamer *streamer)
 
static void astreamer_extractor_free (astreamer *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)
 
astreamerastreamer_plain_writer_new (char *pathname, FILE *file)
 
astreamerastreamer_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

static const astreamer_ops astreamer_plain_writer_ops
 
static const astreamer_ops astreamer_extractor_ops
 

Typedef Documentation

◆ astreamer_extractor

◆ astreamer_plain_writer

Function Documentation

◆ astreamer_extractor_content()

static void astreamer_extractor_content ( astreamer streamer,
astreamer_member member,
const char *  data,
int  len,
astreamer_archive_context  context 
)
static

Definition at line 207 of file astreamer_file.c.

210 {
211  astreamer_extractor *mystreamer = (astreamer_extractor *) streamer;
212  int fnamelen;
213 
214  Assert(member != NULL || context == ASTREAMER_ARCHIVE_TRAILER);
216 
217  switch (context)
218  {
220  Assert(mystreamer->file == NULL);
221 
222  /* Prepend basepath. */
223  snprintf(mystreamer->filename, sizeof(mystreamer->filename),
224  "%s/%s", mystreamer->basepath, member->pathname);
225 
226  /* Remove any trailing slash. */
227  fnamelen = strlen(mystreamer->filename);
228  if (mystreamer->filename[fnamelen - 1] == '/')
229  mystreamer->filename[fnamelen - 1] = '\0';
230 
231  /* Dispatch based on file type. */
232  if (member->is_directory)
233  extract_directory(mystreamer->filename, member->mode);
234  else if (member->is_link)
235  {
236  const char *linktarget = member->linktarget;
237 
238  if (mystreamer->link_map)
239  linktarget = mystreamer->link_map(linktarget);
240  extract_link(mystreamer->filename, linktarget);
241  }
242  else
243  mystreamer->file =
244  create_file_for_extract(mystreamer->filename,
245  member->mode);
246 
247  /* Report output file change. */
248  if (mystreamer->report_output_file)
249  mystreamer->report_output_file(mystreamer->filename);
250  break;
251 
253  if (mystreamer->file == NULL)
254  break;
255 
256  errno = 0;
257  if (len > 0 && fwrite(data, len, 1, mystreamer->file) != 1)
258  {
259  /* if write didn't set errno, assume problem is no disk space */
260  if (errno == 0)
261  errno = ENOSPC;
262  pg_fatal("could not write to file \"%s\": %m",
263  mystreamer->filename);
264  }
265  break;
266 
268  if (mystreamer->file == NULL)
269  break;
270  fclose(mystreamer->file);
271  mystreamer->file = NULL;
272  break;
273 
275  break;
276 
277  default:
278  /* Shouldn't happen. */
279  pg_fatal("unexpected state while extracting archive");
280  }
281 }
@ ASTREAMER_MEMBER_HEADER
Definition: astreamer.h:65
@ ASTREAMER_MEMBER_CONTENTS
Definition: astreamer.h:66
@ ASTREAMER_MEMBER_TRAILER
Definition: astreamer.h:67
@ ASTREAMER_ARCHIVE_TRAILER
Definition: astreamer.h:68
@ ASTREAMER_UNKNOWN
Definition: astreamer.h:64
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)
#define Assert(condition)
Definition: c.h:849
#define pg_fatal(...)
const void size_t len
const void * data
#define snprintf
Definition: port.h:238
tree context
Definition: radixtree.h:1835
void(* report_output_file)(const char *)
char filename[MAXPGPATH]
const char *(* link_map)(const char *)
char linktarget[MAXPGPATH]
Definition: astreamer.h:88
char pathname[MAXPGPATH]
Definition: astreamer.h:81

References Assert, ASTREAMER_ARCHIVE_TRAILER, ASTREAMER_MEMBER_CONTENTS, ASTREAMER_MEMBER_HEADER, ASTREAMER_MEMBER_TRAILER, ASTREAMER_UNKNOWN, astreamer_extractor::basepath, context, create_file_for_extract(), data, extract_directory(), extract_link(), astreamer_extractor::file, astreamer_extractor::filename, astreamer_member::is_directory, astreamer_member::is_link, len, astreamer_extractor::link_map, astreamer_member::linktarget, astreamer_member::mode, astreamer_member::pathname, pg_fatal, astreamer_extractor::report_output_file, and snprintf.

◆ astreamer_extractor_finalize()

static void astreamer_extractor_finalize ( astreamer streamer)
static

Definition at line 382 of file astreamer_file.c.

383 {
385  = (astreamer_extractor *) streamer;
386 
387  Assert(mystreamer->file == NULL);
388 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:185

References Assert, and PG_USED_FOR_ASSERTS_ONLY.

◆ astreamer_extractor_free()

static void astreamer_extractor_free ( astreamer streamer)
static

Definition at line 394 of file astreamer_file.c.

395 {
396  astreamer_extractor *mystreamer = (astreamer_extractor *) streamer;
397 
398  pfree(mystreamer->basepath);
399  pfree(mystreamer);
400 }
void pfree(void *pointer)
Definition: mcxt.c:1521

References astreamer_extractor::basepath, and pfree().

◆ astreamer_extractor_new()

astreamer* astreamer_extractor_new ( const char *  basepath,
const char *(*)(const char *)  link_map,
void(*)(const char *)  report_output_file 
)

Definition at line 187 of file astreamer_file.c.

190 {
191  astreamer_extractor *streamer;
192 
193  streamer = palloc0(sizeof(astreamer_extractor));
194  *((const astreamer_ops **) &streamer->base.bbs_ops) =
196  streamer->basepath = pstrdup(basepath);
197  streamer->link_map = link_map;
198  streamer->report_output_file = report_output_file;
199 
200  return &streamer->base;
201 }
static const astreamer_ops astreamer_extractor_ops
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void * palloc0(Size size)
Definition: mcxt.c:1347
const astreamer_ops * bbs_ops
Definition: astreamer.h:109

References astreamer_extractor_ops, astreamer_extractor::base, astreamer_extractor::basepath, astreamer::bbs_ops, astreamer_extractor::link_map, palloc0(), pstrdup(), and astreamer_extractor::report_output_file.

Referenced by CreateBackupStreamer().

◆ astreamer_plain_writer_content()

static void astreamer_plain_writer_content ( astreamer streamer,
astreamer_member member,
const char *  data,
int  len,
astreamer_archive_context  context 
)
static

Definition at line 108 of file astreamer_file.c.

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

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

◆ astreamer_plain_writer_finalize()

static void astreamer_plain_writer_finalize ( astreamer streamer)
static

Definition at line 135 of file astreamer_file.c.

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

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

◆ astreamer_plain_writer_free()

static void astreamer_plain_writer_free ( astreamer streamer)
static

Definition at line 153 of file astreamer_file.c.

154 {
155  astreamer_plain_writer *mystreamer;
156 
157  mystreamer = (astreamer_plain_writer *) streamer;
158 
159  Assert(!mystreamer->should_close_file);
160  Assert(mystreamer->base.bbs_next == NULL);
161 
162  pfree(mystreamer->pathname);
163  pfree(mystreamer);
164 }
astreamer * bbs_next
Definition: astreamer.h:110

References Assert, astreamer_plain_writer::base, astreamer::bbs_next, astreamer_plain_writer::pathname, pfree(), and astreamer_plain_writer::should_close_file.

◆ astreamer_plain_writer_new()

astreamer* astreamer_plain_writer_new ( char *  pathname,
FILE *  file 
)

Definition at line 82 of file astreamer_file.c.

83 {
84  astreamer_plain_writer *streamer;
85 
86  streamer = palloc0(sizeof(astreamer_plain_writer));
87  *((const astreamer_ops **) &streamer->base.bbs_ops) =
89 
90  streamer->pathname = pstrdup(pathname);
91  streamer->file = file;
92 
93  if (file == NULL)
94  {
95  streamer->file = fopen(pathname, "wb");
96  if (streamer->file == NULL)
97  pg_fatal("could not create file \"%s\": %m", pathname);
98  streamer->should_close_file = true;
99  }
100 
101  return &streamer->base;
102 }
static const astreamer_ops astreamer_plain_writer_ops

References astreamer_plain_writer_ops, astreamer_plain_writer::base, astreamer::bbs_ops, astreamer_plain_writer::file, palloc0(), astreamer_plain_writer::pathname, pg_fatal, pstrdup(), and astreamer_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 359 of file astreamer_file.c.

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

References filename, mode, and pg_fatal.

Referenced by astreamer_extractor_content().

◆ extract_directory()

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

Definition at line 321 of file astreamer_file.c.

322 {
323  if (mkdir(filename, pg_dir_create_mode) != 0 &&
324  (errno != EEXIST || !should_allow_existing_directory(filename)))
325  pg_fatal("could not create directory \"%s\": %m",
326  filename);
327 
328 #ifndef WIN32
329  if (chmod(filename, mode))
330  pg_fatal("could not set permissions on directory \"%s\": %m",
331  filename);
332 #endif
333 }
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 astreamer_extractor_content().

◆ extract_link()

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

Definition at line 346 of file astreamer_file.c.

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

References filename, pg_fatal, and symlink.

Referenced by astreamer_extractor_content().

◆ should_allow_existing_directory()

static bool should_allow_existing_directory ( const char *  pathname)
static

Definition at line 296 of file astreamer_file.c.

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

References filename, and last_dir_separator().

Referenced by extract_directory().

Variable Documentation

◆ astreamer_extractor_ops

const astreamer_ops astreamer_extractor_ops
static
Initial value:
= {
}
static void astreamer_extractor_finalize(astreamer *streamer)
static void astreamer_extractor_free(astreamer *streamer)
static void astreamer_extractor_content(astreamer *streamer, astreamer_member *member, const char *data, int len, astreamer_archive_context context)

Definition at line 66 of file astreamer_file.c.

Referenced by astreamer_extractor_new().

◆ astreamer_plain_writer_ops

const astreamer_ops astreamer_plain_writer_ops
static
Initial value:
= {
}
static void astreamer_plain_writer_content(astreamer *streamer, astreamer_member *member, const char *data, int len, astreamer_archive_context context)
static void astreamer_plain_writer_finalize(astreamer *streamer)
static void astreamer_plain_writer_free(astreamer *streamer)

Definition at line 50 of file astreamer_file.c.

Referenced by astreamer_plain_writer_new().