Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Perl-only Disk Size/Usage

by ccarden (Monk)
on Mar 30, 2004 at 13:20 UTC ( [id://340945]=perlquestion: print w/replies, xml ) Need Help??

ccarden has asked for the wisdom of the Perl Monks concerning the following question:

I've read quite a bit on perlmonks about various ways to determine disk usage, a la df or du, but examples mostly tally up file sizes under a particular directory (Merlyn's example), or they depend on df or du (Mr. Leisure's example, halxd2's example, Hawson's example). Most of the examples seem geared toward reporting how much size is taken up by a user, for billing purposes.

I want to determine if there is enough room on a volume to write a file, so I need to know not how much space is currently used on the disk, but how much space is left. The examples that come closest to this requirement still use a system call.

The biggest problem with system calls is that you restrict yourself to a single platform. I need this script to run on both Linux and Windows. I also don't want to use very many modules, because often our customers do not allow extra modules to be loaded on their systems (think very large companies with very tight security and concern for software support -- and perhaps a prohibitively inefficient IT group).

My question, then, is, "How do I calculate total blocks on a volume?" I figure that I can use File::Find and lstat to get the blocks used, subtract that value from total blocks, and get blocks available. Perhaps another question should be, "Am I missing an easy way to determine total blocks available?"

Replies are listed 'Best First'.
Re: Perl-only Disk Size/Usage
by Abigail-II (Bishop) on Mar 30, 2004 at 13:58 UTC
    The biggest problem with system calls is that you restrict yourself to a single platform.
    Do you mean 'system calls', or a call to system? Different beasts. Very different beasts.

    Anyway, to get information like you want, you will have to query the OS. That, in general, is done differently on different OSses. For a few things, Perl hides this difference from the user, but internally it will do different things (different system calls). There's no Perl primitive for querying disks. (Well, you probably don't want to know how much space is left on a disk. You want to know how much space is left on a filesystem - there can be more than one filesystem on a disk, and a filesystem often lies over several disks, especially at very large companies. Think RAID. Think volumes.) There's no Perl primitive for querying filesystems. There's no POSIX function for it.

    I think your best option is to use df, which, IIRC, has been ported to Windows as well. (Almost any standard Unix tool is available under Windows). That will give you a consistant interface.

    I also don't want to use very many modules, because often our customers do not allow extra modules to be loaded on their systems (think very large companies with very tight security and concern for software support -- and perhaps a prohibitively inefficient IT group).
    I find that a non-argument. What do they say. "We are a very large company. We hire you to write software, but your software may consist of only one file"? What do they do if they hire someone to write a Java application? Everything has to be in a single file? There's hardly any difference between a Perl program and a Perl module - except that the latter doesn't require execution bits.
    My question, then, is How do I calculate total blocks on a volume? I figure that I can use File::Find and lstat to get the blocks used, subtract that value from total blocks, and get blocks available.
    Well, that would be wrong, because that wouldn't take links into account, even resulting into thinking that you have a negative amount of blocks available. Not to mention that this solution could be horribly slow - you'd have to do work (and what a work it is, considering how expensive a subroutine call in Perl is) for every file.

    Abigail

Re: Perl-only Disk Size/Usage
by matija (Priest) on Mar 30, 2004 at 13:53 UTC
    Disk free space is almost inherently system dependant.

    Your File::Find method will fail because

    1. It doesn't take into account the "slack" caused by file sizes not being a integer multiples of cluster size.
    2. On unix operating systems, generaly between 5-10% of the disk is reserved and can only be written by root: disk appears smaller to normal users than to root.
    3. The user may have a system-mandated quota - calculating the size of free space on disk will not tell you how much a given user is allowed to write.
    IMHO, your best option would be to use df and quota to calculate disk space on unix machines, and something else to calculate space on windows.

    If all else fails, you can have a simple script that tries to write a file of desired size, and deletes it immediately afterwads - that will give you the definitive, system-independent answer. All you have to do is trap the error, and if you receive it, the file is too large.

Re: Perl-only Disk Size/Usage
by ctilmes (Vicar) on Mar 30, 2004 at 13:49 UTC
    Well, there are lots of ways to do this sort of things, but I think your constraints have eliminated most of them... :-)

    You don't want to call "df" and you can't install a module that would call the system call that "df" uses.

    You've got to communicate with the OS somehow.

    I say just write the file, and if the disk fills before you're complete, erase it and output an error message. (which you have to do anyway in case the disk fills up after you check the disk space but before you write your file).

Re: Perl-only Disk Size/Usage
by b10m (Vicar) on Mar 30, 2004 at 13:50 UTC

    I see your concerns about platform independancy, but df is installed on most UNIX-based systems, and if I may believe cygwin, df.exe is part of fileutils-4.1-2 so your script should be able to run on MS Windows systems too.

    In this case, I would use the ease of df (most likely since I wouldn't know a pure Perl solution ;)

    --
    b10m

    All code is usually tested, but rarely trusted.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://340945]
Approved by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2024-03-28 21:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found