package fileops import ( "io/fs" "os" "golang.org/x/sys/windows" ) func preserveFileMetadata(file *os.File, target string, _ fs.FileInfo) error { sd, err := windows.GetNamedSecurityInfo(target, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION) if err != nil { return err } owner, _, err := sd.Owner() if err != nil { return err } dacl, _, err := sd.DACL() if err != nil { return err } control, _, err := sd.Control() if err != nil { return err } flags := windows.SECURITY_INFORMATION(windows.DACL_SECURITY_INFORMATION | windows.UNPROTECTED_DACL_SECURITY_INFORMATION) if control&windows.SE_DACL_PROTECTED != 0 { flags = windows.DACL_SECURITY_INFORMATION | windows.PROTECTED_DACL_SECURITY_INFORMATION } // The initial temp owner is already the current process user. Avoid asking // for an unnecessary owner change on ordinary non-elevated saves. user, err := windows.GetCurrentProcessToken().GetTokenUser() if err != nil { return err } if owner != nil && !owner.Equals(user.User.Sid) { flags |= windows.OWNER_SECURITY_INFORMATION } else { owner = nil } return windows.SetNamedSecurityInfo(file.Name(), windows.SE_FILE_OBJECT, flags, owner, nil, dacl, nil) }