PostgreSQL Source Code  git master
file_utils.c File Reference
#include "postgres.h"
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "common/file_utils.h"
#include "port/pg_iovec.h"
Include dependency graph for file_utils.c:

Go to the source code of this file.

Functions

PGFileType get_dirent_type (const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
 
ssize_t pg_pwritev_with_retry (int fd, const struct iovec *iov, int iovcnt, off_t offset)
 
ssize_t pg_pwrite_zeros (int fd, size_t size)
 

Function Documentation

◆ get_dirent_type()

PGFileType get_dirent_type ( const char *  path,
const struct dirent de,
bool  look_through_symlinks,
int  elevel 
)

Definition at line 406 of file file_utils.c.

410 {
411  PGFileType result;
412 
413  /*
414  * Some systems tell us the type directly in the dirent struct, but that's
415  * a BSD and Linux extension not required by POSIX. Even when the
416  * interface is present, sometimes the type is unknown, depending on the
417  * filesystem.
418  */
419 #if defined(DT_REG) && defined(DT_DIR) && defined(DT_LNK)
420  if (de->d_type == DT_REG)
421  result = PGFILETYPE_REG;
422  else if (de->d_type == DT_DIR)
423  result = PGFILETYPE_DIR;
424  else if (de->d_type == DT_LNK && !look_through_symlinks)
425  result = PGFILETYPE_LNK;
426  else
427  result = PGFILETYPE_UNKNOWN;
428 #else
429  result = PGFILETYPE_UNKNOWN;
430 #endif
431 
432  if (result == PGFILETYPE_UNKNOWN)
433  {
434  struct stat fst;
435  int sret;
436 
437 
438  if (look_through_symlinks)
439  sret = stat(path, &fst);
440  else
441  sret = lstat(path, &fst);
442 
443  if (sret < 0)
444  {
445  result = PGFILETYPE_ERROR;
446 #ifdef FRONTEND
447  pg_log_generic(elevel, PG_LOG_PRIMARY, "could not stat file \"%s\": %m", path);
448 #else
449  ereport(elevel,
451  errmsg("could not stat file \"%s\": %m", path)));
452 #endif
453  }
454  else if (S_ISREG(fst.st_mode))
455  result = PGFILETYPE_REG;
456  else if (S_ISDIR(fst.st_mode))
457  result = PGFILETYPE_DIR;
458  else if (S_ISLNK(fst.st_mode))
459  result = PGFILETYPE_LNK;
460  }
461 
462  return result;
463 }
#define DT_DIR
Definition: dirent.h:28
#define DT_REG
Definition: dirent.h:30
#define DT_LNK
Definition: dirent.h:31
int errcode_for_file_access(void)
Definition: elog.c:881
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereport(elevel,...)
Definition: elog.h:149
PGFileType
Definition: file_utils.h:19
@ PGFILETYPE_LNK
Definition: file_utils.h:24
@ PGFILETYPE_UNKNOWN
Definition: file_utils.h:21
@ PGFILETYPE_DIR
Definition: file_utils.h:23
@ PGFILETYPE_REG
Definition: file_utils.h:22
@ PGFILETYPE_ERROR
Definition: file_utils.h:20
void pg_log_generic(enum pg_log_level level, enum pg_log_part part, const char *pg_restrict fmt,...)
Definition: logging.c:205
@ PG_LOG_PRIMARY
Definition: logging.h:67
unsigned char d_type
Definition: dirent.h:13
#define stat
Definition: win32_port.h:286
#define lstat(path, sb)
Definition: win32_port.h:287
#define S_ISDIR(m)
Definition: win32_port.h:327
#define S_ISLNK(m)
Definition: win32_port.h:346
#define S_ISREG(m)
Definition: win32_port.h:330

References dirent::d_type, DT_DIR, DT_LNK, DT_REG, ereport, errcode_for_file_access(), errmsg(), lstat, pg_log_generic(), PG_LOG_PRIMARY, PGFILETYPE_DIR, PGFILETYPE_ERROR, PGFILETYPE_LNK, PGFILETYPE_REG, PGFILETYPE_UNKNOWN, S_ISDIR, S_ISLNK, S_ISREG, stat::st_mode, and stat.

Referenced by CheckPointLogicalRewriteHeap(), CheckPointSnapBuild(), CheckTablespaceDirectory(), copydir(), do_pg_backup_start(), GetConfFilesInDir(), pg_tzenumerate_next(), RemovePgTempFilesInDir(), RemoveXlogFile(), rmtree(), StartupReplicationSlots(), and walkdir().

◆ pg_pwrite_zeros()

