func checkFiles()

in zip/zip.go [200:322]


func checkFiles(files []File) (cf CheckedFiles, validFiles []File, validSizes []int64) {
	errPaths := make(map[string]struct{})
	addError := func(path string, omitted bool, err error) {
		if _, ok := errPaths[path]; ok {
			return
		}
		errPaths[path] = struct{}{}
		fe := FileError{Path: path, Err: err}
		if omitted {
			cf.Omitted = append(cf.Omitted, fe)
		} else {
			cf.Invalid = append(cf.Invalid, fe)
		}
	}

	// Find directories containing go.mod files (other than the root).
	// Files in these directories will be omitted.
	// These directories will not be included in the output zip.
	haveGoMod := make(map[string]bool)
	for _, f := range files {
		p := f.Path()
		dir, base := path.Split(p)
		if strings.EqualFold(base, "go.mod") {
			info, err := f.Lstat()
			if err != nil {
				addError(p, false, err)
				continue
			}
			if info.Mode().IsRegular() {
				haveGoMod[dir] = true
			}
		}
	}

	inSubmodule := func(p string) bool {
		for {
			dir, _ := path.Split(p)
			if dir == "" {
				return false
			}
			if haveGoMod[dir] {
				return true
			}
			p = dir[:len(dir)-1]
		}
	}

	collisions := make(collisionChecker)
	maxSize := int64(MaxZipFile)
	for _, f := range files {
		p := f.Path()
		if p != path.Clean(p) {
			addError(p, false, errPathNotClean)
			continue
		}
		if path.IsAbs(p) {
			addError(p, false, errPathNotRelative)
			continue
		}
		if isVendoredPackage(p) {
			// Skip files in vendored packages.
			addError(p, true, errVendored)
			continue
		}
		if inSubmodule(p) {
			// Skip submodule files.
			addError(p, true, errSubmoduleFile)
			continue
		}
		if p == ".hg_archival.txt" {
			// Inserted by hg archive.
			// The go command drops this regardless of the VCS being used.
			addError(p, true, errHgArchivalTxt)
			continue
		}
		if err := module.CheckFilePath(p); err != nil {
			addError(p, false, err)
			continue
		}
		if strings.ToLower(p) == "go.mod" && p != "go.mod" {
			addError(p, false, errGoModCase)
			continue
		}
		info, err := f.Lstat()
		if err != nil {
			addError(p, false, err)
			continue
		}
		if err := collisions.check(p, info.IsDir()); err != nil {
			addError(p, false, err)
			continue
		}
		if info.Mode()&os.ModeType == os.ModeSymlink {
			// Skip symbolic links (golang.org/issue/27093).
			addError(p, true, errSymlink)
			continue
		}
		if !info.Mode().IsRegular() {
			addError(p, true, errNotRegular)
			continue
		}
		size := info.Size()
		if size >= 0 && size <= maxSize {
			maxSize -= size
		} else if cf.SizeError == nil {
			cf.SizeError = fmt.Errorf("module source tree too large (max size is %d bytes)", MaxZipFile)
		}
		if p == "go.mod" && size > MaxGoMod {
			addError(p, false, errGoModSize)
			continue
		}
		if p == "LICENSE" && size > MaxLICENSE {
			addError(p, false, errLICENSESize)
			continue
		}

		cf.Valid = append(cf.Valid, p)
		validFiles = append(validFiles, f)
		validSizes = append(validSizes, info.Size())
	}

	return cf, validFiles, validSizes
}