github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/core/truncate/truncate.go (about) 1 // Copyright 2013-2017 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Truncate - shrink or extend the size of a file to the specified size 6 // 7 // Synopsis: 8 // 9 // truncate [OPTIONS] [FILE]... 10 // 11 // Options: 12 // 13 // -s: size in bytes 14 // -r: reference file for size 15 // -c: do not create any files 16 // 17 // Author: 18 // 19 // Roland Kammerer <dev.rck@gmail.com> 20 package main 21 22 import ( 23 "flag" 24 "fmt" 25 "log" 26 "os" 27 28 "github.com/rck/unit" 29 "github.com/mvdan/u-root-coreutils/pkg/uroot/util" 30 ) 31 32 const usage = "truncate [-c] -s size file..." 33 34 var ( 35 create = flag.Bool("c", false, "Do not create files.") 36 size = unit.MustNewUnit(unit.DefaultUnits).MustNewValue(1, unit.None) 37 rfile = flag.String("r", "", "Reference file for size") 38 ) 39 40 func init() { 41 flag.Var(size, "s", "Size in bytes, prefixes +/- are allowed") 42 flag.Usage = util.Usage(flag.Usage, usage) 43 } 44 45 func truncate(args ...string) error { 46 if !size.IsSet && *rfile == "" { 47 return fmt.Errorf("you need to specify size via -s <number> or -r <rfile>") 48 } 49 if size.IsSet && *rfile != "" { 50 return fmt.Errorf("you need to specify size via -s <number> or -r <rfile>") 51 } 52 if len(args) == 0 { 53 return fmt.Errorf("you need to specify one or more files as argument") 54 } 55 56 for _, fname := range args { 57 58 var final int64 59 st, err := os.Stat(fname) 60 if os.IsNotExist(err) && !*create { 61 if err = os.WriteFile(fname, []byte{}, 0o644); err != nil { 62 return fmt.Errorf("%v", err) 63 } 64 if st, err = os.Stat(fname); err != nil { 65 return fmt.Errorf("could not stat newly created file: %v", err) 66 } 67 } 68 if *rfile != "" { 69 if st, err = os.Stat(*rfile); err != nil { 70 return fmt.Errorf("could not stat reference file: %v", err) 71 } 72 final = st.Size() 73 } else if size.IsSet { 74 final = size.Value // base case 75 if size.ExplicitSign != unit.None { 76 final += st.Size() // in case of '-', size.Value is already negative 77 } 78 if final < 0 { 79 final = 0 80 } 81 } 82 83 // intentionally ignore, like GNU truncate 84 os.Truncate(fname, final) 85 } 86 return nil 87 } 88 89 func main() { 90 flag.Parse() 91 if err := truncate(flag.Args()...); err != nil { 92 flag.Usage() 93 log.Fatal(err) 94 } 95 }