Implement POSIX compatible '/dev/'

Project:JNode Core
Component:Code
Category:task
Priority:normal
Assigned:Unassigned
Status:active
Description

A lot of shell scripts assume the existence of device files named '/dev/null', /dev/tty', '/dev/console' and so on. Some Java applications from the UNIX/LINUX world will implicitly assume that they can open '/dev/null' etc. For example:

    somecommand > /dev/null 2>&1       # shell redirection to /dev/null
    somecommand --output /dev/null     # application (presumably) opens /dev/null

In the interests of portability, I propose that we rename the existing JNode '/devices' directory to be '/dev', and implement at least the '/dev/null', '/dev/tty' and '/dev/console' devices.

BTW, it is possible (though undesirable) to implement the first case by having the shell interpreter(s) recognize "/dev/null" as a special case in a redirection. But that doesn't work for the second case.

#1

Couldn't you also have /dev as a hidden symlink to /devices, so that users see the Jnode directory layout and the legacy UNIX layout is only there to support scripts? That's what other newish OSes do with the legacy directories.

#2

I guess we could, though I don't know what you mean by "hidden".

To my way of thinking "/dev" is standard and "/device" is non-standard. But if people really want the primary JNode file system layout to be 'better' (aka 'different') and view "/dev" as 'legacy', I won't waste my breath arguing. I won't mention the future JNode app/script portability issues this may raise ... ooops, I'm arguing Smiling.

Can we create symlinks in "/"? AFAIK we don't have a command to do this and I had assumed that this was because symlinks were not fully implemented yet. Am I wrong?

#3

There's not way to symlink at the moment. But that's not the problem. "/" (the root dir) is virtual and there's no root-file system as in Linux. The root ("/") always stays virtual and you can only mount different file systems to it. There's also no way to mount a file system in a file system (once a design decision by Ewout).

As you proposed, I'd simply rename it to "/dev", too.

I guess the reason to call it "/devices" in the first place was to make it easier for the user (more descriptive names,...). Anyway, I think this is not really needed as for the shell "/dev" is fine, too and a GUI app should give a graphical view on devices (so you still can have the user-friendliness, but on a higher level where it makes sense).

#4

As far as "hidden" goes, I mean like /bin on GoboLinux. You don't see it in directory listings but you can still enter it.

Equivalent under Jnode on the API side would be an entry where FSDirectory.iterator() does not return the entry but it is still accessible via FSDirectory.getEntry(String). The practicality of doing this for / or any level is outside my field of knowledge.

Gobo are just following the philosophy that GUI applications are not the only ones which need usability. I tend to agree; the reason most people don't use the command-line is that it's scary and (at least in the case of Linux) full of things which no longer make sense in the modern era.

Apple have made some attempt to tidy this up too, but only on the GUI side for some reason...

#5

Re "hidden". That's an interesting idea, but there are a couple of issues that make this rather hard.

1) We'd need a way to mark a file system object as 'hidden'. This is probably trivial for some FS types, but it is not trivial for FS types designed for UNIX / Linux, where files are "hidden" by using "." as the first character of the file name. In UNIX / Linux, file hiding is just a convention supported by user-space commands such as "ls". But if we named the (hypothetical) symlink "/.dev" we'd be defeating the purpose of creating it!

2) The behavioral change you suggest for FSDirectory.iterator() violates the JDK spec for the File.list methods. Furthermore, it makes it impossible to implement the equivalent of "ls -a" with the meaning list all files including hidden ones.

#6

On looking at the spec for File.list(), I don't immediately see anything indicating that it has to return all entries. I mean, it already hides some entries, clearly. Because I can get to Program Files on Windows via PROGRA~1 or Program Files. Both work, yet File.list() only lists one. I'm not really seeing how "dev" / "Devices" is any different since in both cases it's two names for the same object at the same directory... Eye-wink

As far as it being hard for Ext2, GoboLinux did it via kernel trickery. They have some way of marking hidden files in (what I think was) a file system independent fashion, but I haven't looked into it that deeply.

Yes, if you wanted to do it in some generic way for all filesystems and you needed to store that information with the files themselves, you would need somewhere to store the flag. For DOS/NTFS this would be trivial. Presumably HFS+ has a way to do it already as I am running into it all the time over there. For Ext2 and co. maybe extended attributes (assuming support for them Eye-wink) would be the place to store it. For the root directory though, presumably things are simpler? It has already been said that it is in fact *not* a mount.

#7

On looking at the spec for File.list(), I don't immediately see anything indicating that it has to return all entries.

Actually, you are right. I misremembered. But I think that you will find that the "list*" methods return all entries on Linux, including hidden ones. The only entries specified to be excluded are the names representing the directory and its parent. If the FS layer directly filters out hidden entries from the list*(...) results (rather than letting the application do it with isHidden()) then "ls -a" won't show them ... and I think that would be bad.

I wouldn't draw any conclusions from "PROGRA~1" versus "Program Files" on Windows. I suspect that the first form is considered to not exist at all from the Java perspective. Does Windows actually allocate two physical entries on the disc in this case? Or is this just an illusion presented by the Windows runtime libraries for the benefit of legacy applications?

It has already been said that it is in fact *not* a mount.