ssize_t pg_pwrite_zeros ( int  fd,
size_t  size 
)

Definition at line 540 of file file_utils.c.

541 {
542  PGAlignedBlock zbuffer; /* worth BLCKSZ */
543  size_t zbuffer_sz;
544  struct iovec iov[PG_IOV_MAX];
545  int blocks;
546  size_t remaining_size = 0;
547  int i;
548  ssize_t written;
549  ssize_t total_written = 0;
550 
551  zbuffer_sz = sizeof(zbuffer.data);
552 
553  /* Zero-fill the buffer. */
554  memset(zbuffer.data, 0, zbuffer_sz);
555 
556  /* Prepare to write out a lot of copies of our zero buffer at once. */
557  for (i = 0; i < lengthof(iov); ++i)
558  {
559  iov[i].iov_base = zbuffer.data;
560  iov[i].iov_len = zbuffer_sz;
561  }
562 
563  /* Loop, writing as many blocks as we can for each system call. */
564  blocks = size / zbuffer_sz;
565  remaining_size = size % zbuffer_sz;
566  for (i = 0; i < blocks;)
567  {
568  int iovcnt = Min(blocks - i, lengthof(iov));
569  off_t offset = i * zbuffer_sz;
570 
571  written = pg_pwritev_with_retry(fd, iov, iovcnt, offset);
572 
573  if (written < 0)
574  return written;
575 
576  i += iovcnt;
577  total_written += written;
578  }
579 
580  /* Now, write the remaining size, if any, of the file with zeros. */
581  if (remaining_size > 0)
582  {
583  /* We'll never write more than one block here */
584  int iovcnt = 1;
585 
586  /* Jump on to the end of previously written blocks */
587  off_t offset = i * zbuffer_sz;
588 
589  iov[0].iov_len = remaining_size;
590 
591  written = pg_pwritev_with_retry(fd, iov, iovcnt, offset);
592 
593  if (written < 0)
594  return written;
595 
596  total_written += written;
597  }
598 
599  Assert(total_written == size);
600 
601  return total_written;
602 }
#define Min(x, y)
Definition: c.h:988
#define lengthof(array)
Definition: c.h:772
ssize_t pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
Definition: file_utils.c:472
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
#define PG_IOV_MAX
Definition: pg_iovec.h:36
static int fd(const char *x, int i)
Definition: preproc-init.c:105
char data[BLCKSZ]
Definition: c.h:1130

References Assert(), PGAlignedBlock::data, fd(), i, lengthof, Min, PG_IOV_MAX, and pg_pwritev_with_retry().

Referenced by dir_open_for_write(), and XLogFileInitInternal().

◆ pg_pwritev_with_retry()

ssize_t pg_pwritev_with_retry ( int  fd,
const struct iovec *  iov,
int  iovcnt,
off_t  offset 
)

Definition at line 472 of file file_utils.c.

473 {
474  struct iovec iov_copy[PG_IOV_MAX];
475  ssize_t sum = 0;
476  ssize_t part;
477 
478  /* We'd better have space to make a copy, in case we need to retry. */
479  if (iovcnt > PG_IOV_MAX)
480  {
481  errno = EINVAL;
482  return -1;
483  }
484 
485  for (;;)
486  {
487  /* Write as much as we can. */
488  part = pg_pwritev(fd, iov, iovcnt, offset);
489  if (part < 0)
490  return -1;
491 
492 #ifdef SIMULATE_SHORT_WRITE
493  part = Min(part, 4096);
494 #endif
495 
496  /* Count our progress. */
497  sum += part;
498  offset += part;
499 
500  /* Step over iovecs that are done. */
501  while (iovcnt > 0 && iov->iov_len <= part)
502  {
503  part -= iov->iov_len;
504  ++iov;
505  --iovcnt;
506  }
507 
508  /* Are they all done? */
509  if (iovcnt == 0)
510  {
511  /* We don't expect the kernel to write more than requested. */
512  Assert(part == 0);
513  break;
514  }
515 
516  /*
517  * Move whatever's left to the front of our mutable copy and adjust
518  * the leading iovec.
519  */
520  Assert(iovcnt > 0);
521  memmove(iov_copy, iov, sizeof(*iov) * iovcnt);
522  Assert(iov->iov_len > part);
523  iov_copy[0].iov_base = (char *) iov_copy[0].iov_base + part;
524  iov_copy[0].iov_len -= part;
525  iov = iov_copy;
526  }
527 
528  return sum;
529 }
ssize_t pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
Definition: pwritev.c:22

References Assert(), fd(), Min, PG_IOV_MAX, and pg_pwritev().

Referenced by pg_pwrite_zeros().