Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

Re: using Linux getdents syscall

by andal (Hermit)
on Nov 24, 2015 at 09:04 UTC ( #1148485=note: print w/replies, xml ) Need Help??

in reply to using Linux getdents syscall

I'm not going to discuss what is more efficient, syscall or readdir. It is up to you to check and decide. I'll just try to give you some hints for the use of pack/unpack and/or Convert::Binary::C

Your first mistake, is the difference between actual size of buffer, and the declared size of buffer. You do my $buf = "\0" x 128; which reserves 128 bytes of buffer, but to the syscall you say that your buffer is BUF_SIZE long, which is 4096. You'll end up with corrupted memory, or even SEGFAULT.

Then, you have to check for syscall returning 0. In this case, there's nothing to unpack.

Finally. Returned buffer shall contain one or more records of variable length. You have to configure Convert::Binary::C so that it is prepared to handle such records. Read "The Dimension Tag" section in the module documentation. So your algorithm shall be "while $read != 0 convert first structure; $read -= length of converted; remove processed part from buffer".

You don't have to use Convert::Binary::C. Using perls native "unpack" you can process this structure like this

while($read != 0) { my($ino, $off, $len, $name) = unpack("LLSZ*", $buf); print $name, "\n" if($ino != 0); substr($buf, 0, $len) = ''; $read -= $len; }

Replies are listed 'Best First'.
Re^2: using Linux getdents syscall
by glasswalk3r (Friar) on Nov 24, 2015 at 12:18 UTC

    Thanks for the tips!

    Considering that $buf might have multiple dentries inside of it, how do I navigate thru all those records? For C is easy because I'm accessing memory directly, but how do I know how many bytes I should read from $buf and how to move to the next record with Perl?

    Alceu Rodrigues de Freitas Junior
    "You have enemies? Good. That means you've stood up for something, sometime in your life." - Sir Winston Churchill

      I've already put it in the code. The variable $len contains total length of single dirent structure. So, all you have to do is to remove this many bytes from the beginning of the buffer.

Re^2: using Linux getdents syscall
by ikegami (Patriarch) on Jul 17, 2020 at 19:34 UTC

    For unsigned long, you should use L!, not L.

    For unsigned short, you should use S!, not S.


Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1148485]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2022-12-05 08:39 GMT
Find Nodes?
    Voting Booth?

    No recent polls found