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, off_t offset)
 

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 525 of file file_utils.c.

529 {
530  PGFileType result;
531 
532  /*
533  * Some systems tell us the type directly in the dirent struct, but that's
534  * a BSD and Linux extension not required by POSIX. Even when the
535  * interface is present, sometimes the type is unknown, depending on the
536  * filesystem.
537  */
538 #if defined(DT_REG) && defined(DT_DIR) && defined(DT_LNK)
539  if (de->d_type == DT_REG)
540  result = PGFILETYPE_REG;
541  else if (de->d_type == DT_DIR)
542  result = PGFILETYPE_DIR;
543  else if (de->d_type == DT_LNK && !look_through_symlinks)
544  result = PGFILETYPE_LNK;
545  else
546  result = PGFILETYPE_UNKNOWN;
547 #else
548  result = PGFILETYPE_UNKNOWN;
549 #endif
550 
551  if (result == PGFILETYPE_UNKNOWN)
552  {
553  struct stat fst;
554  int sret;
555 
556 
557  if (look_through_symlinks)
558  sret = stat(path, &fst);
559  else
560  sret = lstat(path, &fst);
561 
562  if (sret < 0)
563  {
564  result = PGFILETYPE_ERROR;
565 #ifdef FRONTEND
566  pg_log_generic(elevel, PG_LOG_PRIMARY, "could not stat file \"%s\": %m", path);
567 #else
568  ereport(elevel,
570  errmsg("could not stat file \"%s\": %m", path)));
571 #endif
572  }
573  else if (S_ISREG(fst.st_mode))
574  result = PGFILETYPE_REG;
575  else if (S_ISDIR(fst.st_mode))
576  result = PGFILETYPE_DIR;
577  else if (S_ISLNK(fst.st_mode))
578  result = PGFILETYPE_LNK;
579  }
580 
581  return result;
582 }
#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:284
#define lstat(path, sb)
Definition: win32_port.h:285
#define S_ISDIR(m)
Definition: win32_port.h:325
#define S_ISLNK(m)
Definition: win32_port.h:344
#define S_ISREG(m)
Definition: win32_port.h:328

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,
off_t  offset 
)

Definition at line 660 of file file_utils.c.

661 {
662  static const PGIOAlignedBlock zbuffer = {{0}}; /* worth BLCKSZ */
663  void *zerobuf_addr = unconstify(PGIOAlignedBlock *, &zbuffer)->data;
664  struct iovec iov[PG_IOV_MAX];
665  size_t remaining_size = size;
666  ssize_t total_written = 0;
667 
668  /* Loop, writing as many blocks as we can for each system call. */
669  while (remaining_size > 0)
670  {
671  int iovcnt = 0;
672  ssize_t written;
673 
674  for (; iovcnt < PG_IOV_MAX && remaining_size > 0; iovcnt++)
675  {
676  size_t this_iov_size;
677 
678  iov[iovcnt].iov_base = zerobuf_addr;
679 
680  if (remaining_size < BLCKSZ)
681  this_iov_size = remaining_size;
682  else
683  this_iov_size = BLCKSZ;
684 
685  iov[iovcnt].iov_len = this_iov_size;
686  remaining_size -= this_iov_size;
687  }
688 
689  written = pg_pwritev_with_retry(fd, iov, iovcnt, offset);
690 
691  if (written < 0)
692  return written;
693 
694  offset += written;
695  total_written += written;
696  }
697 
698  Assert(total_written == size);
699 
700  return total_written;
701 }
#define unconstify(underlying_type, expr)
Definition: c.h:1255
ssize_t pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
Definition: file_utils.c:591
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

References Assert(), fd(), PG_IOV_MAX, pg_pwritev_with_retry(), and unconstify.

Referenced by dir_open_for_write(), FileZero(), 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 591 of file file_utils.c.

592 {
593  struct iovec iov_copy[PG_IOV_MAX];
594  ssize_t sum = 0;
595  ssize_t part;
596 
597  /* We'd better have space to make a copy, in case we need to retry. */
598  if (iovcnt > PG_IOV_MAX)
599  {
600  errno = EINVAL;
601  return -1;
602  }
603 
604  for (;;)
605  {
606  /* Write as much as we can. */
607  part = pg_pwritev(fd, iov, iovcnt, offset);
608  if (part < 0)
609  return -1;
610 
611 #ifdef SIMULATE_SHORT_WRITE
612  part = Min(part, 4096);
613 #endif
614 
615  /* Count our progress. */
616  sum += part;
617  offset += part;
618 
619  /* Step over iovecs that are done. */
620  while (iovcnt > 0 && iov->iov_len <= part)
621  {
622  part -= iov->iov_len;
623  ++iov;
624  --iovcnt;
625  }
626 
627  /* Are they all done? */
628  if (iovcnt == 0)
629  {
630  /* We don't expect the kernel to write more than requested. */
631  Assert(part == 0);
632  break;
633  }
634 
635  /*
636  * Move whatever's left to the front of our mutable copy and adjust
637  * the leading iovec.
638  */
639  Assert(iovcnt > 0);
640  memmove(iov_copy, iov, sizeof(*iov) * iovcnt);
641  Assert(iov->iov_len > part);
642  iov_copy[0].iov_base = (char *) iov_copy[0].iov_base + part;
643  iov_copy[0].iov_len -= part;
644  iov = iov_copy;
645  }
646 
647  return sum;
648 }
#define Min(x, y)
Definition: c.h:993
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().