Beispiel #1
0
// process entry of given name in current directory; recursively descend if
// entry names a directory and the recursive flag is set
func processInputs(entry, accumulatedPath string) {
	var err error
	var info os.FileInfo

	if info, err = statFunction(entry); err != nil {
		myerr.MyError("error: %s", err)
		return
	}

	// skip over non-regular files and non-directories
	if 0 != info.Mode()&(os.ModeSymlink|os.ModeNamedPipe|os.ModeSocket|os.ModeDevice) {
		return
	}

	if info.IsDir() {
		if !*recursive {
			myerr.MyError("%s is a directory without recursive flag", accumulatedPath)
			return
		}

		var thisDir string
		if thisDir, err = os.Getwd(); err != nil {
			myerr.MyPanic(err)
		}
		myerr.MyPanic(os.Chdir(entry))
		defer func() {
			myerr.MyPanic(os.Chdir(thisDir))
		}()

		var f *os.File
		if f, err = os.Open("."); err != nil {
			myerr.MyError("error: could not open directory %s; %s", accumulatedPath, err)
			return
		}
		var entries_info []os.FileInfo
		if entries_info, err = f.Readdir(-1); err != nil {
			myerr.MyPanic(f.Close())
			myerr.MyError("error: could not read directory %s; %s", accumulatedPath, err)
			return
		}
		myerr.MyPanic(f.Close())

		for _, entry := range entries_info {
			newAccumulatedPath := fmt.Sprintf("%s%c%s", accumulatedPath, os.PathSeparator, entry.Name())
			processInputs(entry.Name(), newAccumulatedPath)
		}
	} else {
		var f *os.File
		var e error
		if f, e = os.Open(entry); e != nil {
			myerr.MyError("warning: could not open %s; skipping", accumulatedPath)
			return
		}

		defer func() {
			f.Close()
		}()

		processReader(accumulatedPath, f, info.Size())
	}
}
Beispiel #2
0
func main() {
	defer myerr.MyDefer()

	var err error

	flag.Var(&fromBytes, "fromb", "bytes to replace; used to make sure you don't overwrite wrong data; e.g., \"-b 00ff00AA\"")
	flag.Var(&toBytes, "tob", "replacement bytes; e.g., \"-b 0FE32d17\"")
	flag.Parse() // scan the arguments list

	if len(*fromString) != 0 {
		if len(fromBytes) == 0 {
			fromBytes = []byte(*fromString)
		} else {
			myerr.MyFatal(status_fatal_error, "error: specified both -from and -fromb parameters")
			return
		}
	}

	if len(*toString) != 0 {
		if len(toBytes) == 0 {
			toBytes = []byte(*toString)
		} else {
			myerr.MyFatal(status_fatal_error, "error: specified both -to and -tob parameters")
			return
		}
	} else if len(toBytes) == 0 {
		myerr.MyFatal(status_fatal_error, "error: must specify either -to or -tob parameter")
		return
	}

	if len(fromBytes) != 0 && len(fromBytes) != len(toBytes) {
		myerr.MyFatal(status_fatal_error, "error: if you specify -from or -fromb it must be the same size as -to or -tob; %d is not equal to %d", len(fromBytes), len(toBytes))
		return
	}

	var inFileName string
	positions := NewUint64Slice()
	gotError := false

	for i, arg := range flag.Args() {
		if i == 0 {
			inFileName = arg
		} else {
			var v uint64
			v, err = strconv.ParseUint(arg, 10, 64)
			if err != nil {
				myerr.MyError("error: trying to parse \"%s\" as an offset; got %s", arg, err)
				gotError = true
			} else {
				positions = append(positions, v)
			}
		}
	}

	sort.Sort(positions)

	if gotError {
		myerr.MyFatal(status_fatal_error, "must exit due to errors")
		return
	}

	inFile, oe := os.Open(inFileName)
	if oe != nil {
		myerr.MyFatal(status_fatal_error, "could not open file \"%s\"; %s", inFileName, oe)
	}
	defer func() {
		inFile.Close()
	}()

	outFileName, outFile, oe2 := makeTempFile(inFileName, "tmp")
	if oe2 != nil {
		myerr.MyFatal(status_fatal_error, "%s", oe2)
	}
	complete := false
	defer func() {
		outFile.Close()
		if complete {
			var mode os.FileMode
			if fi, e := inFile.Stat(); e == nil {
				mode = fi.Mode()
			} else {
				myerr.MyPanic(e)
			}

			var backupName string
			var backupFile *os.File
			backupName, backupFile, err = makeTempFile(inFileName, "backup")
			myerr.MyPanic(err)
			err = backupFile.Close()
			myerr.MyPanic(err)
			err = os.Rename(inFileName, backupName)
			myerr.MyPanic(err)
			err = os.Rename(outFileName, inFileName)
			myerr.MyPanic(err)
			err = os.Chmod(inFileName, mode)
			myerr.MyPanic(err)
		} else {
			err = os.Remove(outFileName)
		}
	}()

	if _, err = io.Copy(outFile, inFile); err != nil {
		myerr.MyFatal(status_fatal_error, "error: %s", err)
		return
	}

	buffer := make([]byte, len(fromBytes), len(fromBytes))
	for _, offset := range positions {
		skip := false
		if len(fromBytes) != 0 {
			_, err = outFile.ReadAt(buffer, int64(offset))
			myerr.MyPanic(err)
			if !sameBytes(fromBytes, buffer) {
				fmt.Printf("warning: not same at offset %d; skipping\n", offset)
				skip = true
			}
		}

		if !skip {
			_, err = outFile.WriteAt(toBytes, int64(offset))
			myerr.MyPanic(err)
		}
	}

	complete = true
}