@@ -25,7 +25,6 @@ import (
2525const LargeFileThreshold = 50000
2626
2727type wrappedFile struct {
28- name string
2928 writeCloser io.WriteCloser
3029 withSudo bool
3130 screenb bool
@@ -82,13 +81,13 @@ func openFile(name string, withSudo bool) (wrappedFile, error) {
8281 var sigChan chan os.Signal
8382
8483 if withSudo {
85- conv := "notrunc"
84+ args := [] string { "dd" , "bs=4k" , "of=" + name }
8685 // TODO: both platforms do not support dd with conv=fsync yet
8786 if ! (runtime .GOOS == "illumos" || runtime .GOOS == "netbsd" ) {
88- conv += ", fsync"
87+ args = append ( args , "conv= fsync")
8988 }
9089
91- cmd = exec .Command (config .GlobalSettings ["sucmd" ].(string ), "dd" , "bs=4k" , "conv=" + conv , "of=" + name )
90+ cmd = exec .Command (config .GlobalSettings ["sucmd" ].(string ), args ... )
9291 writeCloser , err = cmd .StdinPipe ()
9392 if err != nil {
9493 return wrappedFile {}, err
@@ -99,25 +98,10 @@ func openFile(name string, withSudo bool) (wrappedFile, error) {
9998 signal .Notify (sigChan , os .Interrupt )
10099
101100 screenb = screen .TempFini ()
102-
103- // Truncate the file before starting the write process to ensure
104- // only one sudo process accesses the TTY at a time. Running both
105- // concurrently causes them to race on TCGETS2/TCSETS2 ioctls for
106- // the password prompt, deadlocking stdin routing.
107- truncCmd := exec .Command (config .GlobalSettings ["sucmd" ].(string ), "dd" , "count=0" , "of=" + name )
108- var truncStderr bytes.Buffer
109- truncCmd .Stderr = & truncStderr
110- if truncErr := truncCmd .Run (); truncErr != nil {
111- os .Stderr .Write (truncStderr .Bytes ())
112- err = truncErr
113- } else {
114- // Need to start the process now, otherwise when we flush
115- // the file contents to its stdin it might hang because
116- // the kernel's pipe size is too small to handle the full
117- // file contents all at once.
118- err = cmd .Start ()
119- }
120-
101+ // need to start the process now, otherwise when we flush the file
102+ // contents to its stdin it might hang because the kernel's pipe size
103+ // is too small to handle the full file contents all at once
104+ err = cmd .Start ()
121105 if err != nil {
122106 writeCloser .Close ()
123107 screen .TempStart (screenb )
@@ -132,15 +116,7 @@ func openFile(name string, withSudo bool) (wrappedFile, error) {
132116 }
133117 }
134118
135- return wrappedFile {name , writeCloser , withSudo , screenb , cmd , sigChan }, nil
136- }
137-
138- func (wf wrappedFile ) Truncate () error {
139- if wf .withSudo {
140- // Nothing to do, truncation already done in openFile()
141- return nil
142- }
143- return wf .writeCloser .(* os.File ).Truncate (0 )
119+ return wrappedFile {writeCloser , withSudo , screenb , cmd , sigChan }, nil
144120}
145121
146122func (wf wrappedFile ) Write (b * SharedBuffer ) (int , error ) {
@@ -161,9 +137,12 @@ func (wf wrappedFile) Write(b *SharedBuffer) (int, error) {
161137 eol = []byte {'\n' }
162138 }
163139
164- err := wf .Truncate ()
165- if err != nil {
166- return 0 , err
140+ if ! wf .withSudo {
141+ f := wf .writeCloser .(* os.File )
142+ err := f .Truncate (0 )
143+ if err != nil {
144+ return 0 , err
145+ }
167146 }
168147
169148 // write lines
@@ -386,6 +365,9 @@ func (b *SharedBuffer) safeWrite(path string, withSudo bool, newFile bool) (int,
386365
387366 file , err := openFile (path , withSudo )
388367 if err != nil {
368+ if withSudo {
369+ return 0 , util.OverwriteError {What : err , BackupName : backupName }
370+ }
389371 return 0 , err
390372 }
391373
@@ -407,12 +389,12 @@ func (b *SharedBuffer) safeWrite(path string, withSudo bool, newFile bool) (int,
407389 size , err = file .Write (b )
408390 if err != nil {
409391 file .Close ()
410- return 0 , util.OverwriteError {err , backupName }
392+ return 0 , util.OverwriteError {What : err , BackupName : backupName }
411393 }
412394
413395 err = file .Close ()
414396 if err != nil {
415- return 0 , util.OverwriteError {err , backupName }
397+ return 0 , util.OverwriteError {What : err , BackupName : backupName }
416398 }
417399 }
418400 b .forceKeepBackup = false
0 commit comments