Skip .DS_Store files in server side utils
authorDaniel Gustafsson <[email protected]>
Tue, 13 Feb 2024 12:47:12 +0000 (13:47 +0100)
committerDaniel Gustafsson <[email protected]>
Tue, 13 Feb 2024 12:47:12 +0000 (13:47 +0100)
The macOS Finder application creates .DS_Store files in directories
when opened,  which creates problems for serverside utilities which
expect all files to be PostgreSQL specific files.  Skip these files
when encountered in pg_checksums, pg_rewind and pg_basebackup.

This was extracted from a larger patchset for skipping hidden files
and system files, where the concencus was to just skip these. Since
this is equally likely to happen in every version, backpatch to all
supported versions.

Reported-by: Mark Guertin <[email protected]>
Reviewed-by: Michael Paquier <[email protected]>
Reviewed-by: Tobias Bussmann <[email protected]>
Discussion: https://postgr.es/m/E258CE50-AB0E-455D-8AAD-BB4FE8F882FB@gmail.com
Backpatch-through: v12

doc/src/sgml/protocol.sgml
doc/src/sgml/ref/pg_basebackup.sgml
doc/src/sgml/ref/pg_rewind.sgml
src/backend/backup/basebackup.c
src/bin/pg_basebackup/t/010_pg_basebackup.pl
src/bin/pg_checksums/pg_checksums.c
src/bin/pg_checksums/t/002_actions.pl
src/bin/pg_rewind/filemap.c
src/bin/pg_rewind/t/003_extrafiles.pl

index ed1d62f5f8a5276b427a82f53c29429a4bb16607..05d6cc42da34924b4469380b646e1fc2f6eadab1 100644 (file)
@@ -3127,7 +3127,7 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
          <para>
           Files other than regular files and directories, such as symbolic
           links (other than for the directories listed above) and special
-          device files, are skipped.  (Symbolic links
+          device and operating system files, are skipped.  (Symbolic links
           in <filename>pg_tblspc</filename> are maintained.)
          </para>
         </listitem>
index e411ddbf456ec3df434b3ef1699f5a508e02e955..88c689e72590644069daab57b0890286c4029702 100644 (file)
@@ -965,7 +965,8 @@ PostgreSQL documentation
    The backup will include all files in the data directory and tablespaces,
    including the configuration files and any additional files placed in the
    directory by third parties, except certain temporary files managed by
-   PostgreSQL.  But only regular files and directories are copied, except that
+   PostgreSQL and operating system files.  But only regular files and
+   directories are copied, except that
    symbolic links used for tablespaces are preserved.  Symbolic links pointing
    to certain directories known to PostgreSQL are copied as empty directories.
    Other symbolic links and special device files are skipped.
index 8e0000d39fb5437b2a0c2a3741613647c5426dbb..841bd49fc748190eea30bb7f7dc260040a120e12 100644 (file)
@@ -403,8 +403,9 @@ GRANT EXECUTE ON function pg_catalog.pg_read_binary_file(text, bigint, bigint, b
       <filename>backup_label</filename>,
       <filename>tablespace_map</filename>,
       <filename>pg_internal.init</filename>,
-      <filename>postmaster.opts</filename>, and
-      <filename>postmaster.pid</filename>, as well as any file or directory
+      <filename>postmaster.opts</filename>,
+      <filename>postmaster.pid</filename> and
+      <filename>.DS_Store</filename> as well as any file or directory
       beginning with <filename>pgsql_tmp</filename>, are omitted.
      </para>
     </step>
index d5b8ca21b748729d11cc99ccb0abef4bbb6ec1cb..c7a2cbb13e7acb6f458d425018df1e038254b74f 100644 (file)
@@ -1265,6 +1265,10 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
                    strlen(PG_TEMP_FILE_PREFIX)) == 0)
            continue;
 
