// If paths is empty, all targets will be removed. func (r *Repo) RemoveTargetsWithExpires(paths []string, expires time.Time) error { if !validExpires(expires) { return ErrInvalidExpires{expires} } t, err := r.targets() if err != nil { return err } if len(paths) == 0 { t.Targets = make(data.Files) } else { removed := false for _, path := range paths { path = util.NormalizeTarget(path) if _, ok := t.Targets[path]; !ok { continue } removed = true delete(t.Targets, path) } if !removed { return nil } } t.Expires = expires.Round(time.Second) t.Version++ return r.setMeta("targets.json", t) }
// Download downloads the given target file from remote storage into dest. // // dest will be deleted and an error returned in the following situations: // // * The target does not exist in the local targets.json // * The target does not exist in remote storage // * Metadata cannot be generated for the downloaded data // * Generated metadata does not match local metadata for the given file func (c *Client) Download(name string, dest Destination) (err error) { // delete dest if there is an error defer func() { if err != nil { dest.Delete() } }() // populate c.targets from local storage if not set if c.targets == nil { if err := c.getLocalMeta(); err != nil { return err } } // return ErrUnknownTarget if the file is not in the local targets.json normalizedName := util.NormalizeTarget(name) localMeta, ok := c.targets[normalizedName] if !ok { return ErrUnknownTarget{name} } // get the data from remote storage r, size, err := c.download(normalizedName, c.remote.GetTarget, localMeta.Hashes) if err != nil { return err } defer r.Close() // return ErrWrongSize if the reported size is known and incorrect if size >= 0 && size != localMeta.Length { return ErrWrongSize{name, size, localMeta.Length} } // wrap the data in a LimitReader so we download at most localMeta.Length bytes stream := io.LimitReader(r, localMeta.Length) // read the data, simultaneously writing it to dest and generating metadata actual, err := util.GenerateFileMeta(io.TeeReader(stream, dest), localMeta.HashAlgorithms()...) if err != nil { return ErrDownloadFailed{name, err} } // check the data has the correct length and hashes if err := util.FileMetaEqual(actual, localMeta); err != nil { if err == util.ErrWrongLength { return ErrWrongSize{name, actual.Length, localMeta.Length} } return ErrDownloadFailed{name, err} } return nil }
func (r *Repo) AddTargetsWithExpires(paths []string, custom json.RawMessage, expires time.Time) error { if !validExpires(expires) { return ErrInvalidExpires{expires} } t, err := r.targets() if err != nil { return err } normalizedPaths := make([]string, len(paths)) for i, path := range paths { normalizedPaths[i] = util.NormalizeTarget(path) } if err := r.local.WalkStagedTargets(normalizedPaths, func(path string, target io.Reader) (err error) { meta, err := util.GenerateFileMeta(target, r.hashAlgorithms...) if err != nil { return err } path = util.NormalizeTarget(path) // if we have custom metadata, set it, otherwise maintain // existing metadata if present if len(custom) > 0 { meta.Custom = &custom } else if t, ok := t.Targets[path]; ok { meta.Custom = t.Custom } t.Targets[path] = meta return nil }); err != nil { return err } t.Expires = expires.Round(time.Second) t.Version++ return r.setMeta("targets.json", t) }
func cmdGet(args *docopt.Args, client *tuf.Client) error { if _, err := client.Update(); err != nil && !tuf.IsLatestSnapshot(err) { return err } target := util.NormalizeTarget(args.String["<target>"]) file, err := ioutil.TempFile("", "go-tuf") if err != nil { return err } tmp := tmpFile{file} if err := client.Download(target, &tmp); err != nil { return err } defer tmp.Delete() if _, err := tmp.Seek(0, os.SEEK_SET); err != nil { return err } _, err = io.Copy(os.Stdout, file) return err }