@Freedo just a suggestion on the phrasing of the question; are you really wanting "bigger buffer for getdents" or: do you want to know why it's slow? or do you want to know how you can make it faster? I'm just afraid of an X/Y question that might not solve your problem.
@ilkkachu Is this a response to the comment saying that the code leaked file descriptors?
This is (as usual) probably a dumb question, but the Unix system calls for reading prominently feature buffering. In fact, it seems impossible to read with buffering, though I'm not clear why. But it seems writing does not require buffering. Again, not clear why. Which is my question.
@ToxicFrog So, there are read and write functions, including POSIX versions, which can read from file streams. They both require buffers. But there is the printf family, which writes to file streams (fprintf version), but does not require a buffer.
But all the read functions I've seen require buffers.
Why isn't there a function where you just read everywhere in there at once?
Your first question is basically "why don't fread() and friends automatically allocate the buffer for you and return a pointer to the allocated buffer"
That's a philosophical question that properly needs to be addressed to the ANSI C standards committee, but my best stab at answering it is that leaving memory management up to the caller is the more general answer; it means you can easily choose whether to stack-allocate or heap-allocate or mmap() your buffer, you can re-use buffers if you want to it, it'll work even on embedded systems that don't have any equivalent to malloc(), etc
If fread() is meant to allocate the buffer itself -- ok, how does that work on platforms that don't have malloc at all and only support compile-time allocation? Is that really what you want if you're just reading, like, 8 bytes that you can easily stack-allocate much faster? etc
If you want a function that's just "allocate a buffer the size of this entire file and copy the contents of the file into memory", you can quickly write that yourself using fseek/ftell/fread/malloc
But for that, 90% of the time you just want mmap() anyways
For your second question -- fprintf formats and prints the string in one go. It doesn't need you to provide a buffer because, if it needs one, it has its own internal buffer it uses; and not all (f)printf implementations may need a buffer at all.
It doesn't need to keep the formatted string around in memory because it gets written to the file descriptor as soon as possible, and after that it's the OS's job to deal with it.
You will note that the sprintf() family does need a buffer, and some systems (BSD, GNU glibc) provide an "asprintf" (allocating sprintf) variant that automatically allocates a buffer for you (it is of course still up to you to free it when you're done)
The broader answer underpinning all of these questions is that, to work with data, it needs to be located somewhere in memory, and in C, it is usually the responsibility of the programmer, not the language runtime, to make decisions about when and how memory is reserved for use and which regions of memory are used for what tasks; thus, functions that move data to or from program memory require the programmer to tell it where the data is coming from or going to.
@ToxicFrog Yes, something like that. Or read the entire output of a pipe. mmap looks relevant, but I don't yet understand it. I should and read about it again.
Lua handles this (in io.read()) by allocating an internal buffer and reading into it until it either runs out of input or buffer space, and expanding the buffer if it runs out of space
It would be nice, and this is why a great many languages that aren't C and have completely different philosophies of memory management implement convenient functions to do that :P
@ToxicFrog Agreed, that's why don't use much either. But in the current circumstance is appears to be the right place for the job.
Namely, writing code to handle the (somewhat) general call of calling a command. Which apparently Lua cannot be bothered to do, and which doesn't exist in C or POSIX, either.
@ToxicFrog But most languages don't have Rust APIs.
Re mmap() -- basically, it reserves a region of memory addresses large enough to hold the entire file without actually allocating memory; reads from those addresses read the file contents and writes to them write back to the file on disk.
Under the hood pretty much any OS will automatically handle copying chunks of the file into memory and back to disk as needed to improve performance, but you don't need to worry about it.
I'll ask you the same question as I asked @ilkkachu earlier. You seem to know a lot about this. So either you studied it in college and remember it well, or you use it regularly.
Rust can both call and export C-compatible APIs, so you anything that can interoperate with C can also interoperate with Rust, if you write the Rust code with an eye to compatibility.
I don't actually know what happens if you try to mmap() an fd connected to a pipe, but if nothing else mmap requires you to know up front how large the file is, which you can't do with a pipe.
> writing code to handle the (somewhat) general call of calling a command. Which apparently Lua cannot be bothered to do, and which doesn't exist in C or POSIX, either.
In POSIX that exists as fork/exec. You seem to be really fixated on having something like Win32's CreateProcessEx instead, and I'm not sure why
Like, I'm not sure what your actual, underlying goal is here, it feels like there's a lot of XY problem going on
> Putting protections in place seems to be very expensive in practice.
Rust implements most of its safety features with extremely rigorous compile-time checks. This makes the learning curve a bit steep but you spend a lot more time dealing with compiler errors and a lot less time dealing with segfaults, which is IMO a very worthwhile tradeoff.
@ToxicFrog I want something that writes standard output and standard error from the called command. popen from the Lua Posix module just mixes them together. And there's the separate issue of the command itself failing out, in which case the error message gets lost.
> I thought that's what D was going for. Though maybe it's not an exclusive ambition.
It's definitely not an exclusive ambition, although Rust appears to be the most successful so far
I tried D back in the day but, independent of any of the merits of the actual language, it was undermined by having two different mutually imcompatible implementations, so you had two competing D ecosystems that couldn't share code with each other
I wasn't expecting to spend so much time with C, but I suppose I shouldn't be surprised. And I learned something. Actually, quite a lot. The last time I did any C programming was circa 20 years ago.
@ToxicFrog So you think Rust is a better choice than D? It's from the same person who was behind Monotone, I think. Hoare?
Graydon Hoare. Yes, I think I have the same person.
> the command itself failing out, in which case the error message gets lost.
You should get the contents of stderr regardless of the program's exit status, unless it couldn't start the program at all in which case there is no error message to lose
Is there a particular reason you can't just do the quick and dirty approach of having the external program write one or both output streams to a temp file and then reading that in?
I just thought I would do it "properly". And I didn't understand the underlying mechanisms at all, so thought it would be an opportunity to learn them.
Personally I quite like lua and would use it in preference to C when I have a choice, although their problem domains are so different that circumstances where "lua or C?" is a sensible question to ask are relatively rare
@ToxicFrog Hmm. I can't say I feel much love for Lua, and I feel C is something of a solid ground for this kind of application. Because this is exactly its use case, and it's one of the worlds most widely used programming languages. So people tend to know it.
@AndrasDeak But as you've probably noticed, half the people here do. And they're just the people who happen to be here.
@ToxicFrog The proprietary flavor, you mean?
BTW, thought you were the US, but your profile is CA.
@AndrasDeak I learned quite a lot in a week. Something to build on, if the occasion arises.
Also, gcc seems to have improved considerably since I last used it. 10 years ago, gcc compiler messages were just gibberish. Now they actually tell you what is wrong.
@AndrasDeak People use that a lot too, sure. But it's a somewhat different domain. C is more common for system applications, I think.
The history is a bit complicated, but tl;dr SCO used to make commercial UNIXes and UNIX development tools, then at some point they were bought by the Caldera Group which kept using the SCO name, and at some point Caldera switched from making software to making litigation and then self-destructed spectacularly
> For an advanced user, you don't actually have much of a presence here. :-)
tbh I'm mostly connected to chat.se because of The Bridge, since some of my friends hang out there, but I like talking UNIX too, so I'm also in this channel. I'm not very active on the site proper.
@FaheemMitha Nope. I learned C somewhat, I'd still claim I can read and maybe even write it if I really have to. Apart from one program in the group that I don't use, we do fortran. And yeah, absolutely no systems programming.
The whole point of Python is productivity. You can write "working" code in no time. The price is performance and higher chance of subtle bugs (UB not withstanding).
@AndrasDeak If I decided to look at one of those, I guess I'd try Rust first, yet.
But I have no such plans currently.
As far as rabbit holes go, few are worse than trying to learn a brand new language. Especially for no particular reason.
@ToxicFrog Actually, at the risk of sounding like a freak, I quite enjoyed learning a bit of Unix Systems Programming. Stevens has been sitting on my bookshelf for 20 years.
Due to ongoing planned network upgrades, all public Stack Exchange properties (stackoverflow.com, stackexchange.com, and so on) will be in read-only mode during two maintenance windows: Saturday October 30 and Sunday, October 31, 2021.
While in read-only mode, the websites will be accessible but ...