+       /* Skip macOS system files */
+       if (strcmp(de->d_name, ".DS_Store") == 0)
+           continue;
+
        /*
         * Check if the postmaster has signaled us to exit, and abort with an
         * error in that case. The error handler further up will call
index 42a09d0da3b8766bfcac28bac9045a20ee1f1598..86cc01a640b6f8e026a71f935d8d7da985cf9bdc 100644 (file)
@@ -3,6 +3,7 @@
 
 use strict;
 use warnings FATAL => 'all';
+use Config;
 use File::Basename qw(basename dirname);
 use File::Path     qw(rmtree);
 use PostgreSQL::Test::Cluster;
@@ -179,6 +180,16 @@ foreach my $filename (
    close $file;
 }
 
+# Test that macOS system files are skipped. Only test on non-macOS systems
+# however since creating incorrect .DS_Store files on a macOS system may have
+# unintended side effects.
+if ($Config{osname} ne 'darwin')
+{
+   open my $file, '>>', "$pgdata/.DS_Store";
+   print $file "DONOTCOPY";
+   close $file;
+}
+
 # Connect to a database to create global/pg_internal.init.  If this is removed
 # the test to ensure global/pg_internal.init is not copied will return a false
 # positive.
@@ -248,6 +259,12 @@ foreach my $filename (
    ok(!-f "$tempdir/backup/$filename", "$filename not copied");
 }
 
+# We only test .DS_Store files being skipped on non-macOS systems
+if ($Config{osname} ne 'darwin')
+{
+   ok(!-f "$tempdir/backup/.DS_Store", ".DS_Store not copied");
+}
+
 # Unlogged relation forks other than init should not be copied
 ok(-f "$tempdir/backup/${baseUnloggedPath}_init",
    'unlogged init fork in backup');
index 6fc13264181b3623d2f409f5cbe20e5655e39653..9e6fd435f6069b6c0901c771ad0ee166e5393745 100644 (file)
@@ -329,6 +329,10 @@ scan_directory(const char *basedir, const char *subdir, bool sizeonly)
                    strlen(PG_TEMP_FILES_DIR)) == 0)
            continue;
 
+       /* Skip macOS system files */
+       if (strcmp(de->d_name, ".DS_Store") == 0)
+           continue;
+
        snprintf(fn, sizeof(fn), "%s/%s", path, de->d_name);
        if (lstat(fn, &st) < 0)
            pg_fatal("could not stat file \"%s\": %m", fn);
index f83cf67a0fa26da065649c58d0feb37622f4bd7d..2faf2f45907a9e2e4a7703b924c1b48781c55d7f 100644 (file)
@@ -6,6 +6,7 @@
 
 use strict;
 use warnings FATAL => 'all';
+use Config;
 use PostgreSQL::Test::Cluster;
 use PostgreSQL::Test::Utils;
 
@@ -114,6 +115,12 @@ append_to_file "$pgdata/global/pgsql_tmp/1.1", "foo";
 append_to_file "$pgdata/global/pg_internal.init", "foo";
 append_to_file "$pgdata/global/pg_internal.init.123", "foo";
 
+# These are non-postgres macOS files, which should be ignored by the scan.
+# Only perform this test on non-macOS systems though as creating incorrect
+# system files may have side effects on macOS.
+append_to_file "$pgdata/global/.DS_Store", "foo"
+   unless ($Config{osname} eq 'darwin');
+
 # Enable checksums.
 command_ok([ 'pg_checksums', '--enable', '--no-sync', '-D', $pgdata ],
    "checksums successfully enabled in cluster");
index 0894c317bfef04cf351615a146c49a40f7ba8496..255ddf2ffaf490e50c1264985fa7258e0859333e 100644 (file)
@@ -647,6 +647,10 @@ decide_file_action(file_entry_t *entry)
    if (strcmp(path, "global/pg_control") == 0)
        return FILE_ACTION_NONE;
 
+   /* Skip macOS system files */
+   if (strstr(path, ".DS_Store") != NULL)
+       return FILE_ACTION_NONE;
+
    /*
     * Remove all files matching the exclusion filters in the target.
     */
index bab4b73d31ffd18db4f295c40c6e2b495a48c67e..94ac55d5f0501f2590efcd64de6966f43fa84901 100644 (file)
@@ -5,6 +5,7 @@
 
 use strict;
 use warnings FATAL => 'all';
+use Config;
 use PostgreSQL::Test::Utils;
 use Test::More;
 
@@ -53,6 +54,10 @@ sub run_test
    append_to_file
      "$test_standby_datadir/tst_standby_dir/standby_subdir/standby_file4",
      "in standby4";
+   # Skip testing .DS_Store files on macOS to avoid risk of side effects
+   append_to_file
+     "$test_standby_datadir/tst_standby_dir/.DS_Store",
+     "macOS system file" unless ($Config{osname} eq 'darwin');
 
    mkdir "$test_primary_datadir/tst_primary_dir";
    append_to_file "$test_primary_datadir/tst_primary_dir/primary_file1",