package diskcapacity import ( "encoding/json" "errors" "net/http" "path/filepath" "runtime" "strings" "imuslab.com/arozos/mod/common" "imuslab.com/arozos/mod/disk/diskspace" "imuslab.com/arozos/mod/user" ) /* Disk Capacity This is a simple module to check how many storage space is remaining on a given directory in accessiable file system paths Author: tobychui */ type Resolver struct { UserHandler *user.UserHandler } type Capacity struct { PhysicalDevice string //The ID of the physical device, like C:/ or /dev/sda1 MountingHierarchy string //The Mounting Hierarchy of the vroot Used int64 //Used capacity in bytes Avilable int64 //Avilable capacity in bytes Total int64 //Total capacity in bytes } //Create a new Capacity Resolver with the given user handler func NewCapacityResolver(u *user.UserHandler) *Resolver { return &Resolver{ UserHandler: u, } } func (cr *Resolver) HandleCapacityResolving(w http.ResponseWriter, r *http.Request) { //Check if the request user is authenticated userinfo, err := cr.UserHandler.GetUserInfoFromRequest(w, r) if err != nil { common.SendErrorResponse(w, "User not logged in") return } //Get vpath from paramter vpath, err := common.Mv(r, "path", true) if err != nil { common.SendErrorResponse(w, "Vpath is not defined") return } capinfo, err := cr.ResolveCapacityInfo(userinfo.Username, vpath) if err != nil { common.SendErrorResponse(w, "Unable to resolve path capacity information: "+err.Error()) return } //Get Storage Hierarcy fsh, err := userinfo.GetFileSystemHandlerFromVirtualPath(vpath) if err != nil { capinfo.MountingHierarchy = "Unknown" } else { capinfo.MountingHierarchy = fsh.Hierarchy } //Send the requested path capacity information js, _ := json.Marshal(capinfo) common.SendJSONResponse(w, string(js)) } func (cr *Resolver) ResolveCapacityInfo(username string, vpath string) (*Capacity, error) { //Resolve the vpath for this user userinfo, err := cr.UserHandler.GetUserInfoFromUsername(username) if err != nil { return nil, err } realpath, err := userinfo.VirtualPathToRealPath(vpath) if err != nil { return nil, err } realpath = filepath.ToSlash(filepath.Clean(realpath)) return cr.GetCapacityInfo(realpath) } func (cr *Resolver) GetCapacityInfo(realpath string) (*Capacity, error) { if runtime.GOOS == "windows" { //Windows //Extract the root disk number rpathAbs, err := filepath.Abs(realpath) if err != nil { return nil, err } //Extract disk ID from path rpathAbs = filepath.ToSlash(filepath.Clean(rpathAbs)) diskRoot := strings.Split(rpathAbs, "/")[0] //Match the disk space info generated from diskspace logicDiskInfo := diskspace.GetAllLogicDiskInfo() for _, ldi := range logicDiskInfo { if strings.TrimSpace(ldi.Device) == strings.TrimSpace(diskRoot) { //Matching device ID return &Capacity{ PhysicalDevice: ldi.Device, Used: ldi.Used, Avilable: ldi.Available, Total: ldi.Volume, }, nil } } } else if runtime.GOOS == "darwin" { //MacOS. } else { //Assume Linux //Use command: df -P {abs_path} } return nil, errors.New("Unable to resolve matching disk capacity information") }