Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

does not produce accurate numbers #5

Open
drrob1 opened this issue Apr 14, 2021 · 7 comments
Open

does not produce accurate numbers #5

drrob1 opened this issue Apr 14, 2021 · 7 comments

Comments

@drrob1
Copy link

drrob1 commented Apr 14, 2021

On Ubuntu 20.04, the numbers it produces are all the same. IE, Free(), Available(), Size() and Used() all produce the same output.
These numbers do not match the output of the df command at all. I'm currently using a script that uses
$(df -k --output=avail /dev/sda1 | tail -n1)
I have kernel 5.8.0.7642-generic

@ricochet2200
Copy link
Owner

@drrob1 This library is actually a very thin wrapper around the following code:

    var stat syscall.Statfs_t
    syscall.Statfs("/path/here", &stat)

This probably means one of the following:

  1. syscall.Statfs() is broken (unlikely)
  2. Something is wonky with your computer
  3. There is a bug in your code

Could you post the code you are using?

@drrob1
Copy link
Author

drrob1 commented Jul 4, 2021

package main
import (
"fmt"
"github.com/ricochet2200/go-disk-usage/du"
"os"
"runtime"
"strings"
"unicode"
)
func main() {
if len(os.Args) < 2 {
fmt.Println(" Usage: diskusage [/dev/sdX] | [drive:]")
os.Exit(1)
}
volumePath := ""
volume := os.Args[1]
if runtime.GOOS == "linux" {
//if !(strings.HasPrefix(volume, "/dev/") && strings.HasSuffix(volume, string(os.PathSeparator))) {
if !(strings.HasPrefix(volume, "/dev/")) {
fmt.Println(" On linux, volume must begin /dev/.")
os.Exit(1)
}
volumePath = volume
} else if runtime.GOOS == "windows" {
volByteSlice := []byte(volume)
driveletter := rune(volByteSlice[0])
colon := rune(volByteSlice[1])
if !(unicode.IsLetter(driveletter) && colon == ':') {
fmt.Println(" On Windows, volume must begin w/ a 2 character drive designator")
os.Exit(1)
}
volumePath = string(driveletter + colon + os.PathSeparator)
}
usage := du.NewDiskUsage(volumePath)
fmt.Println("Free:", usage.Free())
fmt.Println("Available:", usage.Available())
fmt.Println("Size:", usage.Size())
fmt.Println("Used:", usage.Used())
//fmt.Println("Usage:", usage.Usage()*100, "%")
fmt.Println()
}

@drrob1 drrob1 closed this as completed Jul 4, 2021
@drrob1
Copy link
Author

drrob1 commented Jul 4, 2021

Of course, the site removed my indentations. But gofmt would restore those, I guess. I never tested it on windows, though I did write code to be able to.

@ricochet2200
Copy link
Owner

@drrob1 I'm not sure if you meant to close this issue or not, but I thought I'd reply anyway.

I was able to reproduce you results on CentOS 7 running on WSL. The numbers are close, but not exact. I'm not an expert at df so I can't speak to what exactly the numbers are reported. However, I did verify that the results from this code in go

package main

import (
        "fmt"
        "syscall"
)

func main() {

        var stat syscall.Statfs_t
        syscall.Statfs(".", &stat)

        fmt.Println("Bsize", stat.Bsize)
        fmt.Println("Bavail", stat.Bavail)
        fmt.Println("BFree", stat.Bfree)
        fmt.Println("Blocks", stat.Blocks)
}

closely resembles this code in c

#include<stdio.h>
#include<sys/stat.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/vfs.h>
int main(int argc,char *argv[])
{
  struct statfs sb;
  if((statfs(argv[1],&sb))==0)
    {
      printf("optimal transfer blk size is %d\n",sb.f_bsize);
      printf("Free blocks available to unpriviledged user %d\n",sb.f_bavail);
      printf("Free blocks in filesystem %d\n",sb.f_bfree);
      printf("Total Data blocks in filesystem %d\n",sb.f_blocks);
    }
}

There are differences in the lower order bits from run to run but both programs produce very similar results. This is not surprising because I believe go calls statfs under the covers. The math for calculating the results is pretty straightforward using those results. df maybe takes into account more factors which creates a difference?

@ricochet2200 ricochet2200 reopened this Jul 7, 2021
@drrob1
Copy link
Author

drrob1 commented Jul 21, 2021

My point is that the usage.Free() returned from the Go function is off by 3 orders of magnitude from the output of the linux df command.

So I don't understand what you are saying

And I did not intend to close the issue. I must have clicked on the wrong thing.

@ricochet2200
Copy link
Owner

I have a WSL system so it was a little difficult to test your code directly because I don't know how devices like /dev/sda1 apply. I got a hold of a native centos 7 machine and ran your code and replicated your results.

This library as written expects a path and not a device. Which is to say it needs "/" not "/dev/sda1". This is because this library uses https://pkg.go.dev/syscall#Statfs which requires a path. I can look into updating the library to something like https://pkg.go.dev/syscall#Fstatfs but I'd need to investigate and think through this to make sure I don't break live code depending on this functionality. If this goes as expected I'll add this soon...

@drrob1
Copy link
Author

drrob1 commented Jul 21, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants