X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=remote%2Fsync%2Ffiles.go;h=56c9ff0003af3c35d9153ba471655479bbc33efe;hb=37d75eb672f05d758a5e8fb82e32dfd50e7416dd;hp=a11b77e8107d8265ed33dac5acfeaf8aa89a4e6e;hpb=ca3a64ec7f80ee21f167fd2b1b3de03349c65028;p=safcm%2Fsafcm.git diff --git a/remote/sync/files.go b/remote/sync/files.go index a11b77e..56c9ff0 100644 --- a/remote/sync/files.go +++ b/remote/sync/files.go @@ -1,6 +1,6 @@ // MsgSyncReq: copy files to the remote host -// Copyright (C) 2021 Simon Ruderich +// Copyright (C) 2021-2023 Simon Ruderich // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -15,6 +15,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +//go:build !windows // +build !windows package sync @@ -131,6 +132,14 @@ func (s *Sync) syncFile(file *safcm.File, changed *bool) error { parentFd, baseName, err := OpenParentDirectoryNoSymlinks(file.Path) if err != nil { + if os.IsNotExist(err) && s.req.DryRun { + change.Created = true + debugf("will create (parent missing)") + *changed = true + debugf("dry-run, skipping changes") + s.resp.FileChanges = append(s.resp.FileChanges, change) + return nil + } return err } defer unix.Close(parentFd) @@ -249,7 +258,7 @@ reopen: } // Compare file content (if possible) - switch change.Old.Mode.Type() { + switch change.Old.Mode.Type() { //nolint:exhaustive case 0: // regular file x, err := io.ReadAll(oldFh) if err != nil { @@ -324,7 +333,7 @@ reopen: err := unix.Unlinkat(parentFd, baseName, 0) if err != nil && !os.IsNotExist(err) { err2 := unix.Unlinkat(parentFd, baseName, - AT_REMOVEDIR) + unix.AT_REMOVEDIR) if err2 != nil && !os.IsNotExist(err2) { // See src/os/file_unix.go in Go's sources if err2 == unix.ENOTDIR { @@ -383,6 +392,10 @@ reopen: // the error when the user tries to access this // directory (access for the group will fail though). mode := change.Old.Mode & fs.ModePerm & 0700 + // Retain setgid/sticky so that the behavior does not + // change when creating and removing files. + mode |= change.Old.Mode & fs.ModeSetgid + mode |= change.Old.Mode & fs.ModeSticky debugf("chmodding %#o (temporary)", mode) err := oldFh.Chmod(mode) if err != nil { @@ -441,7 +454,7 @@ reopen: err = unix.Fchownat(parentFd, tmpBase, file.Uid, file.Gid, unix.AT_SYMLINK_NOFOLLOW) if err != nil { - unix.Unlinkat(parentFd, tmpBase, 0) + unix.Unlinkat(parentFd, tmpBase, 0) //nolint:errcheck return err } // Permissions are irrelevant for symlinks (on most systems) @@ -453,7 +466,7 @@ reopen: debugf("renaming %q", slashpath.Join(dir, tmpBase)) err = unix.Renameat(parentFd, tmpBase, parentFd, baseName) if err != nil { - unix.Unlinkat(parentFd, tmpBase, 0) + unix.Unlinkat(parentFd, tmpBase, 0) //nolint:errcheck return err } // To guarantee durability fsync must be called on a parent directory @@ -654,31 +667,31 @@ func WriteTempAt(dirFd int, base string, data []byte, uid, gid int, _, err = fh.Write(data) if err != nil { fh.Close() - unix.Unlinkat(dirFd, tmpBase, 0) + unix.Unlinkat(dirFd, tmpBase, 0) //nolint:errcheck return "", err } // createTempAt() creates the file with 0600 err = fh.Chown(uid, gid) if err != nil { fh.Close() - unix.Unlinkat(dirFd, tmpBase, 0) + unix.Unlinkat(dirFd, tmpBase, 0) //nolint:errcheck return "", err } err = fh.Chmod(mode) if err != nil { fh.Close() - unix.Unlinkat(dirFd, tmpBase, 0) + unix.Unlinkat(dirFd, tmpBase, 0) //nolint:errcheck return "", err } err = fh.Sync() if err != nil { fh.Close() - unix.Unlinkat(dirFd, tmpBase, 0) + unix.Unlinkat(dirFd, tmpBase, 0) //nolint:errcheck return "", err } err = fh.Close() if err != nil { - unix.Unlinkat(dirFd, tmpBase, 0) + unix.Unlinkat(dirFd, tmpBase, 0) //nolint:errcheck return "", err }