2

It seems the default os.Open call allows another processes to write the opened file, but not to delete it. Is it possible to enable deletion as well? In .NET this can be done using FileShare.Delete flag, is there any analog in Go?

user626528
  • 13,999
  • 30
  • 78
  • 146
  • Related: http://stackoverflow.com/q/19875329 – Robert Harvey May 27 '14 at 19:16
  • I'm only guessing here - but since this is the way files work in Unix, and since Go is a) unix centric and b) tries to be portable and not have custom per-OS methods or flags - there isn't such an option. I would look in the syscall package that lets you run low level per os syscalls, and is usually used by higher level library code. – Not_a_Golfer May 27 '14 at 19:42
  • It appears the windows syscall package indeed has the notion of a SHARE_DELETE mode when opening files. See http://golang.org/src/pkg/syscall/ztypes_windows.go#L93 . However, keep in mind that doing this in a place that is is not windows specific (i.e. a file not ending with _windows.go) will result in non portable code. – Not_a_Golfer May 27 '14 at 19:52
  • @Not_a_Golfer, I don't know much about nix. Doesn't it allow to let another processes remove the currently opened file? – user626528 May 27 '14 at 19:52
  • @user626528 deleting is called "unlinking" in Unix-ish, meaning removing one link from a path or name to the actual data on the disk (many can be created). These are separate in Unix. Once a file doesn't have any links to it, it disappears. This means that you can delete an open file of a running process, but apart from the path, it still exists until this process exits. – Not_a_Golfer May 27 '14 at 19:54

1 Answers1

6

os.Open will get you a file descriptor with flag O_RDONLY set; that means read only. You can specify your own flag by using os.OpenFile

O_RDONLY int = syscall.O_RDONLY // open the file read-only.
O_WRONLY int = syscall.O_WRONLY // open the file write-only.
O_RDWR   int = syscall.O_RDWR   // open the file read-write.
O_APPEND int = syscall.O_APPEND // append data to the file when writing.
O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist
O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
O_TRUNC  int = syscall.O_TRUNC  // if possible, truncate file when opened.

None of these modes, however, will allow you to have multiple writers on a single file. You can share the file descriptor by exec-ing or fork-ing but naively writing to the file from both processes will result in the OS deciding how to synchronise those writes -- which is almost never what you want.

Deleting a file while a process has a FD on it doesn't matter on unix-like systems. I'll go ahead and assume Windows won't like that, though.

Edit given the tag and @Not_a_Golfer's excellent observations:

You should be able to pass syscall.FILE_SHARE_DELETE as a flag to os.OpenFile on Windows, if that is what solves your problem.

If you need to combine several flags you can do so by or-ing them together:

syscall.FILE_SHARE_DELETE | syscall.SOME_OTHER_FLAG | syscall.AND_A_THIRD_FLAG

(note, however, that it's up to you to build a coherent flag)

thwd
  • 23,956
  • 8
  • 74
  • 108
  • 1
    see my comments to OP, it's possible in Windows but not the default setting, as far as I can tell by reading the OS-specific file opening code in the std library. – Not_a_Golfer May 27 '14 at 20:04
  • I'd add this if this code should live beyond the original author's personal computer, stuff like this should be done inside a windows only file (ending with _windows.go), while keeping support for the same functionality for other targets. The syscall package is the best example for that. – Not_a_Golfer May 27 '14 at 20:12