Approaching the File System II |
[Webmaster's Note: Doug took our request that he "Check the transcript for technical accuracy" to mean "Check the transcript for technical accuracy, clean up your strange speech patterns, and add a little comedy." While this transcript is technically accurate, it's not an exact recording of what Doug said during his presentation. ]
DOUG FULTON: My name's Janet Jackson.
I'll be talking about the API to the file system. This includes, to a certain extent, the POSIX level. But we'll mostly concentrate on the C++ level. We're going to hit the high points. You're probably not going to learn enough to port your DR8 application into a DR9 application. Out of the hundreds of classes that are in the storage kit, we'll only look at the two or three that you really want to pay attention to.
There aren't really hundreds.
There are two approaches: The object oriented C++ API, which is part of the storage kit (which is what we're going to be talking about here), and the POSIX API, with the extensions that we've given to it.
So why do we have both? This is a religious issue, mostly.
POSIX folks want POSIX, it
makes porting easier, and if we don't give them a visible POSIX level,
they'll post to news groups and make our lives hell. But if
we've got that, then why an object oriented C++ API? Well, it actually is
easier to use, and most people who are designing
applications with the BeOS are going to be using objects anyway. It's easier
to have file objects around and directory objects around and manipulate
those, walk around the hierarchy with those, read and write data with those,
than it is to use these C functions that some people aren't necessarily
familiar with.
So anyway, next slide, please.
The API at all levels, POSIX level and at the C++ level, gives you [Image] what you would expect to see: Traditional features such as reading and writing files, creating and deleting files (that includes directories, creating and deleting directories). You can do that with POSIX or you can do that with C++. And at both levels the file system is organized hierarchically and you can navigate the hierarchy with POSIX' readdir() or by looking at a BDirectory object--which actually is one of the places where the C++ level is considerably easier.
And symbolic links. It's a sort of semitraditional feature. It's new in DR9
and you can get to symbolic links both at the POSIX level and at the C++
level. We're not going to talk about symbolic links very much, however.
The advanced features. These are things that the BeOS gives you that you won't find on other platforms. A lot of these have already been gone over. Dominic and Cyril talked about attributes, the name value pairs that you can attach to any file or directory or symbolic link, for that matter.
The ability to watch files and directories. This hasn't really been talked about yet. This is something called the node monitor. The node monitor is a system that allows you to tag certain directories or files, something that we call a node, actually tag the thing itself. So if you say here's this file, it has my whatever in it, my information about my data book, my notebook. I'm going to watch to see if anything happens to it. If the name of it changes, if the size of it changes, if it's moved to another directory, I can tell the node monitor to let me know.
The nice thing about the node monitor is that it works across all volumes; it doesn't have to be the Be file system. It can be a foreign file system and the node monitor will still work. That's not true with queries. The file system has to support attributes, of course, in order for queries to work. The node monitor works on anything.
Queries across the entire file system, and the file typing mechanism based on MIME -- these have already been discussed by Cyril and Dominic.
Move on.
Okay. The design goals -- now we're moving over to the C++ level. [Image] The design goals of the C++ Storage Kit. Of course, the most important thing is to appease John Watte.
Starting at the top we tried to balance efficiency and ease-of-use. Is the C++ level faster or easier to use than POSIX? Well, of course it's not going to be faster. It's going to be a little bit slower. There's going to be an object-oriented layer that you're going to be going through. But does it really make any difference? If you're reading and writing a bunch of data, who cares? You're going to be disk bound anyway. You're going to be limited by the I/O speed.
So the overhead, which is actually quite minimal, the C++ overhead doesn't really make that much difference. So is it really that much slower than POSIX? Well, in the tests that we've run it depends on what you're doing. With POSIX you're chdir()'ing and you're readdir()'ing and you're dealing with file descriptors. You're pretty close to what it is that you want to access. When you move up and down the file system hierarchy, you're dealing very directly with tokens that can get you from one place to another very quickly, but you have to be smart about it in order to do it correctly. You have to chdir() to the right place and all of that. But once you get there you don't necessarily get a whole lot of information, don't get a whole lot of extra information that you might want.
With the C++ level, you do a similar sort of thing but at a nicer level. You get a directory object which is sort of an implied chdir(). And you look at entries inside of there and these entries have more information than you would get just from the file descriptor or just from the name, from doing a readdir() or just from the dirent. So it's not really fair to compare them. This isn't all leading up to me saying that well, yeah, it's grotesquely slower: It's really not that much slower. There's really not that much of a hit in efficiency by going to the C++ level.
Ease-of-use. Well, this again is just a religious war. I mean it depends on what you're used to, what it is you want to do, whether you really want to stay in POSIX. The C++ layer is, for the most part easier, in my opinion anyway. Dominic will give you another one. C++ layer is a little bit easier, is easier to use. Not just a little bit, it is easier to use.
Another design goal: Consistency between the API and the underlying file system. We wanted the C++ API to reflect what the POSIX layer actually was doing and what the file system was actually doing. The objects that you get at the C++ layer do not have a state that you can't get at from the POSIX layer. So in other words, the storage kit doesn't jam together a bunch of attributes from the directory and shove them into a file object, such that the file object that you've got doesn't really reflect what's going on at the POSIX layer.
In this way when data is changed on the disk you get to see it clearly and obviously, if you've done the correct things. If you're node monitoring or querying or whatever or if you go and look again, you're not going to be fooled into thinking that you've got some sort of super object that knows more than it really does.
Transparent support for external file systems. That's already been discussed. And, of course, appease John Watte, the number one consideration for designing the C++ layer.
The key concepts. The most important concept and the one that is the hardest to get used to--at least for the folks around Be that have been looking at this and been trying to use it: There are entries and there's data. This is actually not a new concept, but in POSIX it's called path names and file descriptors. There's just not a whole lot of support for dealing with path names in POSIX. You've got a path name, you go find the file, you open it up, you have the file descriptor, now what? Well, if you've lost the path name, you're done. You don't get to go back, you can read and write data all you want, but you don't get to go back into the hierarchy.
In the C++ layer that's not true: Entries are the locations of your data. We have objects that cover the entry level. In other words, we have objects that simply tell you where something is, that know how to keep track of where that thing is. Then there are objects that cover the data level, objects that know how to read and write. These are separate.
Directories -- going into more about what an entry is, directories, of course, contain named entries. So the directory is the container for these entries, what we would normally call the files. An entry has associated data -- whenever you've got an entry there is data associated with it. The entry knows how to get to the data.
So in other words, an entry object knows how to get the object that can read and write the data. These are two distinct concepts and the class design clearly reflects this, as we'll see in the next few slides.
Of the three classes that reflect this, the first one is BEntry. BEntry is the class that represents entries in a directory. An entry object is simply a name inside of a directory where a directory is identified as a directory ID and a volume ID. So the directory is uniquely identified and the name of the entry is then identified as a name. If it changes, if the name changes then the entry has changed. It can refer to a file or directory. A BEntry is generic, it doesn't consider the flavor of the file, whether it's actually a file or a symbolic link or a directory.
A BEntry is simply a location inside of a directory. It gets access to the
name of the location, the hierarchy so you can get and change the entry name
to the BEntry, you can get the parent directory of the BEntry. You can
move and remove the file or directory, whatever this BEntry talks to,
whatever it refers to, through the BEntry object.
The BFile and BDirectory classes -- I'm being urged on -- they know how to read and write data as is commanded according to the class. So the BFile knows how to read and write file data, raw data, you know, whatever the thing is supposed to open, whatever the file is supposed to hold, whether it's structured or just flat. The directory knows how to read and write its own contents, which we'll get to in a second. You're not simply opening up a BDirectory object and saying read me some data and then you get it back in this raw form and you have to figure what it is that the directory contains.
The BDirectory class, of course, gives you slightly more humane access to
its own contents. And it can read and write attributes. Both the
BFile and BDirectory classes know how to read and write attributes for the
file or directory that they represent. This isn't true of BEntry. BEntry
can't read and write attributes. It's simply there to locate the file and
then if you want to look at the file's data you have to turn it into either a
BFile or BDirectory, depending on what flavor of entry that you've got.
The BFile class support data reading and writing -- it simply supports read, write and seek, just like you would expect, from, you know, any object that could read and write data. You can position it and then read a certain amount of data or back up and read some more, write to it. It can extend itself.
In relation to POSIX, there is no open and closed, so when you create a BFile object, you tell it the name of the file that you want to open and give it a reference to the directory. You can do this through an entire path name or by passing in a BDirectory object and a name or by passing in a BEntry object. However you want to refer to the thing as an entry, you pass that into the constructor of the BFile and the BFile constructor will give you a file object that knows how to read the data that is contained in that entry. It doesn't know about its entry after it's been created so even if you pass in a BEntry object to the BFile constructor, once the file's been created it doesn't know anything about location in the file hierarchy. This is one of the things that is difficult for people to accept. It's really not that hard to understand, but it's sort of difficult to accept. They expect a BFile--something that is called a BFile object or a BFile class--to be able to not only read and write the data that the file contains, but to know where this data is. But it simply can't because of the consideration, the design goal that we wanted to keep this consistent with the file system itself.
What would happen if you opened up a file and you were reading and writing the data that was based on a particular entry and then the user renames the file? The entry that this object would refer to or the name, if it stored the name, would no longer be accurate. There may be no good way to update it. It's analogous to the file descriptor at the POSIX level. The file descriptor in POSIX doesn't know anything about where it's located.
Continue. The BDirectory class. It knows how to iterate through its entries. You open it up by creating it and then you say GetNextEntry(), GetNextEntry(), until you hit NULL. You can also find a specific entry. If you suspect that there is a particular entry, a particular name in that directory, you can ask the BDirectory to pass this BEntry object back to you directly. And it also works with relative path names, so if you've got a BDirectory object and it contains a subdirectory, however deep, that has an entry in it, a file or directory that's got a particular name, you can ask the BDirectory to descend from itself down to however many levels of subdirectory that you want to go to find it. And the BDirectory knows how to create new entries. It creates specifically a file or it creates specifically a directory or specifically a symbolic link.
One thing about BDirectories that's not true of
BFiles is that the BDirectory does know its own entry, so the BDirectory can
be linked back into the hierarchy. If you've got a BDirectory object, you
can get its parent and you can ask for its name. BDirectory is sort of a
hybrid, but the basic use of the BDirectory is to look at the data and the
attributes where the data is separate entries in the BDirectory.
Now, how do you refer to these things? In your application what are you going to be dealing with? We've introduced three classes here: BEntry, BFile, BDirectory. We want to separate them, BEntry on one side, BFile, BDirectory on the other.
Now, I want to send something to somebody else. I want to send a reference to a file. What am I supposed to send? If it's in my own application can I send a BFile object, should I send a BEntry object? We have a separate class called BPath, which is a handy little class that represents path names. It does allocation for you: When you pass in a string, it allocates the storage for that. Then you can append a leaf to it. You can ask for a pointer to it. It also knows POSIX path name indirection such as dot dot, it knows what dot is, it knows how to coalesce slashes if you've got more than one slash. It's a nice handy little way to represent an entry, a location in the file hierarchy. And we have something called an entry ref. Entry ref is a structure that also identifies an entry. It identifies an entry as a leaf name within a directory. It also knows the volume ID, so it can uniquely identify the directory.
You can use either one. You can use the BPath object or you can use an entry ref to tell some other application or to tell some other part of your own application, to pass as an argument to a function, to let the other function or other application know about a reference to a particular entry.
If you want to refer to data, if you want to refer to a file on the disk, you pretty much want to stay either with a path name or an entry ref and this is again, this is sort of to taste. If you want to stick with path names you can, but if you want to use this slightly smaller, somewhat more compact way of referring to a file through the entry ref structure, you can do that as well.
And yeah, BPath and entry ref can also be used as tokens to create a new BFile or BDirectory object or a new Be entry, for that matter.
File and directory information: POSIX has a notion of stat structure, which is -- gives you information, statistics about a file or directory. Both BFile and BDirectory know how to get to this information, as does BEntry. So you can get statistical information about your entry either at the entry level or at the BFile, BDirectory level and there's some convenient covers.
We have another class called BStatable from which these other classes inherit, mostly just for the protocol, that cover most of the stat fields so you can ask the entry if it's a file or a directory, you can ask for the size of a file or directory, you can set the size, modification time, owner. This is all -- these are all just covers for the stat call itself. You can actually get the stat structure back directly if you want.
That's the brief overview of the C++ API level for the file system. Steve Horowitz has got some source code that he's written which sort of shows you what this looks like.
This is a RefsReceived(). In DR8 there was a notion of a ref, but that was a RecordRef. A RecordRef was a unique identifier for a record in the database. There is no more any notion of a completely unique identifier for a record in a database. There is no database, there are no records. There are only files on the disk. You can't have a persistently unique identifier for a file, you just can't do it. You know, you mount a -- you put a floppy in and you get a reference to it somehow, pop it out, put another one in and it may end up with the same volume number, you may end up referring to a file that looks like the file that you were referring to before, but it isn't because it's on a different floppy. You just can't do it. It's not possible, unless you write to the floppy, which would be one way to do it, but not on a read only file system.
So anyway, refs in this case mean -- when you see ref these days in the DR9 API, it's referring to an entry ref and entry refs, of course, refer to locations in the file system. So when you get a RefsReceived, as many applications do when somebody drops an icon on you, you do the normal FindRef. This API hasn't changed from DR8. You do just -- it's what you get out of it that has changed. And what you're trying to find in the message is an entry ref. So you go through and you iterate over this, getting your refs stored in the refs field of the message. And in this case the ref is used, is passed to this application, a function of this particular application that wants to take that ref and open it as a document.
So what this application does is take the entry ref by reference in its OpenDocument() function, makes a BFile on the stack, creates the file or makes it refer to the reference, the referred to file through a function called SetTo() and then takes the file and looks through all the windows that it's already created. Looks at each of the -- it iterates through all the windows that it's created so far and asks each window for the file object that that window represents.
This is jumping ahead a little bit. This is assuming that each time you get a RefsReceived you want to open up a document that has the data from the file. So it asks the window for the file that it represents and asks if it is equivalent to the file that was just created based on that entry ref and if it was it says okay, I already got this guy, so he returns the -- returns that window.
Now, the comparison here is not comparing an object to another object. It's comparing the reference to the file, the ultimate reference to the file on the disk to another reference to the file on disk. These are actually two different BFile objects that are pointing to the same file, which, of course, you can do. If it doesn't find the object in any of the windows then it's going to go ahead and create a new one, which it does here. And here it passes a reference to the file object and it passes the entry ref as well to the constructor of the TDocumentWindow class. And it passes the file object here simply so that the window can record the file that has already been opened. The TDocumentWindow constructor could simply take a ref and create another BFile.
Since the BFile that's used here is created on the stack, when the function in this frame is done the object will be destroyed. When the object is destroyed, the file is automatically closed. So it's that simple.
Going down here, showing a simple use of some of the other functions that we have in the API. Here we have another static object for a BDirectory. It's going to open /boot and then go through and simply get all the entries that are in /boot and ask each one of them whether it's a file or a directory or symbolic link.
Iterating through is simple. First it does a rewind; that's not entirely necessary. It's like opening a file, you're going to be at the top of the file, but it's not a bad idea to rewind the thing just to make sure that you're going to be getting the first entry out of it, just in case, even though it's impossible in this case that you wouldn't. Then it iterates through, gets each of the entries, gets the name, stores it for a second, asks if it's a file. If it's a file it's going to print its name and say it's a file, is it a directory, is it a symbolic link.
So this shows a use of getting information out of the -- out of the entry and here we've not used any BFiles or BDirectories to represent the entries in the root directory. These are all using a BEntry from the -- from the time that we get the entry out of the directory.
So that's it for the -- the overview of the C++ API. Are there any questions?
Yes?
A SPEAKER: Is there a limit to how many BFiles you can create at one time?
DOUG FULTON: Yeah, each BFile is a file descriptor and right now there's a limit of 128 file descriptors that you can have in your -- Cyril's here -- that you can have in your application. In your application, not across the entire system, of course, but each application can only have 128 file descriptors, so --
CYRIL MEURILLON: But that's going to change. The real DR9 you will be able to up that limit of 128.
DOUG FULTON: On an application basis.
Yes?
A SPEAKER: Do they have a BPath for an entry? Can you get the other one, create a BPath?
DOUG FULTON: In the case of BPath you can create -- it depends on what you've got already, but let's say you've got a BPath. You can create an entry out of that and then get the entry ref out of the entry. Right now you can't go directly from a BPath to an entry ref, but you can go directly from a BPath to any of the other objects and then from there, as long as you're not going over to a file. Then if you go to a BEntry you can get the entry out of that.
Yes. In the back.
A SPEAKER: So you're kind of using this directory option as handle code kind, sort of like an -- I assume that you have multiple directory objects open on the same entry?
DOUG FULTON: Umphumble. Quack quack quack. I've been hit.
A SPEAKER: So let's say that you created one of these BDirectory objects and you said get next entry, get next entry.
DOUG FULTON: Right.
A SPEAKER: And could the same entry ask the constructor of another BDirectory do a rewind that's not going to rewind the first BDirectory?
DOUG FULTON: Yeah, each BDirectory object, even if they're referring to the same BDirectory, will have it's own set of iterators, yes.
A SPEAKER: Is the file system still limited to 64 folder nesting limit?
DOMINIC GIAMPAOLO: What folder nesting limits?
CYRIL MEURILLON: The file system has been completely rewritten.
DOUG FULTON: You'll be limited by the path limit, which is right now 1024.
DOMINIC GIAMPAOLO: There is a maximum path limit of 1024 characters, so theoretically you have folder nesting at 512 levels, with one character names.
DOUG FULTON: Yes?
A SPEAKER: Are entries and symbolic links tied to path names? That is, if I, like, rename a directory on the fly or move a file from one directory to another, does that invalidate entries on that and does it invalidate symbolic links that point to it or do they work the way aliases do on the Mac?
DOUG FULTON: We're sort of in the middle of hashing that out. We will have something that is akin to aliases, that records more information than simply -- if you start with a symbolic link and say this is sort of like the basis of what an alias is, it points over here.
A SPEAKER: Is it a path name or is it a directory name?
DOUG FULTON: Which?
DOMINIC GIAMPAOLO: Symbolic link is a path name.
DOUG FULTON: Yeah, and then at the alias level it records more information than that. The Inode, the volume that it's on, the size, so that if the symbolic link gets broken or if somebody moves it after you've already cached this path name, which you will have converted into an alias, you might be able to find it. You should be able to find it. Depends on how much time you want to take to sit and paw over the disk. There are different levels.
A SPEAKER: Is there even such a concept as a unique ID for a directory or --
DOUG FULTON: Not consistently.
CYRIL MEURILLON: There is at the lower level, but making it public creates a lot of problems.
DOMINIC GIAMPAOLO: Support for external file systems, for example NFS, would make it impossible to have a unique ID, because there's not enough information to do that.
CYRIL MEURILLON:Because that ID will not be persistent. It should reboot -- if you keep that ID, if you store that ID in a file and try later to reopen the file giving this ID, you will end up opening random files, because it is not persistent. In other terms, not all file systems can generate persistent file IDs.
A SPEAKER: I noticed in one of the earlier demos that he attempted to drag and drop a file on a symbolic link and it didn't work. Then when he found the original and then he dragged and dropped it on the --
STEVE HOROWITZ: It's a bug. It will be fixed, like, tomorrow probably. My bug.
DOUG FULTON: Yes?
A SPEAKER: Are file names still limited to 64 characters?
CYRIL MEURILLON: No, 256.
DOMINIC GIAMPAOLO: 255.
DOUG FULTON: Over there.
A SPEAKER: Does BDirectory understand Wild Cards?
DOUG FULTON: BPath name understands -- well, it depends what you mean. You mean like look for star inside of --
A SPEAKER: Well, will your iterator here be useful to pass a wild card in?
CYRIL MEURILLON: No.
DOUG FULTON: It doesn't right now.
CYRIL MEURILLON: Will it?
DOUG FULTON: It will be done tomorrow.
CYRIL MEURILLON: No, this is -- Wild Cards are shallow things. It's a different level and we don't do that in BDirectory.
A SPEAKER: Since the database is gone does that mean that you no longer need to have a BApplication to use this?
DOUG FULTON: Since the BDatabase is gone does that mean what?
A SPEAKER: That you no longer have to have a BApplication around so you can use BFiles and BDirectories?
DOUG FULTON: Yes.
CYRIL MEURILLON: That's true. So it's kind of simpler, says BFile, BDirectory in an application which is C++ but doesn't have the BApplication.
DOUG FULTON: Straight back.
A SPEAKER: The former system seemed to be good for identifying empty cells in the rays by having a directory identify a potential cell. How do you do that now if cells are empty and you have no files associated with those cells?
DOUG FULTON: You want to make an empty cell?
A SPEAKER: Essentially. Make a ray.
DOUG FULTON: Actually, one thing that I didn't mention here that I should have, BEntry and entry ref can be abstract; they don't have to exist. You can create a BEntry for a file that isn't there yet. This is essential for, say, a save file panel. The user wants to type in the name of the file that he wants to save it as, this comes back to you as an entry ref. Well, it doesn't exist yet because you haven't written it yet, so you can create --
A SPEAKER: Versus files that have no data base?
DOUG FULTON: Yes, it's a path name at that point essentially. The directory has to exist if you're using entry ref, but the leaf name doesn't.
A SPEAKER: You mentioned that the symbolic link and the attributes don't work with other file systems. What about with Be running nonlanguages from the code, will it recognize Kanji?
A SPEAKER: Repeat the question.
CYRIL MEURILLON: Well, the question is can we put Kanji tractors --
DOUG FULTON: Let's say you're running Unicode and you've got attributes in Unicode, A, will that work, will that work in a port in a different language and B, If it does, will it be recognizable if you took it to a 9-Kanji bits?
DOMINIC GIAMPAOLO: You can store Be Kanji file names. In fact, I was surprised Hiroshi didn't show it, he has some. I walked over to his cube one day and he had files names with Kanji in them. Cool. It's just storing strings that attach -- UTF-8 is the way the way we store Unicode characters. So yes, you can have them, you can have a symbolic link to a Unicode name -- I mean UTF-8 name, any of that. Does that answer your question?
CYRIL MEURILLON: What about queries, though?
DOMINIC GIAMPAOLO: Same things. You can actually do string compares on Kanji -- on UTF-8 strings, so that's okay. The file system is actually fairly unaware that there's UTF-8 being stored.
A SPEAKER: Would they have to be to be able to do string compares correctly?
DOMINIC GIAMPAOLO: To do correct locale sorting, but there is actually no collating sequence for Kanji. We could collate sequences that exist, but are extremely complicated and so yes, to do correct string compares, you're right, but to do correct string compares requires an awful lot of code that's not going to go in the file system.
A SPEAKER: Now, you extended the file name length to 255 characters, but the path name is limited to --
DOUG FULTON: 1024.
A SPEAKER: 1024?
DOUG FULTON: Yeah. If you've got four, you know, three directories that are 255 characters long, then yeah, you're only going to be able to have one more level of 255 character files underneath that, but that's --
DOMINIC GIAMPAOLO: I did some interesting studies on that. I did a survey, had posted a little shell script and out of about half a million files that people had run the script over, there was one file that was 144 characters long and that was the longest one. 90 percent of the files were under 32 characters in length and then there was a smattering in between there and 144. Given that, that experience, the file name length of 255 characters maximum path found is 1024, I don't see it as a significant limitation.
UNIX has existed for 25 years at 1024 and I know of no one that's has actually hit into it, so I just accepted that as just valid data that is not a problem.
A SPEAKER: Doesn't that mean there is a nesting limit in the file system?
DOMINIC GIAMPAOLO: Yeah, I said 512, with one character directory name.
A SPEAKER: Actually, can't you do chdir and then use relative path?
CYRIL MEURILLON: Of course.
DOMINIC GIAMPAOLO: Yeah, for complete path name, but the file system itself has no problem. You can nest as far down as you want if you use relative path names.
A SPEAKER: So that would be the work name?
DOMINIC GIAMPAOLO: Yeah. Do you actually have file names longer than --
A SPEAKER: No, no.
DOMINIC GIAMPAOLO: I'm curious.
A SPEAKER: My point is we've increased the name of the file names, the length of the file names to 255, but we didn't extend anything else. It just seems why do that then? Why not make it if you think it should be, you know, 128 --
A SPEAKER: Is there error checking or will the class that represents path names just crash and overwrite memory?
CYRIL MEURILLON: There is indeed error checking.
DOMINIC GIAMPAOLO: There wasn't at first, there is now.
DOUG FULTON: In the back.
A SPEAKER: These numbers, 255 and 1024, that's considering all the UTF-8 characters go into one byte?
DOMINIC GIAMPAOLO: It's 1024 characters, not necessarily glyphs. If you have 3-byte glyphs then it's, you know, whatever, 300 and some.
A SPEAKER: You parse the file descriptors?
DOUG FULTON: Oh once you're in the file descriptor, yeah, this is another thing that it might be nice to be able to take a file descriptor and be able to get some information out of it that you could then convert into a BFile, but you can't. And you can't go the other way either: Once you've got a BFile you can't ask for the file descriptor out of it. We could do that but why? You're either in C++ or you're in POSIX and you pretty much want to stay in one place or the other for the most part. There are still things that you can do. You can mix POSIX and C++ and get a lot out of it, chdir is a very good example. If I know that my application, you know, is directory savvy and wants to chdir and wants to do a relative path name off of that, then yeah, you can win by moving around in the hierarchy and then picking up files from there. But for the most part when it comes to actually getting the data out of the file you either want to be in POSIX land or C++ land. You can't really mix them, it'd be silly to. You might end up with two file descriptors onto the same file when you didn't intend to.
Actually, that reminds me of another thing -- oops we're done? These things aren't meant to be multithreaded. How's that? Shall we take one more question?
Thank you.
Home | About Be | Be Products | BeWare | Purchase | Events | Developers | Be User Groups | Support