Repository: zyedidia/micro
File: internal/buffer/save.go (Go)

Code before:
		err = cmd.Start()
		if err != nil {
			screen.TempStart(screenb)

			signal.Notify(util.Sigterm, os.Interrupt)
			signal.Stop(sigChan)

			return wrappedFile{}, err
		}
	} else {
		writeCloser, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE, util.FileMode)
		if err != nil {
			return wrappedFile{}, err
		}
	}

	return wrappedFile{name, writeCloser, withSudo, screenb, cmd, sigChan}, nil
}

func (wf wrappedFile) Truncate(size int64) error {
	if wf.withSudo {
		cmd := exec.Command(config.GlobalSettings["sucmd"].(string), "truncate", "-s", strconv.FormatInt(size, 10), wf.name)

		sigChan := make(chan os.Signal, 1)
		signal.Reset(os.Interrupt)
		signal.Notify(sigChan, os.Interrupt)
		screenb := screen.TempFini()

		err := cmd.Start()
		if err != nil {
			screen.TempStart(screenb)

			signal.Notify(util.Sigterm, os.Interrupt)
			signal.Stop(sigChan)

			return err
		}

		err = cmd.Wait()

		screen.TempStart(screenb)
		signal.Notify(util.Sigterm, os.Interrupt)
		signal.Stop(sigChan)

		return err
	}
	return wf.writeCloser.(*os.File).Truncate(size)
}

func (wf wrappedFile) Write(b *Buffer) (int, error) {
	file := bufio.NewWriter(transform.NewWriter(wf.writeCloser, b.encoding.NewEncoder()))

Review comment (suggestion):
We have already attached SIGINT to `wf.sigChan` in `openFile()`, and we only detach it when we are done in `wrappedFile.Close()`, right? So why re-attach it to this temporary `sigChan` in the middle?

(And you know what your `signal.Notify(util.Sigterm, os.Interrupt)` at line 143 in this function is doing? It defeats the very purpose of `wf.sigChan`: it prematurely attaches SIGINT back to the default micro's channel, so it will cause micro exit if the user presses Ctrl-C when `truncate` is already done but `dd` is not done yet.)

Code after:

		screenb = screen.TempFini()
		// need to start the process now, otherwise when we flush the file
		// contents to its stdin it might hang because the kernel's pipe size
		// is too small to handle the full file contents all at once
		err = cmd.Start()
		if err != nil {
			screen.TempStart(screenb)

			signal.Notify(util.Sigterm, os.Interrupt)
			signal.Stop(sigChan)

			return wrappedFile{}, err
		}
	} else {
		writeCloser, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE, util.FileMode)
		if err != nil {
			return wrappedFile{}, err
		}
	}

	return wrappedFile{name, writeCloser, withSudo, screenb, cmd, sigChan}, nil
}

func (wf wrappedFile) Truncate() error {
	if wf.withSudo {
		// we don't need to stop the screen here, since it is still stopped
		// by openFile()
		// truncate might not be available on every platfom, so use dd instead
		cmd := exec.Command(config.GlobalSettings["sucmd"].(string), "dd", "count=0", "of="+wf.name)
		return cmd.Run()
	}
	return wf.writeCloser.(*os.File).Truncate(0)
}

func (wf wrappedFile) Write(b *Buffer) (int, error) {
	file := bufio.NewWriter(transform.NewWriter(wf.writeCloser, b.encoding.NewEncoder()))

	b.Lock()
	defer b.Unlock()

	if len(b.lines) == 0 {
		return 0, nil
	}

	// end of line
	var eol []byte
	if b.Endings == FFDos {
		eol = []byte{'\r', '\n'}
	} else {
		eol = []byte{'\n'}