-1

fsync doc states

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.

I'm trying to sync a directory to the network mapped drive using SMB on windows, similar to what fsync does on Linux.

The following go code snippet which works fine if the directory is stored on a local drive but fails if it is on a network mapped folder.

func main() {
    dir := "Z:\\smb-test" // Path to network mapped drive
    f, err := openDir(dir)
    if err != nil {
        log.Fatal(err)
    }
    // Works fine if the path is located on a local disk but
    // fails if the directory is on a network mapped drive
    if err := f.Sync(); err != nil {
        log.Fatal(err)
    }
    if err := f.Close(); err != nil {
        log.Fatal(err)
    }
}

func openDir(path string) (*os.File, error) {
    fd, err := openDirWin(path)
    if err != nil {
        return nil, err
    }
    return os.NewFile(uintptr(fd), path), nil
}

func openDirWin(path string) (fd syscall.Handle, err error) {
    pathp, err := syscall.UTF16PtrFromString(path)
    if err != nil {
        return syscall.InvalidHandle, err
    }
    access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE)
    sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE)
    createmode := uint32(syscall.OPEN_EXISTING)
    fl := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS)
    return syscall.CreateFile(pathp, access, sharemode, nil, createmode, fl, 0)
}

The program fails with

Z:\\smb-test Incorrect function.

MSDN states that the handle passed in should either be a handle to a file, or to a volume, but says nothing about directories. https://learn.microsoft.com/en-us/windows/desktop/api/FileAPI/nf-fileapi-flushfilebuffers

And FlushFileBuffers is not listed as a function that accepts directory handles https://learn.microsoft.com/en-us/windows/desktop/fileio/obtaining-a-handle-to-a-directory

I also noticed the flushfilebuffers system call fails with Invalid Device Request for a network mapped drive

Untitled

So the question is how do I sync a directory on windows? Or is window's buffered I/O fundamentally different from POSIX and we don't need to flush a directory when a file inside it is modified?

Ibrahim
  • 287
  • 1
  • 3
  • 13
  • What are you actually trying to achieve with this code? – David Heffernan Jun 19 '19 at 07:28
  • The above code is just a sample code. My intention is to sync directory contents to the file system on windows. See https://github.com/dgraph-io/badger/issues/699 for the actual issue. – Ibrahim Jun 19 '19 at 07:30
  • 1
    Usually, when a network file is offline, a temporary cache file is generated locally (in C:\Windows\CSC. Unfortunately, very strict permissions prevent even administrators to peek inside the cache – only SYSTEM has full access.)and updated to the share folder when being online. You can also disable the caching by setting the properties of the share folder. – Drake Wu Jun 19 '19 at 10:03

1 Answers1

0

The short answer to my question is there's no way to sync directories on windows using system calls.FlushFileBuffers works for files and volumes, NOT Directories.

Read https://social.msdn.microsoft.com/Forums/Windowsdesktop/en-US/847a735b-f21a-4be2-880b-12660e5b98b4/flushfilebuffers-system-call-fails-on-network-mapped-drive and https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/0e0b734b-2b73-414d-8833-8d2eed7043f6/sync-directories-on-windows for more details.

Ibrahim
  • 287
  • 1
  • 3
  • 13