I don't think Peter said that. I think what he said is that "/" is not part of a file system in JNode, but is the name for the place where filesystems are mounted. Since "/" is not part of a filesystem, you simply cannot create a symlink in it, hidden or otherwise.

So there is not really a lot of point to this discussion, is there ... Smiling

#8

I think Daniel made a point here and we should find a solution to implement it.
Probably it's sufficient that the /dev/ filesystem will be only visible to the Bjorne environment and not visible for the rest because the rest wouldn't use it anyway. So, /dev/ is a special case just like /jifs.

#9

Well as Peter pointed out, the simple answer is just to rename /devices to /dev. Peter's point about /dev not being significantly user-unfriendly is also well made. It is a well known fact that most non-technical users don't type in pathnames: they click on icons on the desktop or a file browser.

Building infrastructure to hide "/dev" from File.list() is overkill (and a bad idea). Making "/dev/..." only visible in the Bjorne environment is overkill (and a worse idea. For heavens sakes, do we really want pathnames to resolve differently in different environments? This just sounds to me like a recipe for implementation and usability problems.)

If we really, really want both "/dev" and "/devices", we should figure out how to bind multiple names in the root FS namespace to a single mounted filesystem ... or something like that. But the most important thing is that Java code (including the Bjorne interpreter and regular applications) gets stream objects with the expected behavior when it invokes the FileInputStream(...) constructor for "/dev/null", etc.

#10

I guess keeping the console scary guarantees that the non-technical users are going to stick with the GUI, thus creating a self-perpetuating truism that GUI users are not going to use it.

Of course if it were easier to use, they would... but that isn't the point, is it?

#11

I honestly think that trying to make the console non-scary for non-technical users is quixotic. It simply won't work. The best text console based user interface you could ever come up will be far less intuitive and far harder to learn than a well designed GUI-based equivalent. The reason is that the human mind just works better with pictures than with text. Its an evolution thing.

You and I use a console interface because once you have learned the idioms, you can do complex things a lot faster (and with less stress on the fingers) by typing. But most non-technical folks don't need to do complex things with the user interface. For them, GUIs are the right answer.

I'm not against making the console interface intuitive. But I am against gratuitously breaking portability in the name of intuitiveness or "non-scariness". IMO, portability is by far the more important goal, in the command console, scripting and so on.

#12

I recognize the need for the /dev/ filsystem in the Bjorne shell but I'm not sure why do you want to have it by renaming the current /devices directory. By looking at the actual role of the /devices directory within the system I would consider it an analogy of the /mount or newly /media directory of the linux distributions which contains mounted file systems recognized while booting JNode. The /dev filesystem would need to be a special filesystem like /jifs which contains special files named after the devices registered in the device manager. So these are two completely different things. Now a lot of questions arise like how to map the devices to files and do we need to map all devices to files? We should not forget that goal of JNode is not to write a Unix clone in Java. Therefor we should push these unixish features only as far as they make sense for JNode, anything more would be a waste of time.
So one thing that could be done is to create a special file system which will be available under /dev. In the beginning it will contain one special file /dev/null and later we will see what else do we need here.
Since /dev is a special directoy in the root directory it will not be too hard to handle it in a speciffic way if we need to hide it or show it in various situations. I consider the /dev file system as a special feature needed for some level of Unix compatibility under JNode with no general interest for other services of the system. For that case we already have the device manager and we are using it.
Therefor I would prefer hiding /dev in most cases because it only adds complexity to the overal view of the file system with little interest to most users and usecases.
The JNode file system layout is still needs to be determined anyway and the current one should not be considered as final. This is still a completely open issue.

#13

Are you suggesting that /dev and /devices could be distinct special file systems? That would work for me. Or making /dev and /devices as aliases for the same special file system. A simple rename is easier to implement of course, and given people's past reactions to my attempted FS fixes, it is the only alternative that I'd dare to implement myself!!!

I am not trying to turn JNode into UNIX. I'm just trying to make it compatible in ways that will help folks who need to implement applications and systems on both JNode and Linux. So for example, I don't particularly care whether the existing JNode device files systems are mounted in /dev in /devices or in (say) /mount. This isn't a significant JNode / UNIX portability issues because scripts and apps that depend on specific names for file system mount points are most likely non-portable for a variety of other reasons. (But calling the mount point /mount is aesthetically pleasing ...)

Now a lot of questions arise like how to map the devices to files and do we need to map all devices to files?

Off the top of my head ...

  1. We could implement "null", "tty", "console" etc as JNode Devices, and modify the device manager so that devices could be mapped into /jifs or /dev or somewhere else. Sort of like having multiple JIFS instances. Or something else if that is too hard to implement.
  2. We certainly don't need to map all devices to entries in /dev. But we don't need to not do it either. A portable app / script is unlikely to refer to (say) /dev/eth0, but it is unlikely to care if one exists. So, I'd vote for whichever is easiest to implement.

I'm happy to leave implementation details to the person who implements /dev.

#14

There is not much special about /devices right now, because it's a directory in the JNode VFS which contains other directories in the JNode VFS and in these directories we mount the file systems found on the hard disks and cd drives.

So yes, basically I suggest to create a new special file system type like devfs with the default mount point /dev and in this file system to implement the necessary mappings to the required devices.