--- /dev/null
+/*
+netstring -- netstring format serialization library
+Copyright (C) 2015-2020 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+
+ "go.cypherpunks.ru/netstring/v2"
+)
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "ns -- Work with netstring encoded files\n\n")
+ fmt.Fprintf(os.Stderr, "Usage: %s list FILE\n", os.Args[0])
+ fmt.Fprintf(os.Stderr, " %s read FILE CHUNK > data\n", os.Args[0])
+ fmt.Fprintf(os.Stderr, " %s write FILE ... > data\n", os.Args[0])
+ os.Exit(1)
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+ if len(os.Args) < 3 {
+ usage()
+ }
+ switch os.Args[1] {
+ case "list":
+ fd, err := os.Open(os.Args[2])
+ if err != nil {
+ panic(err)
+ }
+ r := netstring.NewReader(fd)
+ for i := 0; ; i++ {
+ size, err := r.Next()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ panic(err)
+ }
+ fmt.Printf("%d\t%d\n", i, size)
+ r.Discard()
+ }
+ case "read":
+ if len(os.Args) != 4 {
+ usage()
+ }
+ chunk, err := strconv.Atoi(os.Args[3])
+ if err != nil {
+ panic(err)
+ }
+ fd, err := os.Open(os.Args[2])
+ if err != nil {
+ panic(err)
+ }
+ r := netstring.NewReader(fd)
+ for i := 0; i < chunk; i++ {
+ _, err = r.Next()
+ if err != nil {
+ panic(err)
+ }
+ r.Discard()
+ }
+ _, err = r.Next()
+ if err != nil {
+ panic(err)
+ }
+ if _, err = io.Copy(os.Stdout, r); err != nil {
+ panic(err)
+ }
+ case "write":
+ w := netstring.NewWriter(os.Stdout)
+ for i, fn := range os.Args[2:] {
+ fd, err := os.Open(fn)
+ if err != nil {
+ panic(err)
+ }
+ fi, err := fd.Stat()
+ if err != nil {
+ panic(err)
+ }
+ size := uint64(fi.Size())
+ if _, err = w.WriteSize(size); err != nil {
+ panic(err)
+ }
+ if _, err = io.Copy(w, fd); err != nil {
+ panic(err)
+ }
+ fmt.Fprintf(os.Stderr, "%d\t%d\t%s\n", i, size, fn)
+ }
+ }
+}