// GoCheese -- Python private package repository and caching proxy // Copyright (C) 2019-2024 Sergey Matveev // // 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 . package main import ( "log" "net/http" "os" "path/filepath" "time" ) var ( NoSync = os.Getenv("GOCHEESE_NO_SYNC") == "1" UmaskCur int ) func TempFile(dir string) (*os.File, error) { tmp, err := os.CreateTemp(dir, "gocheese") if err != nil { return nil, err } err = os.Chmod(tmp.Name(), os.FileMode(0666&^UmaskCur)) if err != nil { tmp.Close() return nil, err } return tmp, nil } func DirSync(dirPath string) error { if NoSync { return nil } fd, err := os.Open(dirPath) if err != nil { return err } err = fd.Sync() if err != nil { fd.Close() return err } return fd.Close() } func WriteFileSync(dirPath, filePath string, data []byte, mtime time.Time) error { dst, err := TempFile(dirPath) if err != nil { return err } if _, err = dst.Write(data); err != nil { os.Remove(dst.Name()) dst.Close() return err } if !NoSync { if err = dst.Sync(); err != nil { os.Remove(dst.Name()) dst.Close() return err } } dst.Close() if err = os.Chtimes(dst.Name(), mtime, mtime); err != nil { return err } if err = os.Rename(dst.Name(), filePath); err != nil { return err } return DirSync(dirPath) } func mkdirForPkg(w http.ResponseWriter, r *http.Request, pkgName string) bool { path := filepath.Join(Root, pkgName) if _, err := os.Stat(path); os.IsNotExist(err) { if err = os.Mkdir(path, os.FileMode(0777)); err != nil { log.Println("error", r.RemoteAddr, "mkdir", pkgName, err) http.Error(w, err.Error(), http.StatusInternalServerError) return false } log.Println(r.RemoteAddr, "mkdir", pkgName) } return true }