Skip to content
Browse files

add copy/delete logic if rename fails.

refactor prune logic into a switch/case
  • Loading branch information...
1 parent 32da2a6 commit 01e0273eb693979acacbbd928e17fa4d858d6e0b @falconindy committed Aug 30, 2010
Showing with 77 additions and 10 deletions.
  1. +77 −10 gobble.go
View
87 gobble.go
@@ -1,12 +1,14 @@
package main
import (
+ "bufio"
+ "container/list"
"exec"
"flag"
- "os"
"fmt"
+ "io"
+ "os"
"strings"
- "container/list"
)
const (
@@ -69,10 +71,63 @@ func parsePkg(file string) *archpkg {
return &archpkg{pkgname, pkgver, ext[0], ext[1]}
}
-func movePkg(pkg *archpkg) os.Error {
- /* try to rename, first */
+func doCopy(src io.Reader, dst *bufio.Writer) os.Error {
+ defer dst.Flush()
+
+ buf := make([]byte, os.Getpagesize())
+ for {
+
+ nr, err := src.Read(buf)
+ if err != nil && err != os.EOF {
+ return err
+ }
+
+ if nr > 0 {
+ _, err = dst.Write(buf[0:nr])
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.String())
+ break
+ }
+ } else {
+ return nil
+ }
+ }
+
+ return nil
+}
+
+func tryMovePkg(pkg *archpkg) os.Error {
filename := fmt.Sprintf("%s-%s-%s.%s", pkg.Name, pkg.Version, pkg.Arch, pkg.Ext)
- return os.Rename(fmt.Sprintf("%s/%s", *cachePath, filename), fmt.Sprintf("%s/%s", *destPath, filename))
+
+ /* try to rename, first */
+ err := os.Rename(fmt.Sprintf("%s/%s", *cachePath, filename), fmt.Sprintf("%s/%s", *destPath, filename))
+ if err != nil { /* move failed, we're assuming it inter-device */
+ src, err := os.Open(flag.Arg(0), os.O_RDONLY, 0666)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err.String())
+ os.Exit(1)
+ }
+ defer src.Close()
+
+ sfi, err := src.Stat()
+
+ dst, err := os.Open(flag.Arg(1), os.O_WRONLY|os.O_CREAT|os.O_TRUNC, sfi.Permission())
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err.String())
+ os.Exit(1)
+ }
+ defer dst.Close()
+
+ err = doCopy(src, bufio.NewWriter(dst))
+ if err != nil {
+ return os.Remove(fmt.Sprintf("%s/%s", cachePath, filename))
+ }
+ return err
+ } else {
+ return nil
+ }
+
+ panic("unreachable")
}
func addPkgToMap(pkg *archpkg) {
@@ -99,7 +154,8 @@ func prune() (int, int) {
filename := fmt.Sprintf("%s-%s-%s.%s", p.Name, p.Version, p.Arch, p.Ext)
fullpath := fmt.Sprintf("%s/%s", *cachePath, filename)
- if *delete {
+ switch {
+ case *delete:
if !*quiet {
fmt.Println("Deleting " + filename)
}
@@ -108,9 +164,18 @@ func prune() (int, int) {
fmt.Fprintf(os.Stderr, "error deleting %s: %s\n", fullpath, err.String())
os.Exit(2)
}
- } else {
+ case *destPath != "":
if !*quiet {
- fmt.Println("Would delete: " + filename)
+ fmt.Println("Moving " + filename)
+ }
+ err := tryMovePkg(p)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error moving %s: %s\n", fullpath, err.String())
+ os.Exit(2)
+ }
+ default:
+ if !*quiet {
+ fmt.Println("Would prune: " + filename)
}
}
pkgCount++
@@ -148,12 +213,14 @@ func main() {
fmt.Fprintln(os.Stderr, "error: cannot delete and move in same operation")
os.Exit(5)
}
+
if (*delete || *destPath != "") && os.Getuid() != 0 {
fmt.Fprintln(os.Stderr, "error: cannot delete/move as non-root user")
os.Exit(5)
}
- if *destPath != ""; _, err := os.Stat(*destPath); err != nil {
- fmt.Fprintf(os.Stderr, "error: cannot stat destination: %s\n", err.String())
+
+ if _, err := os.Stat(*destPath); *destPath != "" && err != nil {
+ fmt.Fprintf(os.Stderr, "error: %s\n", err.String())
os.Exit(5)
}

0 comments on commit 01e0273

Please sign in to comment.
Something went wrong with that request. Please try again.