russ@wpg.UUCP (Russell Lawrence) (04/08/88)
I'm stumped. Apart from using system() to run 'df', could someone please suggest a method for checking available disk space from a c program? Thanks. -- Russell Lawrence, WP Group, POB 306, Metairie, LA 70004 AT&T: +1 504 456 0001 COMPUSERVE: 72337,3261 UUCP: {philabs,hpda,nbires,amdahl,...}!uunet!wpg!russ
ford@kenobi.UUCP (Mike Ditto) (04/10/88)
Posting-Front-End: GNU Emacs 18.41.10 of Fri Oct 2 1987 on kenobi (usg-unix-v) In article <398@wpg.UUCP> russ@wpg.UUCP (Russell Lawrence) writes: > I'm stumped. Apart from using system() to run 'df', could someone > please suggest a method for checking available disk space from a > c program? Read /etc/mnttab to see what devices are mounted, and use the ustat system call to check the status of each. Or, if you are wondering how big you can make a certain file, you can also stat() the file (or the directory in which you intend to create it) to see what device it is on, and ustat() that. See mnttab(4), stat(2), ustat(2). -=] Ford [=- "Once there were parking lots, (In Real Life: Mike Ditto) now it's a peaceful oasis. ford%kenobi@crash.CTS.COM This was a Pizza Hut, ...!sdcsvax!crash!kenobi!ford now it's all covered with daisies." -- Talking Heads
gandalf@csli.STANFORD.EDU (Juergen Wagner) (04/10/88)
Yes, there is a way to find out the space available on the file system a particular file resides on. The only problem is that you have to setuid to root to be able to read the disk device. Normal users will have to use df. Here comes a small program which does the job (usage: "d <file>" tells you the free space on the file system of <file>). Juergen "Gandalf" Wagner, gandalf@csli.stanford.edu Center for the Study of Language and Information (CSLI), Stanford CA /* ** Unpack this into d.c ** $Compile: cc -g -o d d.c */ # include <stdio.h> # include <sys/param.h> # include <sys/stat.h> # include <sys/ioctl.h> # include <sys/file.h> # include <ufs/fs.h> # include <fstab.h> union { struct fs iu_fs; char dummy[SBSIZE]; } sb; # define sblock sb.iu_fs static char *getfs(file,dev) char *file; int dev; { struct stat s; struct fstab *fs; if (dev > 0) { setfsent(); while (fs = getfsent()) { if (stat(fs->fs_spec, &s)) continue; if (s.st_rdev == dev) { endfsent(); return(fs->fs_spec); } } } else return(file); } main(argc, argv) int argc; char **argv; { char *file = argv[1]; int f; int totalblks, free, used, availblks, avail; int freeblks; struct stat s; if (stat(file, &s)) { perror(file); exit(1); } if ((s.st_mode & S_IFMT) != S_IFBLK) file = getfs(file,s.st_dev); if (stat(file, &s)) { perror(file); exit(1); } if ((s.st_mode & S_IFMT) != S_IFBLK) { printf("%s is not a block-oriented device", file); exit(1); } f = open(file, O_RDONLY); if (f < 0) { perror(file); exit(1); } lseek(f, (long) (SBLOCK * DEV_BSIZE), 0); read(f, &sblock, SBSIZE); totalblks = sblock.fs_dsize; free = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag + sblock.fs_cstotal.cs_nffree; used = totalblks - free; availblks = totalblks * (100 - sblock.fs_minfree) / 100; avail = availblks > used ? availblks - used : 0; freeblks = avail * sblock.fs_fsize / 1024; printf("free of %s: %d\n", file, freeblks); exit(0); } -- Juergen "Gandalf" Wagner, gandalf@csli.stanford.edu Center for the Study of Language and Information (CSLI), Stanford CA
zjat02@apctrc.UUCP (Jon A. Tankersley) (04/10/88)
On a Sun maybe on any BSD system - statfs has the information. Here is a skeleton: #include <sys/types.h> #include <sys/vfs.h> . . . struct statfs buf; /* * call statfs regarding a filename path and check out the results * filename MUST exist as either file or directory */ if ( statfs(path,&buf) == 0 ) /* return block_size*blocks_avail as size in bytes */ return(buf.f_bsize*buf.f_bavail); else /* error, return -1 */ return(-1); -tank-
friedl@vsi.UUCP (Stephen J. Friedl) (04/11/88)
In article <3431@csli.STANFORD.EDU>, gandalf@csli.STANFORD.EDU (Juergen Wagner) writes: > Yes, there is a way to find out the space available on the file system > a particular file resides on. The only problem is that you have to setuid to > root to be able to read the disk device. Normal users will have to use df. > > Here comes a small program which does the job (usage: "d <file>" tells you > the free space on the file system of <file>). > > [small program text here] No comments on the code included, but you might not need to make the program setuid root. Many systems have their disk devices owned and grouped (grouped?) by other users. 0 brw-r----- 1 root sys 17, 16 Jun 27 1987 /dev/dsk/c1d1s0 If you are writing your program to include this code, look at the group (and mode, of course) to see if you can exploit a lesser id. In the above example, the program could be set-group-id `sys' rather than set-user-id `root'. Better from a lot of points is to just popen("df") (or the sample "d" program) and read the output; then the program is still safe and effective. Please do not take setuid or setgid lightly. You may be writing for some small single-user machine (your Unix PC, an AT with uport, etc.), but you will move on someday. Or, perhaps, you will submit your program to the net and lots of other people on more lively machines will use it. If you make it a habit to not put in security holes when it doesn't matter, then you will be that much farther ahead when it does matter. BTW, portability works the same way... I welcome all questions on setuid/setgid topics via email. -- Steve Friedl V-Systems, Inc. "Yes, I'm jeff@unh's brother" friedl@vsi.com {backbones}!vsi.com!friedl attmail!vsi!friedl
gandalf@csli.STANFORD.EDU (Juergen Wagner) (04/11/88)
In article <71@kenobi.UUCP> ford@kenobi.UUCP (Mike Ditto) writes: >... >Read /etc/mnttab to see what devices are mounted, and use the ustat >system call to check the status of each. Or, if you are wondering how >big you can make a certain file, you can also stat() the file (or the >directory in which you intend to create it) to see what device it is >on, and ustat() that. >... The problem with ustat is that it doesn't exist on BSD systems (even on Suns), and the problem with stat is that you can't get the whole information without actually reading the super-block, i.e. without having root privileges. Normal users have to stick with "df" pipes thru some filter. Juergen "Gandalf" Wagner, gandalf@csli.stanford.edu Center for the Study of Language and Information (CSLI), Stanford CA Disclaimer: The opinions expressed herein are those of my cat. -- Juergen "Gandalf" Wagner, gandalf@csli.stanford.edu Center for the Study of Language and Information (CSLI), Stanford CA
dieter@titan.nmt.edu (Dieter Muller) (04/11/88)
In article <3448@csli.STANFORD.EDU> gandalf@csli.stanford.edu (Juergen Wagner) writes: >In article <71@kenobi.UUCP> ford@kenobi.UUCP (Mike Ditto) writes: >>... >>Read /etc/mnttab to see what devices are mounted, and use the ustat >>system call to check the status of each.... >>... > >The problem with ustat is that it doesn't exist on BSD systems (even on >Suns), and the problem with stat is that you can't get the whole >information without actually reading the super-block, i.e. without having >root privileges. Normal users have to stick with "df" pipes thru some >filter. If you have a Sun, what's wrong with statfs? True, it isn't on our 4.3BSD Vax, and it doesn't seem real happy with NFS, but it's there and it works (SunOS 3.5). Here's an example: Filesystem: /titan1 Block size: 1024 Num blocks: 490369 Total free: 97943 Avail free: 48906 Total nodes: 96256 Free nodes: 77991 Looks like exactly what was asked for. Yes, I know all the world's not a Sun. The code for this example follows. I didn't run it as root. Dieter Muller ---------------- #include <stdio.h> #include <sys/types.h> #include <sys/vfs.h> main () { struct statfs buffer; if (statfs ("/titan1", & buffer) == -1) perror ("/titan1"); else print_statfs ("/titan1", & buffer); exit (0); } print_statfs (name, buffer) char * name; struct statfs * buffer; { printf ("Filesystem: %s\n", name); printf ("Block size: %d\n", buffer -> f_bsize); printf ("Num blocks: %d\n", buffer -> f_blocks); printf ("Total free: %d\n", buffer -> f_bfree); printf ("Avail free: %d\n", buffer -> f_bavail); printf ("Total nodes: %d\n", buffer -> f_files); printf ("Free nodes: %d\n", buffer -> f_ffree); fflush (stdout); return; } -- ...{cmcl2, ihnp4}!lanl!unm-la!unmvax!nmtsun!dieter ...gemini!crunch!unmvax!nmtsun!dieter dieter@nmtsun.nmt.edu