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 "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 206 of file astreamer_file.c.

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

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

References Assert, and PG_USED_FOR_ASSERTS_ONLY.

◆ astreamer_extractor_free()

static void astreamer_extractor_free ( astreamer streamer)
static

Definition at line 393 of file astreamer_file.c.

394{
395 astreamer_extractor *mystreamer = (astreamer_extractor *) streamer;
396
397 pfree(mystreamer->basepath);
398 pfree(mystreamer);
399}
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 186 of file astreamer_file.c.

189{
190 astreamer_extractor *streamer;
191
192 streamer = palloc0(sizeof(astreamer_extractor));
193 *((const astreamer_ops **) &streamer->base.bbs_ops) =
195 streamer->basepath = pstrdup(basepath);
196 streamer->link_map = link_map;
197 streamer->report_output_file = report_output_file;
198
199 return &streamer->base;
200}
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 107 of file astreamer_file.c.

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

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 134 of file astreamer_file.c.

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

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 152 of file astreamer_file.c.

153{
154 astreamer_plain_writer *mystreamer;
155
156 mystreamer = (astreamer_plain_writer *) streamer;
157
158 Assert(!mystreamer->should_close_file);
159 Assert(mystreamer->base.bbs_next == NULL);
160
161 pfree(mystreamer->pathname);
162 pfree(mystreamer);
163}
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 81 of file astreamer_file.c.

82{
83 astreamer_plain_writer *streamer;
84
85 streamer = palloc0(sizeof(astreamer_plain_writer));
86 *((const astreamer_ops **) &streamer->base.bbs_ops) =
88
89 streamer->pathname = pstrdup(pathname);
90 streamer->file = file;
91
92 if (file == NULL)
93 {
94 streamer->file = fopen(pathname, "wb");
95 if (streamer->file == NULL)
96 pg_fatal("could not create file \"%s\": %m", pathname);
97 streamer->should_close_file = true;
98 }
99
100 return &streamer->base;
101}
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 358 of file astreamer_file.c.

359{
360 FILE *file;
361
362 file = fopen(filename, "wb");
363 if (file == NULL)
364 pg_fatal("could not create file \"%s\": %m", filename);
365
366#ifndef WIN32
367 if (chmod(filename, mode))
368 pg_fatal("could not set permissions on file \"%s\": %m",
369 filename);
370#endif
371
372 return file;
373}
static PgChecksumMode mode
Definition: pg_checksums.c:55
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 320 of file astreamer_file.c.

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

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

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 295 of file astreamer_file.c.

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

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 65 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 49 of file astreamer_file.c.

Referenced by astreamer_plain_writer_new().