// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//go:build !windows
// +build !windows
package sync
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 {
// 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 {
unix.Unlinkat(parentFd, tmpBase, 0)
return err
}
+ // To guarantee durability fsync must be called on a parent directory
+ // after adding, renaming or removing files therein.
+ //
+ // Calling sync on the files itself is not enough according to POSIX;
+ // man 2 fsync: "Calling fsync() does not necessarily ensure that the
+ // entry in the directory containing the file has also reached disk.
+ // For that an explicit fsync() on a file descriptor for the directory
+ // is also needed."
err = unix.Fsync(parentFd)
if err != nil {
return err
}
dir = ".."
parts = []string{filepath.Base(wd)}
- } else if parts[0] != "." {
+ } else {
// Relative path: start at the current directory
dir = "."
+ if parts[0] == "." {
+ parts = parts[1:]
+ }
}
dirFd, err := unix.Openat(unix.AT_FDCWD, dir, openReadonlyFlags, 0)
return os.NewFile(uintptr(fd), ""), tmpBase, nil
}
-
-// SyncPath syncs path, which should be a directory. To guarantee durability
-// it must be called on a parent directory after adding, renaming or removing
-// files therein.
-//
-// Calling sync on the files itself is not enough according to POSIX; man 2
-// fsync: "Calling fsync() does not necessarily ensure that the entry in the
-// directory containing the file has also reached disk. For that an explicit
-// fsync() on a file descriptor for the directory is also needed."
-func SyncPath(path string) error {
- x, err := os.Open(path)
- if err != nil {
- return err
- }
- err = x.Sync()
- closeErr := x.Close()
- if err != nil {
- return err
- }
- return closeErr
-}