Skip to content

Commit 1dbb058

Browse files
authored
Merge pull request zyedidia#3814 from JoeKar/fix/sudo-save
save: Use `dd` with the `notrunc` & `fsync` and postpone truncation
2 parents bce573b + 165a5a4 commit 1dbb058

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

internal/buffer/save.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
const LargeFileThreshold = 50000
2626

2727
type wrappedFile struct {
28+
name string
2829
writeCloser io.WriteCloser
2930
withSudo bool
3031
screenb bool
@@ -81,7 +82,13 @@ func openFile(name string, withSudo bool) (wrappedFile, error) {
8182
var sigChan chan os.Signal
8283

8384
if withSudo {
84-
cmd = exec.Command(config.GlobalSettings["sucmd"].(string), "dd", "bs=4k", "of="+name)
85+
conv := "notrunc"
86+
// TODO: both platforms do not support dd with conv=fsync yet
87+
if !(runtime.GOOS == "illumos" || runtime.GOOS == "netbsd") {
88+
conv += ",fsync"
89+
}
90+
91+
cmd = exec.Command(config.GlobalSettings["sucmd"].(string), "dd", "bs=4k", "conv="+conv, "of="+name)
8592
writeCloser, err = cmd.StdinPipe()
8693
if err != nil {
8794
return wrappedFile{}, err
@@ -111,7 +118,18 @@ func openFile(name string, withSudo bool) (wrappedFile, error) {
111118
}
112119
}
113120

114-
return wrappedFile{writeCloser, withSudo, screenb, cmd, sigChan}, nil
121+
return wrappedFile{name, writeCloser, withSudo, screenb, cmd, sigChan}, nil
122+
}
123+
124+
func (wf wrappedFile) Truncate() error {
125+
if wf.withSudo {
126+
// we don't need to stop the screen here, since it is still stopped
127+
// by openFile()
128+
// truncate might not be available on every platfom, so use dd instead
129+
cmd := exec.Command(config.GlobalSettings["sucmd"].(string), "dd", "count=0", "of="+wf.name)
130+
return cmd.Run()
131+
}
132+
return wf.writeCloser.(*os.File).Truncate(0)
115133
}
116134

117135
func (wf wrappedFile) Write(b *SharedBuffer) (int, error) {
@@ -132,12 +150,9 @@ func (wf wrappedFile) Write(b *SharedBuffer) (int, error) {
132150
eol = []byte{'\n'}
133151
}
134152

135-
if !wf.withSudo {
136-
f := wf.writeCloser.(*os.File)
137-
err := f.Truncate(0)
138-
if err != nil {
139-
return 0, err
140-
}
153+
err := wf.Truncate()
154+
if err != nil {
155+
return 0, err
141156
}
142157

143158
// write lines
@@ -349,7 +364,6 @@ func (b *SharedBuffer) safeWrite(path string, withSudo bool, newFile bool) (int,
349364
}
350365
}()
351366

352-
353367
// Try to backup first before writing
354368
backupName, err := b.writeBackup(path)
355369
if err != nil {

0 commit comments

Comments
 (0)