summaryrefslogtreecommitdiff
path: root/cmd/iiifdownloader
diff options
context:
space:
mode:
authorNick White <git@njw.name>2020-10-13 16:24:45 +0100
committerNick White <git@njw.name>2020-10-13 16:24:45 +0100
commit9d5ee15ff86760beb3daaa1962eb556e60bbd107 (patch)
tree219df8940a5210f0c529d45792246b72a330f807 /cmd/iiifdownloader
parentd8423accbb0e0ec4c564a2f024d3fc376c258098 (diff)
[iiifdownloader] Catch SIGINT when writing a file to remove half-written files before exit
Diffstat (limited to 'cmd/iiifdownloader')
-rw-r--r--cmd/iiifdownloader/main.go43
1 files changed, 33 insertions, 10 deletions
diff --git a/cmd/iiifdownloader/main.go b/cmd/iiifdownloader/main.go
index eeb253e..20c7ac8 100644
--- a/cmd/iiifdownloader/main.go
+++ b/cmd/iiifdownloader/main.go
@@ -11,9 +11,11 @@ import (
"net/http"
"net/url"
"os"
+ "os/signal"
"path"
"strconv"
"strings"
+ "syscall"
)
// TODO: Add tests
@@ -238,19 +240,40 @@ func dlPage(bookdir, u string) error {
return fmt.Errorf("Error downloading page %s: %v", u, err)
}
- f, err := os.Create(fn)
- defer f.Close()
- if err != nil {
- return fmt.Errorf("Error creating file %s: %v\n", fn, err)
- }
- _, err = io.Copy(f, resp.Body)
- if err != nil {
- _ = f.Close()
+ // We do the file writing in a goroutine so that we can catch
+ // SIGINT (Ctrl-C) and ensure the file is removed, to ensure it
+ // can't be left in a half-written state. This is important so
+ // SIGINT can be used to stop the download in a state that it
+ // can safely be continued later by rerunning iiifdownloader.
+
+ sigint := make(chan os.Signal)
+ done := make(chan error)
+ signal.Notify(sigint, syscall.SIGINT)
+
+ go func() {
+ f, err := os.Create(fn)
+ defer f.Close()
+ if err != nil {
+ done <- fmt.Errorf("Error creating file %s: %v\n", fn, err)
+ }
+ _, err = io.Copy(f, resp.Body)
+ if err != nil {
+ _ = f.Close()
+ _ = os.Remove(fn)
+ done <- fmt.Errorf("Error writing file %s: %v\n", fn, err)
+ }
+ done <- nil
+ }()
+
+ select {
+ case <-sigint:
_ = os.Remove(fn)
- return fmt.Errorf("Error writing file %s: %v\n", fn, err)
+ os.Exit(0)
+ case err = <-done:
}
- return nil
+ signal.Reset(syscall.SIGINT)
+ return err
}
// dlNoPgNums downloads all pages, starting from zero, until either