A Grail Millennium Project
White Paper
This document is maintained by the author, Lewis A. Sellers, somewhere in the mountains of East Tennessee, the United States of America. It is an informal technical document for a works in progress project called Grail Millennium, or fully, The Minimal Operating System of Object Class Interfaces Holy Grail for the Millennium. In other words, for a new, easy to use, long-lived operating system.
Copyright Notice
This document and all material therein, unless otherwise stated, is Copyright © 1995,1996, Lewis A. Sellers. All Rights Reserved. Permission to distribute this document, in part or full, via electronic means (emailed, posted or archived) or printed copy are granted providing that no charges are involved, reasonable attempt is made to use the most current version, and all credits and copyright notices are retained.
Distribution Rights
All requests for other distribution rights, including incorporation in commercial products, such as books, magazine articles, CD-ROMs, and or computer programs should be made to the primary author Lewis Sellers.
Warranty and disclaimer
This document is provided as is without any express or implied warranties. This is a work-in-progress, and as such will contain outdated or as yet uncorrected or substanstiated assumptions. The author, maintainer and/or contributors assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.
WWW Home Sites
You can currently find home sites to this project at If you can not reach them, or they seem to be down, do a key word search on AltaVista, Lycos, or the Web Crawler search engines.
Contact Email
The primary author of Grail Millennium should be reachable at lsellers@usit.net.
OCI/Spec | LONG-TERM MEMORY
DESIGNER
Lewis A. Sellers (aka Minimalist) lsellers@usit.net
CRITIQUED BY
- Anis Ahmand bq689@freenet.carleton.ca (pre a0)
- Cleo Saulnier p8uu@jupiter.sun.csd.unb.ca (a0)
- Bryan Hanks bhanks@sunfse.ese.lmsc.lockheed.com (a1)
DRAFTS
- August ? 95 revision 0 - .31
- 2/1/96 revision 0.32
- 2/2/96 revision 0.33
- 2/6/96 revision 0.34
- 2/14/96 revision 0.35 (first WWW appearance)
- 2/18/96 revision 0.36 (minor collapse of rev numbers for "public at a1.00" scheme)
- 2/20/96 revision 0.37
- 2/21/96 revision 0.38
- 6/1/96 revision .40 (third ressurgance of Grail as "Millennium")
- 7/31/96 reivsion .50 (begin rewrite for www 0.12)
(a0.50)
The Philosophy
Grail itself is an object-oriented system. Merge this with my desire to completely do away the static boring far-too-generalized GUI that most operating systems present and you have the seeds by which the Grail file system sprang.
The filesystem's core difference with many others is that allows a file to hold any information associated with it with it, thus allowing you to divorce yourself from a GUI and rely upon a metaphoric interpretation of the file system for navigation through itself, etc.
An Brief Overview
The Grail File System is rather unique. Grail utilizes a two-branch file system with dptr (32-bit dwords on Intel processors) layered IDs. That is, for instance, filenames, etc are treated as extraneous information in the associative branch, thus granting them a variable ASCIIZ/UNICODEZ length in the range of 4gb (on intel machines).
Each file is composed of a BINDING, an ASSOCIATIVE BRANCH and a DATA BRANCH. The binding contains a 32-bit ID relative to the current subdirectory (which also has a 32-bit id), groups of file flags, and couple 32, 64, etc bit values containing the pointers to the beginnings of each branch and their lengths.
The DATA BRANCH contains the raw data of the file.
The ASSOCIATIVE BRANCH contains everything else you'd every want to know about the file. It is: ICO, INI, thumbnail, comment file, FILE_ID.DIZ, prefs, read_me.1st, copyright notice, registration key, save game folder, and metaphor guise descriptor, etc all rolled into one. Any application/object in the Grail FS generally uses it's own associative branch to keep track of all things pertaining to itself. NO EXTERNAL FILES ARE NECESSARY.
Table of Contents
Legal Notices Who gets sued and why History Changes and who made them Preface About the FS and the people that make it
Overview An Overview of File Systems Anatomy The structure of a file Heirarchy The heirarchy of file objects
A File Systems Overview
BY | Lewis Sellers lsellers@usit.net
The Philosophy
Grail itself is an object-oriented system. Merge this with my desire to completely do away the static boring far-too-generalized GUI that most operating systems present and you have the seeds by which the Grail file system sprang.The filesystem's core difference with many others is that allows a file to hold any information associated with it with it, thus allowing you to divorce yourself from a GUI and rely upon a metaphoric interpretation of the file system for navigation through itself, etc.
An OverviewThe Grail File System is rather unique. Grail utilizes a two-branch file system with dptr (32-bit dwords on Intel processors) layered IDs. That is, for instance, filenames, etc are treated as extraneous information in the associative branch, thus granting them a variable ASCIIZ/UNICODEZ length in the range of 4gb (on intel machines).
Each file is composed of a BINDING, an ASSOCIATIVE BRANCH and a DATA BRANCH. The binding contains a 32-bit ID relative to the current subdirectory (which also has a 32-bit id), groups of file flags, and couple 32, 64, etc bit values containing the pointers to the beginnings of each branch and their lengths.
The DATA BRANCH contains the raw data of the file.
The ASSOCIATIVE BRANCH contains everything else you'd every want to know about the file. It is: ICO, INI, thumbnail, comment file, FILE_ID.DIZ, prefs, read_me.1st, copyright notice, registration key, save game folder, and metaphor guise descriptor, etc all rolled into one. Any application/object in the Grail FS generally uses it's own associative branch to keep track of all things pertaining to itself. NO EXTERNAL FILES ARE NECESSARY.
"Mm. Ok, but what's all that mean?", you might ask.
It means that, a little like the Macintosh systems, you can store information associated with a file in a different branch (fork) of that file. Think of a saddle bag, if that helps. One side of the bag holds the actual data or program of a file, the other side holds information about the file which may include it's name, the authors name, a graphic icon representing the file, some user preferences on how to use the file, it's x/y/z location on the screen, etc etc. Almost every bit of information relating to that file is stored in it's associative branch. Nice, neat and tidy.
One of the first things people notice about this, is that the file's name itself is held in the associative branch just like any other information. And yes, this does mean that on the current Intel platforms filenames can be up to a little over 4 billion characters in length (or 2 billion if using Unicode).
I don't want to hear anyone complaining about filename lengths being too short from now on, ok? :-)
Anyway, the Grail FS can either use it's own partition, or exist on a DOS partition as a huge permanent file (similar to a Windows SWAP file). There are only a few slight differences to the core, and NONE to the application.
Grail tries to hide all the differences between devices. Grail does not try to adapt it's interface for new or badly designed storage devices, it either subsumes them with Grail FS spec drivers, or just does not support them.
The file system is the only part of the core that is required to upgrade itself on a device per device basic. Filesystem devices include standard floppy, hard drive and tape backup units, as well as modems, 16650 devices, and ethernet connections.
A History: The Evolution of the GRAIL Filesystem
It all began when I decided to get rid of the horrid FAT filesystem of DOS. But the information describing how the file mapped onto the storage device had to be held somewhere. Thus, after forming the idea that each file should manage its own such information, the file associative branch was born.
Initially the file associative branch only contained this said filemap information, and was fairly ridged. After a while however, the desire to add in both practically infinite file names and bind related files such as the .INIs, etc into one rapidly accessable place resulted in the revision of the associative design to also hold several binary and string variables.
filemap
mac
metaphor
It was after a somewhat argumentative, though construction, discussion on IRC #coders 2/10/95 with OS2MAN that I went on a search for more information on other file systems, especially the HPFS which OS/2 taunts....
os/2
cts2p
File and Object Names
There is some confusion related to the proper usage of file and object names. In general you can use any character at all in either ASCII (8-bit) or UNICODE (16-bit), however there a few special characters that can not be part of a name, but are considered control characters. They are: NULL, ";", ":", "/" and NEWLINE.
NULL is character code 0. It represents the end of a character stream.
A colon, ":", represents the division between either a title and a subtitle or between an object name and it's instance name. For example this is a title/subtitle name "STAR WARS:A New Hope". And this is a class/instance name "METAPHOR:The Natural Landscape".
A semi-colon ";" usually represents the series number. For instance "X-men:Trading cards;7" might represent the 7th in the series of X-Men trading card pictures. It is also used for extra attributes such as revision or fragmentation numbers, in that order.
The right slash "/" prefixed to a name section indicates a folder, thus it's also called a folder mark. For example "public/readme_please", pointer to the readme_please document in the folder public. Using a folder mark without a name before it indicates that you wish to start with the NULL or ROOT folder.
The Title name is the same as the Object name. The Subtitle is the same as the instance name.
A filename is the combined title:subtitle. An objectname is the combined object:instance.
UNIFORM RESOURCE LOCATOR
To make interfacing with other filesystems easier across inter/intranets Grail has adopted a naming system that is compatible with UNIX and the URL (Uniform Resource Location) syntax. To access local files you can use the prefix "local:","file:" or no prefix at all. To access non-local files you must use the prefix "nonlocal:" or "ftp:". Grail also recognized "user:" as a synonym of the user's base folder.
The Anatomy of the File
BY | Lewis Sellers lsellers@usit.net
The Grail file is a composition of three parts: The Binding, The Associative Branch, and the Data Branch. Depending on your policy settings, a file containing 1-byte of data could take up only 200 odd bytes or so, including everything. Or, if speed is of the utmost concern, you can, on a file by file basis, have the file take up a little more overhead but have much better response by isolating each section on sector boundaries.BINDINGFile Structure Illustration___________________ | BINDING | | | ------ |___________________| | | | | ASSOCIATIVE BRANCH | | _ ___________________ | | | | FILEMAP |<- | | | | | | |___________________| | | ___________________ | | | ASSOCIATIVES | | | | System | | | | Application | | | | User 1 | | | | User 2 | | | | . | | | | . | | | | . | | | | User n | | | | | | |_ |___________________| | | ___________________ | | DATA BRANCH |<------ | | |___________________|The binding is a static structure that exists only in a folder (a folder being a list of bindings) and that describes the file. In other systems, it would be called a directory entry. Details of the binding structure are provided later in the document.
FILEMAP
A filemap stores information describing how the file maps onto the device.
ASSOCIATIVES
The associatives are sections of the associative branch not including the filemap, which are the system associatives, the application associatives and potentionally several user associatives.
DATA
The data branch very simply contains the data of the file.
BY | Lewis Sellers lsellers@usit.net
Grail is not as reliant upon the "everything is a file" concept as UNIX is, but it has a definite hierarchy.What is filespace and what does it look like?
File-space is the term used to designate any place where a file can be stored, whether it be on a hard-drive, a floppy, a CD-ROM, or those again remotely. The collective term to refer to all such devices except modems and network cards are file-devices. This includes the aforementioned floppies, hard-drives, CD_ROMs and tape-units.
File-space in Grail is hierarchical in nature, starting with the ROOT, the sub-root, folders and then files.There are in general about ten (10) file types for Grail, which are: ROOT, DRAWER, VIRTUAL DRAWER, FOLDER, ARCHIVE, SYSTEM, OBJECT, DATA, TEXT, and LINK.
The ROOT is the very top-most structure on all of your filespace devices. All of the essential files that GRAIL requires to functions are stored here, including the core itself. Within the root filespace there are folders containing secured information about multiple users, filespace device objects and, rather importantly, the sub and virtual roots.
[ed: redo]
ROOT FILESPACE
EXAMPLE FILE-SPACE MAP ROOT | |------------------|------------------------| DRAWER DRAWER DRAWER | | | FOLDER FOLDER FOLDER FOLDER FOLDER FOLDER LINK FOLDER LINK FOLDER---FOLDER---FOLDER FOLDER ROOT |
|- Core |- Session State File |- Virtual Memory Swap File |
|--| drawers |
|--| virtual drawers |
|- /Help/ | All Grail help files reside here. |
|__/User/ |- NULL/ |- Default/ |- Supervisor/ DRAWER
A drawer is a special folder which contains additional information allowing it to address other drives or drive partitions.
VIRTUAL DRAWER
Same as a drawer, but references folders on remote computer systems.
SPECIAL USER FOLDERS
There are a few special folders that exist in the root space that are not drawers or virtual drawers. These are normal folders, but with predefined special purposes.
One of these is the User BASE Folder, which starts at "/User/". Each user account has it's defined base folder which resides within these folder. Within this folder are all the subfolders holding specific information pertaining to them that they can change. All files within the base folder however can not be changed except by the Supervisor account.
The base folder for supervisor mode is always /User/Supervisor/. There are also always /User/NULL/ and /User/Default/.
Folders that you will find in a Base Folder are: "Command Interface", "Redirection", and "Authorization". The Command Interface defines all the folder links used by the command interface of your Metaphor. Authorization holds your passwords and voice verification, etc. Redirection is a little similar to the Command Interface, in that it contains links almost exclusively.
Temporary Folder
Mail Folder
Fax Folder
Hermetic Folder
Mail Folder
News Folder (USENET)
Script Folder
Files that you will find are "User Profile".
USER://
You can use the special reference USER:// to refer to a users BASE folder.
HOW DO (COMMERCIAL) APPLICATIONS FIT INTO THE FILESPACE HIERARCHY?
Excepting of course the special circumstances where you are talking about upgrades or filesystem device drivers, all sets of objects and data files grouped as a distinct applications typically have their own folders and sets of folders. New applications should not ever mingle with others (unless they are upgrades) nor ever place themselves into the ROOT filespace.
Context Overview
BY | Lewis Sellers lsellers@usit.net
SUPERVISOR USER RESOURCE FILE
[min: For a very very long time this was an enormous structure known as the PNF Policy/Navigation File, but there were huge revisions for 1.0 and the structures were broken up.]
This file resides in root space. It contains a list of all the user accounts under Grail. All accounts are situated in below the /user/ folder. See URF for more information.
As you can tell, HTML has had some impact on the design of the entire file system. Originally I came up with the metaphor concept, and then created a file system that would easily serve it before I ever had full internet access. Rather to my surprise, HTML and my Metaphor/FS had much in common in the way they viewed the world. I have tried to further change the Metaphor/FS so as to be extremely friendly to concepts of abstract visualization inherent therein.
The policy information in the file is read into memory, and all changes are echoed back to the file.
The SURF resides only in the top-level of ROOT space, and always has the same name "Supervisor User Resource File". Only the Supervisor (ie, parent) has the right to directly change anything in root space. Other users can not even directly look into the root space and see what files exist there.
A File Systems Overview
BY | Lewis Sellers lsellers@usit.net
User BASE FolderFor security and ease of use within family and educational environments, Grail is capable of having several distinct configurations for various persons. The hardware setups all remain the same, but each user can have separate core-up parameters and folders available to them.
The way this works is that when Grail starts, after having gone through the Supervisor User Resource File, it looks through the users in the /Users/ folders to see if there is more than one of them there. If not everything continues as normal. Otherwise it switches to what is called the NULL User. That is, it loads it's user data partially from an internal structure in the core and this users Task Automatic Load is the Metaphor Program __USER_VERIFICATION which resides in root space (naturally). The supervisor can alias in different custom object for this, but the default one that comes with Grail very simply presents a conservative but pastel screen requesting your user name, and whatever means of access authorization you require. Usually this is a password.
The folder is an example list of the folders in the /Users/ folders.
/User/NULL//User/Supervisor/
/User/Default/
/User/Lewis Sellers/
/User/Susy/
/User/Sissy/
/User/Michelle Sellers/
________________________________________________________________________________ In each users base folder, there is a file called the "User Account Resource File". They can only be edited by an application while you are running as a Supervisor (/User/Supervisor/).User Account Resource File (UARF)
_______________________________________________________________________________
USER TYPEIllustration User .----------------------- | User type | |_______________________| Binary Items .----------------------- | DOB | | POB | | Time | | Location | |_______________________| Policy Items .----------------------- | Policies | |_______________________| Text Items .----------------------- | Object Automatic load | | Task Automatic load | | Script | |_______________________|There are three types of users as defined by Grail: The Supervisor, The Normal User, and the Child User.
The supervisor user account is not limited in any fashion, and uses the general global default files, etc. Only someone with supervisor status can change, delete or create other user accounts. Also, only they have direct access to the bulk of ROOT space. All others are always restricted to using DRAWER space and their folders. There is only one Supervisor account. A log is kept in ROOT space of failed attempts to gain supervisor status. This user type is sometimes known as "parental control".
The normal user account, the one most often used, is known technically as an Explicitly_Restrict account. It is for the family, friends, co-workers, and even the primary user. It has also the same resources as the Supervisor, except that access to ROOT space is denied them, and the Supervisor can explicitly restrict folders from them, or limit free space in a drawer or folder. Each account has it's own separate settings, so you can customize it without affected others on the machine.
A child account is technically called a Restrict_Unless_Explict or Pariah* account. This is for children or running demos in stores, etc. By default they are denied access to everything. The supervisor must explicitly declare what folders they can use and how much space they get. As said, in the real world, this is typically the status given to family and neighborhood kids so they can play a few games or educational programs without destroying all your work or viewing R-rated or better materials. Also good for Grail-based BBSes.
As an aside, there is also a NULL User Account. It is denied everything and automatically runs a function that asks which user you wish to log in as and its passwords. The supervisor can change this and thus customize the authorization program.
And finally, there is a Default User Account (/User/Default/). You are forbidden from running as user Default, but the Supervisor and setup a User Account Resource File for them. Their Binary Items, Text Items and Polices are used before the user you log in as. This is just a handy thing to be able to do.
*For Gary, The Orion Overlord. R.I.P.. :-)
BINARY ITEMS
Date of Birth
UTCAD_TIMECODE DOB
Point of Birth
ULCLL_LOCATIONCODE POB
Time
UTCAD_TIMECODE Time
Location
ULCLL_LOCATIONCODE Location
TEXT ITEMS
OBJECT AUTOMATIC LOAD
This section is an asciiz13 listing of all the objects that Grail should load in automatically after core-up. This operation occurs directly before the task autoload operation. Each object is verified and loaded in the order it is listed in the section. If any object can not be loaded a null object (see __OBJECT.NULL) is created in its place.
This is a list of all the objects that are originally listed in the object autoload:
GRAPHICS
3DGRAPHICS
GMIDI
DIGITALAUDIO
FMAUDIO
VISUAL
MONITOR
CURSOR
TEXT
OLEFACTORY
KEYBOARD
JOYSTICK
MOUSE
LIGHTPEN
TABLETPEN
VR_ABSTRACT
VR_HUMAN
TASK AUTOMATIC LOAD
METAPHOR
POLICIES
You can change the operating policy of all the CORE functions through the User Account Resource File.
[ed: reformat these!]
OBJECT.Function Auto-Null
If this is flagged on, then any request for an object that fails causes a NULL object to be created automatically and a 2 to be returned.
SYSTEM.Optimization switch
This sets the global switch CORE_OPTIMIZATIONS. If it is 0, then the operating system should take advantage of every performance trick it knows of... mainly things related with aligning data. This setting is usually more memory hungry. For less powerful machines, you may need to drop this down to 1. By default it is 0. This is usually set by a Metaphor program.
SYSTEM.Optimization_Get
Returns the SYSTEM.Optimization.
SYSTEM.System_Class
"Personal Computer"
"Workstation"
SYSTEM.Processor_Name
"intel 486sx""
SYSTEM.Platform_Name
Allocates memory and copies a string into it. The handle is passed back. Currently recognized platforms are:
"IBM-derived PC"
"APPLE-derived Macintosh"
OBJECT.Language langcode
This function tells the operating system which languages the personnel prefers to use. An application can then query the OS itself instead thus not having to pester the end-personnel to repeatedly re-answer a simple question. Also, the driver functions use the policy language to determine which set of text info to load in for use by the personnel.
You can have any number of languages listed that you want. Generally you create a list of the languages that you can read in the order of your preference or proficiency. The first language in the list is assumed to be your primary or original language.
The langcode itself is a 32-bit number that is directly computed from the ASCII letter codes internationally assigned to each language. English for instance is eng. Thus the langcode sequence is 97 + 110 +103 + 0, and the langcode itself is 6778465. (Ie, 97 + 110*256 + 103 *65536 + 0*16777216)
Below is a sample list with a couple langcodes resolved.
Language_Get
CODE LANGUAGE LANGCODE ara Arabic chr Cherokee chi Chinese dan Danish egy Egyptian eng English 6778465 esk Eskimo esp Esperanto fin Finnish 7235942 fre French gae Gaelic (Scots) ger German gre Greek haw Hawaiian heb Hebrew iri Irish ita Italian jpn Japanese 7237738 lat Latin rus Russian swe Swedish tib Tibetan apa Apache Gets the current language preference (langcode).
OBJECT.Filter debug, info, parameter
Settings the filtering aspects for loading objects into active memory. By setting any of these you cause it to be stripped from the object at load and all pointers directed to a NULL. If you're having problems with running out of memory for a program, filter everything.
OBJECT.Filter_Get
Returns the debug (EAX), info (EDX) and parameter (ECX) filter settings.
__VMMU.Size swap_size
Defines the size of the virtual memory common swap file. This value only takes effect after the next __VMMU.Create. Though it does accept any value, currently the size is rounded up to the nearest megabyte.
__VMMU.Size_Get
Returns the size of the swap file.
Filesystem_Names preference
Defines whether you prefer to use ASCII or UNICODE for text. The default right now is ASCII, but it will be changed to UNICODE just as soon as we familiarize ourselves intimately with UNICODE.
__FS.Defrag switch
This policy setting controls how Grail reacts if you try to create file on a sub-root that has insuffficient filespace. A switch of 0 means simply report it as an error. A switch of 1 means do a __FS.Defrag first, then check again.
__FS.Overwrite
overwrite 0=no 1=if exists? 2=only if newer
__FS.CreateFolder
create folders if need be?
__FS.
0=kill pointer 1=zero data 2=security delete
__FS.DeleteFolder
Allow deletion of folder (and files within) only:
0 when empty
1 if no other folders are contained within
2 just delete them
__FS.Target
0 USE CURRENT
1 use target
________________________________________________________________________________ Access is granted or restricted in Grail either on a folder-by-folder basis or on a folder an child subfolders inclusive basis.Access
_______________________________________________________________________________
Grant_Folder
Access is granted to the folder specified.
Restrict_Folder
Explicitly declares a folder that is not accessable by a personnel.
Grant_File
Restrict_File
Grant_Folder_Specifically
Restrict_Folder_Specifically
Grant_FreeSpace
This is only used with Restrict_Unless_Explict, and limits the pool of....
________________________________________________________________________________ All user authorization programs must reside below /User/Authorization/. All authorizing files (passwords, voice IDs) should reside in the users BASE folder in the Authorization/ subfolder.Security Authorization
_______________________________________________________________________________
/User/NULL/
/User/Authorization/
All plaintext passwords should reside in the file "Plaintext Password". All encrypted passwords should reside in "UNIX Encrypted Password".
If you wish to use comparison voice-authentification to gain access to a user account, the file name should be "Voice Comparision" and the filetype should be Audio/AU.
Group
User
age
_____________________________________________________________________________ P O L I C Y F U N C T I O N S
_____________________________________________________________________________
Policy functions sets switches and flags that determine some global aspects of the functionality of the entire operating system. Typically these changes are shadowed and/or saved into the Policy / Navigation File (PNF) which resides in the root of the boot device.
HARDWARE
Hardware policy entries are unique on the system. That is, they are the same for every profile, account or user that uses the computer. Only the supervisor can change them. They are grouped by object class and instance. Each can use a set of unicode/ascii text parameters to set different aspects of a device object.
__POLICY.HARDWARE_Add ptr_OBJECT.name, ptr_instance_name, ptr_item_line
Only while in the supervisor profile mode.
__POLICY.HARDWARE_Get ptr_OBJECT.name, ptr_instance_name, ptr_item_prefix
Only while in the supervisor profile mode.
__POLICY.HARDWARE_Delete ptr_OBJECT.name, ptr_instance_name, ptr_item_prefix
Only in the supervisor profile mode.
__POLICY.HARDWARE_Purge
Only in the supervisor profile mode. Checks to see if the drivers specified actually exist, and deletes all nonsensical entries.
RESOURCES
Defines how various resource are to be used.
__POLICY.RESOURCES_Add ptr_group_name, ptr_grouptype_name, ptr_item_line
__POLICY.RESOURCES_Get ptr_group_name, ptr_grouptype_name, ptr_item_prefix
__POLICY.RESOURCES_Delete ptr_group_name, ptr_grouptype_name, ptr_item_prefix
__POLICY.RESOURCES_Purge ptr_group_name
Removes all entries for the specified group.
OBJECT
Qualifies parameters or sets defaults used by objects.
__POLICY.OBJECT.Add ptr_class_name, ptr_instance_name, ptr_function_name, flag
__POLICY.OBJECT.Get ptr_class_name, ptr_instance_name, ptr_function_name, flag
__POLICY.OBJECT.Delete ptr_class_name, ptr_instance_name, ptr_function_name, flag
__POLICY.OBJECT.Purge ptr_class_name, ptr_instance_name
PROFILE
Manages user profiles.
__POLICY.USER_Create ptr_form
STRUCT
db usertype
db ?
dw age
ptr ptr_name
ptr ...
ptr ptr_access
dptr access_length
ptr ptr_authorization
dptr authorization_length
STRUCT END
usertype=
supervisor
explictly_restrict
restrict_unless_explict
age=
1-n
0 not-relevant
-1 child (innocent)
-2 youth
-3 young adult (provisionally adult)
-4 adult
__POLICY.USER_Revise
?
__POLICY.USER_Modify
Modifies the current profile.
__POLICY.USER_Delete
For security reasons you can only delete your own current profile. When this happens you are automatically thrust back by the core to a NULL Profile just as if you have just got core-up. You can not delete the supervisor profile.
_____________________________________________________________________________ __SESSION.SaveS E S S I O N
_____________________________________________________________________________
Does a complete save of every single thing in the __MMU list after it saves the __MMU list itself. The file structure is very simple. The file is always called 'Grail_CoreImage' and it resides in the root space of the primary device along with the Policy / Navigation File. It begins with:
STRUCT d.32 build ;the GRAIL core build d.32 timedate ;a time date stamp STRUCT END Then follows a dump of several internal pointers, then a dump of the complete __MMU list, followed, in sequence of their appearance in the list, a memory dump of each of the memory blocks.
This function is used by some Metaphors for quick resume ability. Others sometimes use it for emergency session resumes, by invoking it every 15 or so minutes.
This function is also known as a CORE IMAGE SAVE.
__SESSION.Restore
The inverse function of COREIMAGE save. It overwrites the current session in favor of the previous one assuming the build versions are identical. Do not attempt to write your own session save routines. Internal changes will almost be promised to result in failure.
This function is also known as a CORE IMAGE RESTORE.
_____________________________________________________________________________ Data and associative branches can have automatic on-disk compression if so flagged. They are, it might be mentioned, independent of each other. There is an ASCII associative to name the compression type, but that can almost be ignored and only the flag used since only one compression type is incorporated directly into the operating system. As of this writing it's a fast variant of huffman.COMPRESSION
_____________________________________________________________________________
You must explicitly compress a file on a device. When reading it the data is automatically decompressed for you. It is only permanently decompressed by writing to the file or explicitly issuing a command to decompress it.
As you know, compression and decompression of files is built into and the Grail Operating System. By default you would use the core-compiled generic-compression and generic-decompression routines which are accessed via the __COMPRESS and __DECOMPRESS objects.
It should be made clear however, if you missed it when looking through the File System document, that Grail, true to it's nature, is not shackled to any single de/compression routine. You are guaranteed the generics will always be there, but third-parties can create and distribute any other new software they like.
Say for instance Stacker, the premiere company for de/compression software, decides they'd like to help the Grail consumer out by providing the absolute best technology available. They could create a free-ware __DECOMPRESS object instance to handle any file compressed with their technology. They would then also make a shareware and/or commercial __COMPRESS object instance. While you'd need to buy their product to compress using their technology, anyone with the free decompression object could later on use any files so compressed.
What's the point? Grail simply provides the framework and workable objects for inclusion with it. The compression/decompression that comes with Grail is good, but there is no way for it to beat that of Stacker and the techs. Even the juggernaut Microsoft apparently though so at one time.
I whole-heartedly encourage for-profiet companies to develop plug-in technology to enhance grail, especially when some of their basic functionally can be had by the end-consumer for free or at a negligible cost.
__COMPRESS.FileEstimate ptr_refID
Returns the estimate of compression results as well as the file's original size. For example:
(FileSize,CompressedSize) = __COMPRESS.FileEstimate "test_file" __COMPRESS.File ptr_refID
Compresses a file with the current policies preferred compressor. It then flags the file as having a compression policy and as being compressed, and adds the instance name of the compressor to it's pre-associative branch.
__DECOMPRESS.File ptr_refID
This permanently decompresses a file and sets it's flags to non-compression. You can of course a read compressed file without doing this since all accesses to the file will automatically decompress portions of it to memory. Note that __DECOMPRESS and __COMPRESS are separate object classes for very specific commercial reasons (ie, a company can give a decompressor away for free but charge for the compressor).
_____________________________________________________________________________ The encryption of an object and the encryption of a file are separate issues. __ENCRYPT and __DECRYPT are separate object classes.E N C R Y P T I O N
_____________________________________________________________________________
__ENCRYPT.Object ptr_refID, instance, encryption_stream_handle
Uses the current policy encryption object class to encryption an file that is an object
__DECRYPT.Object ptr_object, decyption_stream_handle
This decrypts the code and data section of an object that is already loaded into memory. This function is not meant to be called by other than the operating system. It is called after an object is loaded but before the creation function is executed.
__ENCRYPT.File ptr_filename, encryption_stream_handle
Encrypts a file.
__DECRYPT.File ptr_filename, decryption_stream_handle
Decrypts a file.
EXAMPLE USER RESOURCE FILES
"And fools shine on..." brother caine Resources
[Control] Root= Core= Session= Swap= [Image] Core= Application= [Object]
Device=
Platform=
Script=
[Plaintext]
ASCII/TXT= ROOT/Text_Viewers/VPRO
UNICODE/TXT= ROOT/Text_Viewers/UNIVPRO
Document/GRAY= ROOT/Text_Viewers/GrayReader
Document/RTF= ROOT/Text_Viewers/Word7_Reader
Document/HTML= ROOT/Internet/Netscape/Netscape
[Data]
Image/JPEG= ROOT/Image_Viewers/ACDSEE/ACDSEE15
Image/PNG= ROOT/Image_Viewers/ACDSEE/ACDSEE15
Image/GIF= ROOT/Image_Viewers/ACDSEE/ACDSEE15
Image/TGA= ROOT/Image_Viewers/ACDSEE/ACDSEE15
Image/PCX= ROOT/Image_Viewers/ACDSEE/ACDSEE15
Image/TIFF= ROOT/Image_Viewers/ACDSEE/ACDSEE15
Image/Native= ROOT/Image_Viewers/ACDSEE/ACDSEE15
Image/MPEG1= ROOT/Movie_Players/MPEG1/MPEG1
Image/MPEG2= ROOT/Movie_Players/MPEG2/MPEG2
Image/QuickTime= ROOT/Movie_Players/Apple_QuickTime/QuickTime_Player
Image/FLICK= ROOT/Movie_Players/Trilobyte_FLICK_Player/FLICK_PLAYER
Document/WORD= ROOT/Text_Viewers/Word7_Reader
[Alias]
__USER_AUTHORIZATION= ROOT/Authorizations/Babalyon5_Authorization
[Object Autoload]
GRAPHICS
3DGRAPHICS
GMIDI
DIGITALAUDIO
FMAUDIO
VISUAL
MONITOR
CURSOR
TEXT
OLEFACTORY
KEYBOARD
JOYSTICK
MOUSE
LIGHTPEN
TABLETPEN
VR_ABSTRACT
VR_HUMAN
[Task Autoload]
METAPHOR
[Type]
UserType= Supervisor
Maturity=Adult ;28yrs
[Authorization]
Name= Lewis Sellers
Identity= herekittykitty
Authorization= ROOT/Authorizations/Lewis_Sellers
Verification= ROOT/Authorization_Verifications/VoiceVerify
[Alias]
Metaphor
ROOT/Metaphors/Natural_Landscape
[Task Autoload]
METAPHOR
******
;Lewis_Sellers
[Type]
PersonnelType= Supervisor
Maturity=Adult ;28yrs
[Authorization]
Name= Lewis Sellers
Identity= herekittykitty
Authorization= ROOT/Authorizations/Lewis_Sellers
Verification= ROOT/Authorization_Verifications/VoiceVerify
[Alias]
Metaphor
ROOT/Metaphors/Natural_Landscape
[Task Autoload]
METAPHOR
****************
;Susy
[Type]
PersonnelType= Restrict_Unless_Explict
Maturity=byDOB
DOB=13/7/91 ;age 4
[Authorization]
Name= Susy Q.
Identity= SusyAuthorization= Sissy
Verification= /Authorization_Verification/PasswordCompare
[Access]
Grant_Folder= /Drive3/Tetris
Grant_Folder= /Drive3/DOOM2
Grant_Folder= /Drive3/Pooky's_PlayHouse
Grant_FreeSpace= 10MB
[Task Autoload]
/Metaphors/Cat_Land
*****************
;Michelle_Sellers
[Type]
PersonnelType= Explicity_Restrict
Maturity=Adult ;Age 23
[Authorization]
Name= Michelle Sellers
Identity=Missy
Authorization= /Authorizations/Michelle_Sellers
Verification= /Authorization_Verification/PasswordVerify
[Access]
Restrict_Folder= /Drive3/Borland_C++
Restrict_Folder= /Drive3/Watcom
Restrict_Folder= /Drive3/Grail_R&D
[Task Autoload]
/Metaphors/Natural_Landspace
_____________________________________________________________________________ This is extremely important. Listen up. A binding is the essential structure which binds the data and associative branches together. The bulk of the data in folders is simply a long list of bindings. This is true of the root, drawer and virtual roots as well.B I N D I N G
_____________________________________________________________________________
The binding consists of a refID (32-bit dword on Intel processors), a series of 8-bit flag groups, BRANCH offsets/lengths and timedate data. There is also a "BIND" at the beginning of each for verification. A file is considered erased if it's "BIND" key-word is missing. By convention, you permanently erase a file by nullifying out those four bytes. Also, you can change it to "bind" (lowercase) which technically stills means the file is erased, but this allows routines later on to be run that might be able to reconstruct your file.
This is the file binding structure in GA (Grail Assembler) notation:
FILESPACE BITWIDTHCLASS STRUCT FF_BINDINGascii <BIND>
d.8 filespace_bitwidth ;bitwidth of file pointers in 2^(n-1), usually 6
dbit.8 format
1 series ;series or vol/no?
dbit end
dbit.8 type
4 primary
4 sub
dbit end
dbit.8
1 token
1 temporal
2 security
1 supervisor
1 application
dbit end
fsdptr refID ;usually 32-bits
dbit.8 log
1 accesses
1 error
1 history
dbit end
dbit.8 access
1 read_only
1 write_only
1 archived
1 copyright ;permit the file to be copied?
dbit end
dbit.8 change
1 copy ;0=original 1=copy
1 upload ;1=has been transferred "up"
1 download ;1=has been downloaded but not yet opened
dbit end
dbit.8 policy
1 use_compression ;shall we do a decompress when accessing?
1 encrypt ;access blocked by encryption?
1 contiguous ;streaming?
1 static
1 emulation
1 mirroring
1 caching
1 speed ;size/speed
dbit end
dbit.8 policy_check ;inverse check
dbit end
dbit.8 status
1 compressed? ;shall we do a decompress when accessing?
1 encrypted? ;access blocked by encryption?
1 complete? ;file only a partial? (error or downloading?)
1 corrupt? ;DO NOT CHANGE!! File has problems.
1 viral?1 contiguous?
dbit end
dbit.8 status_check ;inverse check
dbit end
STRUCT data
dptr length
dptr space
dptr start
STRUCT END
STRUCT associative
fsdptr length
fsdptr space
fsdptr start STRUCT END STRUCT count d.32 accesses d.32 upload d.32 download END STRUCT series d.32 last d.32 no STRUCT END STRUCT revision d.32 limit d.32 no STRUCT END STRUCT fragment d.32 fragments d.32 no STRUCT END UTCAD_Timedate create ;created UTCAD_Timedate modify ;last modified UTCAD_Timedate access ;last accessed UTCAD_Timedate event d.32 sort d.32 Security_ID d.32 mirror_no d.8 lock STRUCT END
The filespace value indicates the size of all offsets used in the BINDING and ASSOCIATIVE BRANCH. Normally this is 3, which indicates a 64-bit or 18,446,744,100,000,000,000 (or 18 pentillion) byte file space. For smaller devices, such as floppies and IOMega ZIP drives, you'd use the 2 type which is a 32-bit or 4 gigabyte filespace. The FILESPACE_WIDTH is the bitwidth of the filespace expected by the file starting at 8-bits and using a 2^nth power to compute all that comes afterward. There is some expandibility for the future as you can see from the table below:
Width Actual Bitsize 0 8 1 16 2 32 3 64 <-- default 4 128 5 256 This is used to verify that the file is using the same bitwidth as the current filesystem. You can, I might mention, have one device using 32-bit filespace and one using 64-bit. As a file is moved, the file structure is appropriately modified.
FORMAT.SERIES
If the series flag is 0, then the series data is one number. If it is 1, then data is two equal bitwidth components.
TYPE.PRIMARY
There are 10 binding types.
0 NULL 1 root (supervisor area) 2 file drawer 3 folder 4 archive folder 5 file 6 system file 7 object file 8 binding link 9 virtual file drawer 10 package TYPE.SUBSystem File
1 Core 2 Saved Session Image (rapid resume) 3 Global Swap File 4 Supervisor User Resource File 5 User Account Resource File Object File
There are four types of objects:
0 Device-dependant Object (device object) 1 Platform-dependant Object (object) 2 All-platform Script (the only one with a non-binary data branch) (script) TOKEN
This allows you to create a simple stand-in token file for a file that is not currently available locally. Refer to the section on tokens for more information.
A token file is one in which only the binding and part of the associative branch are valid. This type of file is a place-keeper for non-local files that may exist on LAN (Local Area Network) or WANs (Wide Area Networks) but have not yet been transferred. Suppose you log into ftp.cdrom.com and do a directory of /pub. Under Grail you would have created a virtual root containing /ftp.cdrom.com/pub/ which would be filled with tokens of all the files shown by your dir or ls command.
Each binding has a bit field called token:
0 non-token
1 empty token
A token file uses the data branch to store a simple structure containing the date at which the token was created and a formal URL where the complete file may be found.
CLASS STRUCT
UTCAD_Timedate Token
STRUCT END
URL: ;label for NULL-string
TEMPORAL
0 permanent
1 temporal
A temporal file is one that is tagged with a life-expectancy. When this peroid is at an end, the file is automatically deleted. The peroid of expiration may be of three flavours:
Demand Only
You may explicitly purge a specific temporial file, all temporials from a folder or all temporials globally.
Low Resource
A forced Demand Only.
Expiration Date
A UTCAD timedate either expressly stated or derived from a life-expectancy. The GUTC resides in the binding event.
SECURITY
SUPERVISOR
Any file flagged as supervisor is only directly accessable via the Supervisor Account or internally by the core.
APPLICATION HEAD
refID
The 32-bit refID is the actual value the Grail FS uses internally for handling/scanning files. As there is the possibility for over 4 BILLION UNIQUE files per subdirectory in Grail (coupled with it's lower need for seperate files due to the associative branch and it's refID latency policy [give up old used refID's only during a PURGE or when 4gb-1 refIDs have been used]) the possibility of confusion locally is almost nonexistant. The file name, etc are looked up only when asked for thusly.
Using 32-bit numbers to reference each file (instead of long names) also cuts memory overhead.
A refID sequence consisting solely of a single NULL points to the ROOT. If the sequence has one element then it points either to a sub-root, a system folder or a system file. System files and system folders always have the same refID, so yes, this means you can always directly reference a ROOT system file without having to do a name-string lookup.
refID bitwidth depSTRUCT END on the filespace pointer size, thus while usually 32-bits, you may also encounter 64-bit refIDs on some systems.
It didn't start out this way, but in an order to have extremely long filenames I moved them to the associative branch. In order to reference a file I created the ideal of using unique 32-bit reference ids for files (or folders). You would reference a file using a string of these 32-bit refIDs denoting the folders, subfolders and then the file you were talking about. It was about this time a few months ago that I got my first true internet account... and lo and behold I encounter URLs and the DNS! Suddenly everything meshed and became very clear. So yes, Grail in effect now uses a DNS/URL similar file naming system. All files use a string of refIDs, which you can lookup through folder and filenames through the __FS.FileLookup function much like a DNS lookup.
A DNS is composed of 4 8-bit numbers, though, I might mention and does not reference actual files, while each element in the Grail FS is 32-bits currently. The bitwidth of the refID is usually the same as the architecture of the machine it is running on, I might mention. You can set the default to other though. For example, most Intels currently have 32-bit pointers and a 32-bit filesystem. With the bigger hard drives and DVDs coming out though, you might have 64-bit refIDs.
Grail's FS and core are designed with the idea in mind that at some point it may run on 32-bit, 64-bit, 128-bit, 256-bit, etc systems or devices.
LOG
If any of the loggging bits is set, then each access of a file will cause information to be added to it's associative file under the approriate...
AccessesErrors
History
EMULATION
Grail provides some limited ability to interface with other older filesystems such as DOS FAT. This is mainly intended for accessing images and data from soon-to-be-old pre-DVD CD-ROMs (~500 to 700kb), etc. To access these files you must first have GRAIL automagically create bindings for them that link to the old files. These new bindings have new associative branches but point to the same old data file as the data branch. At this point, you should notice that neither the binding, associative branch or data branch must exist on the same physical disk....
__FS.EMULATION_
CACHING
If no, then the policy is that no disk cache is required for performance reasons. Probably the file will be read completely into memory.
SPEED
Favour Speed over Size? Not currenty used.
USE_COMPRESSION
Is the file flagged that it should be compressed for best performance? When modifying files, they are typically automatically uncompressed so that the constant decompression/uncompression routines don't bring the system to a crawl. Occasionally it's good to have a program search through your files compressing anything that should be. Simple housekeeping.
ENCRYPTED
This file is encrypted.
COMPLETE
If not set, then file is assumed to be from an aborted download, or is CURRENTLY being downloaded.
READ_ONLY
Grail will not allow the (data branch of the) file to be written to or changed.
ARCHIVED
Is this file part of an archive? thus possibly compressed and encrypted?
VIRAL
Flag this if suspect.
CORRUPT
A very stern read-only flag for disk managers.
1 compressed? ;shall we do a decompress when accessing? 1 encrypted? ;access blocked by encryption? 1 complete? ;file only a partial? (error or downloading?) 1 corrupt? ;DO NOT CHANGE!! File has problems. 1 viral? 1 contiguous? COMPRESSED?Is the file currently compressed?
CONTIGUOUS?
Is the file now currently contiguous? Slightly different routines are used when non-contiguous and contiguous.
STREAMING?
Essentially, if this flag is set, we are saying that the file is of a nature where it's data is streamed-out at high speed and it should, if at all possible, be physically contiguous.
STATIC
COPYRIGHT
Permit the file to be copied? By default you can copy any file, however, if this is set to 1, then Grail copy functions will not work. This does not mean there are not ways to get at it, just that it is harder.
SECURITY
Privilege is either none/personnel (0) or OS (1). Among other things, any file that is privileged is only accessable if you are the Supervisor.
Should the file be secured from corruption by other programs? If this flag is set, then when the application is started up several things will happen. One of which is that all memory handle's which are owned by the process will be invisible to all but the core. What this means is that if another program is viral, etc it can not uses the MMU functions to look up what memory is being used for what, and since this list is down in SECURE memory behind CPL0 supervisor pages, it can not be gotten at directly. Other things may also be used to protect the program later on.COPY
Is this the original or the copy?
UPLOAD
Has this file been copied remotely?
DOWNLOAD
Has this file been downloaded, but as yet not "used" or looked at?
COUNT.ACCESS
How many times has the file been accessed?
COUNT.UPLOAD
The number of times a copy of a file to a non-local area has been made.
COUNT.DOWNLOAD/REFRESH
The numer of times this file has been retreived from a remote location. This may sound strange at first, but consider it a refresh count. If a file of the same name, etc already exists here, then it will inherent this count +1.
ASSOCIATIVE BRANCH
length
the length of the assc branch
space
the filespace actually reserved for assc
start
the direct linear starting address of the assc
DATA BRANCH
SERIES
You can specify that a file of the same title and subtitle is part of a series if you wish. Thus, for instance, you could have 213 nice PNGs of your favourite cat and use this to specify which they are in the series. Also useful for publications or newsletters. Series can be represented as a single series number or broken up into a volume/number pair. For example: "Discover:THE WORLD OF SCIENCE;16,12".
Whether series is a single or paired number depends on the format.series setting. The vol/no format is 16 bits each part. There are two series variables in a binding. Series.Last denotes the logical last number in the series. Series.no denotes this files number in the series.
This always uses d.32, thus giving a maximum series limit of 4,294,967,295. The series number 0 is special, and is taken to mean the either that the series number should be ignored or that series is not used.
REVISION
You can have multiple backup revisions of a document available. That is, you can specify that a certain document you are working on should allow 10 revisions of itself to exist at a time. Every time you save the document (or autosave it) a new version is created and, if there at more than 10 versions alread in existance, the oldest ones are erased.
There are two revision variables. Revision.limit is the maximum number of revision ofthis file allowed. Revision.no is the revision number of this current file.
The revision number can go up to 4,294,967,295, at which point it loops around. It starts at 1. A revision number of 0 means to ignore revisions.
FRAGMENT
Occasionally your file may be larger than the capacity of the medium you are trying to store it on. This most often happens with the now extremely aged floppy disks still in use.......
SORT
A kindred variable of the refID. Sometimes SORT and refID in a folder are identical.
This is for file sort classes to take advantage of.SECURITY ID
Default of 0. Every user gets one..............
LOCK
If lock is not-zero then the file is currently busy being modifyed by another process. Check again later.
________________________________________________________________________________ Need to translate some old DOS files into GRAIL?FILESYSTEM TRANSLATION
_______________________________________________________________________________
_______________________________________________________________________________
_______________________________________________________________________________ One of the very first things you will do with Grail after booting up it's install program is to create a Grail filesystem. It may reside in it's own partition or be statically embedded in a DOS/WIN95 FS. It all looks the same to Grail.
If you were to install Grail on the system I'm using now, it would automatically generate the following drawers.
/QUANTUM ELS170A 4.40 166317883587 142mb VFAT/
/QUANTUM ELS170A 4.40 166317883587 20mb PERMANENT_FILE/
/MAXTOR 7546AT EA7X3636 C608NAJS 249mb VFAT 1/
/MAXTOR 7546AT EA7X3636 C608NAJS 235mb 2/
/MAXTOR 7546AT EA7X3636 C608NAJS 40mb 3/
/FDC_1.4mb_Floppy/
/CL50A_2X_CDROM/
Obviously, though descriptive, this is more than a little difficult to read. You can of course rename the drawers to anything you feel is more appropriate. Those drawers with the keyword VFAT are formatted with the newer version of DOS FAT that is included with Window 95. Normally, unless you have a device object installed that will emulate through VFAT, you will be denied access into those particular drawers.
My C: drive has a 20mb permanent file that Grail has erected on it. I have done this as an example. Most computer illiterate people will typically have one large, unpartitioned hard drive. To have them either go through the newbie horror of partitioning it or suffer the added burden of buying a second hard drive specifically for Grail is just not realistic.
To that end, a special program (simple real-mode sufficing) will come with Grail that will allow the computer illiterate choose a certain number of megabytes of hard disk space to be given over to Grail in the format of a permanent DOS file. This is essentially the same kind of setup as the Window swap file. The file has a set, filename and attributes such as:
GRAIL.FS 74,200,218 1-13-95 4:22pm The filename is always GRAIL.FS. The filesize is the file space allocated for that drive. The date is always 1-13-95 and the time 4:22pm. The attributes are always read-only and system. It is marked as unmovable, hidden and is a permanent continguous file.
Grail, in effect pretSTRUCT END the file is a sort of varient of an extended DOS partition. Since, for E/IDE devices, Grail works only with the cylinders we give, we simple compute for it where this DOS file is on the hard drive, pass this start and end clyinders on to it, and it continues on as if it were any partition.
__FS.Initialize virgin
The magic function that sweeps the darkness from the face of the Earth. Queries all filesystem device objects for devices and the various partition/drawer areas. It builds a list in memory of these areas. It then looks for Grail ROOT. If it does not find such it proceeds to create ROOT on the first unused drawer area of the first device of the primary filesystem device object. You can of course move ROOT later on, if you desire.
If ROOT already existed, it of course does not recreate it.
Next, the function begins creating the essential folders in ROOT space, including drawer folders to all filespace areas it has encountered, as the example previously had illustrated.
If the virgin variable is non-zero then we're doing a new installation. With new installations, the multi-OS boot program loads into memory all of the essential required files. Then, on core-up, the core writes them back to root space after it is set up. This is one of the reasons that 4MB is the required minimum to run Grail.
In particular these files include the core, the IDE, EIDE ATAPI, the FDC Floppy, The NULL Authentification......
[ed: fix]
__FS.MoveROOT
__FS.Device device
__FS.Information drawer
Retrieves a header:
STRUCT
d.8 bitwidth
dptr no
STRUCT END
and a list of available FS in the following element structures:
STRUCT
dptr available_filespace
dptr grail_filespace
d.8 type ;0=unknown 1=grail 2=known and changable
d.8 op ;0=grail 1=free 2=resizable.....(fix)
STRUCT END
primary filesystem
grail fs DOS 12 DOS 16 DOS 16 extended WIN95 OS/2 HPFS
__FS.Create device, start, end, root, wipe
This creates a Grail filesystem on the specified device within the specified linear addresses. If the root flag is set, then it also created the filesystem structures for the system root space. How do you get these numbers?
Normally the entire area that is affected is wiped to NULL if wipe is flagged, and then the default structures are created.
**********
HOW DOES GRAIL KNOW WHAT FILE-DEVICES I HAVE?
When a new file system is created, either native or DOS/Grail, the primary navigation file is updated to reference the device and all it's sub-roots. Besides the obvious fill data, a few tests are performed and that data stored: access time, transfer rate, -*etc.
THAT'S NICE, BUT DO I NEED DEVICE DRIVERS FOR MY HARD DRIVE?
Probably not. Grail comes with E/IDE and SCSI device objects compiled into it. You can thus use any such device as your BOOT device. As far as __DRIVER functions are concerned these are critical device drivers just like any other, only they'll always be present and probably at fixed places. If you use a drive that is other than this, then, yes, you'll need more drivers.
Oh, yes, floppy drives (FDC) are supported internally as well.
You can elect to have E/IDE and SCSI drivers other than the internal Grail ones loaded in, btw. This is sometimes useful, depending on the drive in question.I'M A NUMBER, NOT A NAME!
**********
________________________________________________________________________________ The root is analogous to the drawer at the top of the drawer that is locked. The root is a fairly simple structure in and of itself. It contains a pointer to a drawer structure where ....R O O T (SUPERVISOR AREA)
_______________________________________________________________________________
RefID is always 0.
STRUCT FF_root ascii <ROOT> d.8 filespace_bitwidth FF_binding binding FF_drawer drawer d.32 refID STRUCT END
__FS.ROOT_Binding
__FS.ROOT_Drawer
________________________________________________________________________________ A file drawer may contain files, folders and folders within folders, etc. Excepting for the root (supervisor area) it is at the top level of all folders. It's data branch describes the filespace device it is associated with and it's partition, if any. In some sense, a drawer is roughly equivalent to a partition. They can only be created or modified by the supervisor personnel.FILE DRAWER
_______________________________________________________________________________
It's best to have one drawer taking up the full space of each drive, but if you've partitioned or DOS formatted the drive already, you may have several others. Descriptions of all drawers reside in the root. Each drawer has it's own name which is local to your system.
The collection of all the drawers on a physical device (such as a hard drive) is called a cabinet.
CLASS STRUCT FSS_drawer
ascii <DRAW>
d.8 filespace_bitwidth
d.8 transfer_type
d.8 root? ;this file drawer the root?
d.8 drawer_no ;partition #?
fdptr refID ;root refID
FSS_binding folder_binding ;folder used by drawer... first folder
fsptr OBJECT.class
fsptr OBJECT.instance
fsdptr cache ;on-board
fsdptr transfer_rate ;bits per sec
fsdptr access_time ;ns
fsdptr files ;total files in file drawer
fsdptr filespace ;total file space of file drawer
fsdptr freespace
dbit.32
1 grail_fs?
1 exist?
1 non-local?
1 boot?
1 root?
1 See_filespace
1 error_state
1 change_line?
1 changed?
1 removable?
1 removed?
1 mirror?
1 readonly?
1 readoverload
1 writeonly?
2 writeoverload
1 write_protected?
1 writable?
dbit end
;db.phase1
;db.phase2
;phase1 = track*head*4/8
;phase2 = track*head*sectors*2/8
STRUCT END
Folder Binding
This is the first, or main, folder in the file drawer. It is the top level. Though it is actually the same as a normal folder structure, consider it as containing all the drawers of the drawer and what ever files are laying on top of it, if that helps you.
OBJECT.Class
Defines the device object to be used. Is a pointer to data at the end of the structure.
OBJECT.Instance
The instance of the device object to be used. A pointer to the name at the end of the structure.
General transfer type
How is data transfered to and from this device? memory sequential block network Cache
Returns the size of the devices cache, if any in, bytes. My Maxtor 524MB hard drive, for instance, would return 64kb.
AccessTime
Returns the sequential (track to track) and end-to-end (ie, first track to last track on a EIDE) access times for the device.
TransferRate
Returns the maximum, and averaged data transfer rates of the device. The maximum value is either obtained by direct query of the device, from the specs encoded in the driver, or through an approved test algorythm built into the function. The function should not take more than 5 seconds per iteration however the values are obtained, just to be polite.
The averaged data transfer rate is actually computed continually in real-time. Logs of the total amount of data transfer for each device are kept in it's root directory, as well as the accumulated wait time for each request from start to end. To get the average data transfer rate all that must be done is for the function to... well, take the average.
This is reset only during a reformat. Example returns for the maximum transfer rate are, say, a 14.4 modem has 1.6kb and a quad-speed CD 600kb.
Files
Returns the total number of all files in the drawer.
FileSpace
Returns the total amount of space on the device.
FreeSpace
Returns the amount of space all the files in the drawer take up.
Native_fs?
Is the drawer native fs?
Exist?
Does the device exist? Should always be 1.
Non-local?
Is the device not local? (across a modem, ISDN or IPX connection)
Boot?
Can you boot from this device?
Root?
Does this device have a root (supervisor area)?
See_filespace?
Can we see the devices filespace heirarchy?
WriteOverload
ReadOverload
Writable?
Can you write data to this medium? Not the same as asking if it is write protected.
Write_protected?
Is the current medium protected from changes to the data?
Removable?
Can the device be removed?
Removed?
Is the device currently empty of media?
Change_line?
Will the device tell you if it's medium has changed (ie, the floppy removed)?
Changed?
Has someone/something removed the medium since last time we checked.
Mirror?
Is the data written to the device mirrored elsewhere to provide for data integrity?
Error_state?
Are we detecting some kind of general error state from the device?
__FS.DRAWER_Information
__FS.DRAWER_SlackSpace
Computes the total amount of space on the device this is not being used but, due to speed optimization techniques, etc can not be used either.
__FS.DRAWER_Purge quality
Zeros out everything not in use in file-space of the current sub-root. This also means that any deleted files in the sub-root will be permanently lost. If the quality parameter is 0 (fast) then this simply writes 0 (NULL) to all the areas once. If it is 1 (secure) then it performs the much slower military-grade wipe.
CONTIGUOUS FILES AND DEFRAGMENTATION
At almost any time you desire, you can of course call up the non-instanced __ . This object class will defragment, compression, verify defects, and many other housekeeping operations to keep your filespace operating at efficiency.
Some of these operations however, will, unless you change the default policies, occur in the background as light threads. Most notable of these is the one that, if nothing else important is happening, go about defragmenting all files marked for contiguous high-speed streaming.
__DEFRAGMENT. refID
__DEFRAGMENT.Start
Initiates a collapse of all empty file-spaces of the current drawer. Returns NULL if fails, otherwise returns....
__DEFRAGMENT.Stop
__DEFRAGMENT.Status
FILESPACE ACQUISITION
There is, in every drawer as part of the drawer structure itself, what is known as the Rapid Filespace Acquisition Structure. This structure varies from device type to device type. There is currently defined the same structure on the IDE, EIDE ATAPI and FDC Floppy drives loosely called the CTS2P (Cylinder/track/sector/2-phase).
The filespace acquisition structures, no matter what device they are for, all are used to rapidly find space on a device when you wish to create a new file or change the size of a current one.
CYLINDER/TRACK PHASE
The first phase contains sets of nybbles, one for each track on the device. They are ordered by cylinder grouping. That is, if you have a drive that has 15 heads then you have 15 tracks per cylinder, and the first 15 tracks in the first phase are logically order top to bottom.
This nybble structure holds four bit-sized variables: AVAILABLE, FULL, UNUSED and DEFECTS. The boolean variable AVAILABLE indicates whether the track is available to GRAIL, or is thus otherwise in use by some other operating system or other purpose. FULL gives immediate response indicating whether the track is completely full already or not. UNUSED states that the track is completely unused is might make a good candidate for long contiguous streamed files. DEFECTS indicates that there is a problem with some sectors in the track, and thus influences the Defect Aversion strategy.
PHASE 1 Track/Cylinder Nybble Illustration_____________________________________________________ | AVAILABLE | FULL | UNUSED | DEFECTS | |_____________|_____________|____________|____________|The First Phase structure is small and used to rapidly scan the entire device filespace for a "general" area that may be suitable for the kind of file we wish to create.For an IBM PC clone 1.4mb FDC Floppy Disc the first phase is 80 bytes in length.
SECTOR PHASE
The second phase gets down to specifics and maps the drive on a sector by sector basis. Each sector has a boolean pair of flags. USED simply indicates whether the sector is used or not. DEFECT indicates the sector is defective. Note that if DEFECT is set, then the USED flag indicates SOFT at 0 and HARD at 1. That is 01b is SOFT DEFECT and 11b is HARD DEFECT.
PHASE 2 Sector Pair Illustration ____________________ | USED | DEFECT | |_________|__________| For the 1.4mb disc, the second phase is 720 bytes in length.
DEFECT MAP
The defect map is incorporated directly into the Acquisition Structure.
DEFECT AVERSION
When trying to acquire filespace, all cylinders/tracks with DEFECTS will be avoided unless there is insufficient filespace to do otherwise. This takes place so as to avoid neighboring sectors in the same tracks which may also have some as yet undiscovered problems.
1.4mb FDC FLOPPY
Cylinders 80 Heads 2 Sectors per Track 18 Bytes per Track 9216 Bytes per Sector 512 Sectors 2880 Buffer ECC bytes GRAIL Phase 1 80 bytes GRAIL Phase 2 720 bytes Click here for Picture
162mb QUANTUM ELS170A
Cylinders 1011 Heads 15 Sectors per Track 22 Bytes per Track 11,264 Bytes per Sector 512 Sectors 333,630 Buffer 32kb ECC bytes 4 GRAIL Phase 1 7,582.5 bytes GRAIL Phase 2 83,487 bytes Click here for Picture
GENERATING THE ACQUISITION STRUCTURE
This structure is generated for quickly finding filespace, and consequentially, for avoiding defective areas. The area that a file occupies is contained in it's filemap, and not here. Every time a file is create or deleted, the acquisition structure is modified properly. Changes may also be made when routines are executed to verify that a device is defect free (and fails in someway).
________________________________________________________________________________ When through a non-local filesystem interface you move through filespace, tokens are created on your systems representing the non-local systems observed in filespace.VIRTUAL DRAWER
_______________________________________________________________________________
Say for instance you visit ftp.cdrom.com (Walnut Creek Software) looking for new and exciting programs to download. Grail will create non-local/ if it has not done so already, then it will created non-local/ftp.cdrom.com/. Typically, since you have come in at the top level it will then create a folder for every subdirectory at their site and a token for every file, such as:
/non-local/ftp.cdrom.com/ ;folder bin/ ;folder pub/ ;folder readme.txt ;token While the concept of recreating non-local filesystems on your on system may sound a bit distressing at first, don't worry about it too much. All recreations occur in the virtual drawer non-local and all true files have only a token of their existence stored unless your software transfers them. This applies no matter what the source or the means of connection. When you are connected to computer systems that may not present a decernable filesystem (such as most current BBSes) then you must declare it's proper name to be used and all files are grouped into a single common folder. Take for instance, The Other World BBS, which ran under Major BBS software. The folder /non-local/The Other World BBS/ would be created and used.
Ideally however, the best BBS software would take advantage of this and use the STMP, FTP and HTTP protocols for their users, allowing easy file transfers.
Asides from being flagged as virtual, the virtual drawer is identical to virtual drawer.
________________________________________________________________________________ The DATA BRANCH of the file called a folder contains a small header and then n binding structures. The header structure contains a count of the bindings in the folder (entries.total), and a count of the number of those that are actually in use (entries.current). There is also a variable (entries.highest) that shows the highest number of entries that have ever been in the folder at one time, and a variable (entries.created) showing the number of files that have been created in the folder. Unless you use a __SORTFOLDER or the binding decays by natural processes, deleted file bindings will remain for an undetermined peroid of time. The structure also contains a full binding that links back to the folders parent folder. CLASS STRUCT FSS_FolderF O L D E R
_______________________________________________________________________________
ascii <FOLD>
d.8 filespace_bitwidth
STRUCT entries
fsdptr created
fsdptr highest
fsdptr total
fsdptr current
FF_binding up
STRUCT END
STRUCT END
;n bindings here...
__FS.MakeFolder ptr_folder_name
This creates the specified folder, returning error status if failure. A NULL means all works. A 1 means folder already exists, a 2 means the operating system is restricted from allowing you to do so. Returns the refID if successful.
__FS.RemoveFolder refIDlist
This removes the specified folder only if it is empty.
__FS.ChangeFolder refIDlist
All logical drives and directories in the grail fs are referenced by unique 32-bit refIDs. All requests to change folders are facilitated by a sequence of refIDs when you want fast response. If you do not know the refID sequence, you must use __FS.LookupFolderNames. The refID sequence is NULL terminated. Returns NULL on a failure, and the depth it obtained otherwise. Grail keeps two refIDpaths for each task. The primary (or source) path and the target path. Use __FS.tpath to change target path.
__FS.TargetFolder refIDlist
policy no/target.
__FS.ExchangePaths
Exchanges the current path with the target path.
__FS.UpFolder
Gets the up binding from the current folder and changes to that folder.
__FS.DownFolder refID
Goes down into a folder in the current folder.
__FS.FolderFiles type
Returns number of files in current folder. Type is created, highest, total and current.
__FS.FolderBindingsLength
Returns the size of all the bindings in the current folder in bytes.
__FS.GetFolderBindings ptr_folderbindings
Copies all the bindings in the current folder to the destination in memory. Returns the filespace bitwidth if sucessful, or NULL if not.
__FS.FolderrefIDsLength
Returns the size of all the refIDs used to reference the current folder, in bytes.
__FS.GetFolderrefIDs ptr_folderrefids
Copies all the refIDs referencing the current folder to the destination in memory.
__FS.LookupFile ptr_filename
Parses the current folder looking for the specified filename. If it is found then the function returns its refIDstring, else a NULL is returned. It also computes the folder depth of the file/foldername and passes it back.
(refID, depth) = _FS_refIDLookup()__FS.LookupPath ptr_foldername
If you give this function the real name of a file path, it will create a NULL terminated dword list of all the refIDs required to move the position (a refIDlist). The refIDlist ..... Returns the depth of a file. ROOT is considered deep 1. Also useful in determining how much memory to allocate for a __FS.refIDpath call.
WHOLE FOLDERS
Need to move about entire folders and subfolders?
FOLDER.Move subfolders, overwrite, purge
Moves a folder, all its files and subfolders and merges them with the target. If subfolders flagged then copies subfolders as well. If overwrite flagged, then files with same filename over overwritten. If purge flagged, then files from the target folder are erased first.
FOLDER.Copy subfolders, overwrite, purge
Copies a folder from the current to the target folder. If subfolders flagged then copies subfolders as well. If overwrite flagged, then files with same filename over overwritten. If purge flagged, then files from the target folder are erased first.
FOLDER.Delete
Similar to __FS.RemoveFolder, this is more pervasive and dangerous, if the __FS.Policy settings allow it.
SORTING FOLDERS
This object class simply reads in a folder and sorts it by the most efficient algorithms possible, given the sort parameters. The target of the sort can be either an element of the binding itself, or a binary/string element of the associative branch. Sorting on the binding of course is faster since all the information is already in memory. The latter requires additional accesses to each files associative branch to extract the string that is to be sorted on.
SORTFOLDER.Binding element, direction
This function sorts on only elements from the binding. The elements are specified by number, the number being equivalent to the order of presentation of the element is the binding structure. Direction is either from lowest to highest (0) or highest to lowest (1).
SORTFOLDER.Associative ptr_name, direction
This function looks up an elements string from each files associative branch, storing them in memory (or the boolean truth of their existence) and then binary sorts on these strings. Direction can be from lowest to highest (1), highest to lowest (2) or a simple sort on their boolean existence.
________________________________________________________________________________ A link is a very simple thing. It's data branch contains two items: a full refIDlist URL and the unicode name of the URL. A link very simply points you to some other place in the filespace hierarchy. The command interface uses them to create an efficient personnel menu. Other applications use them for other reasons which anyone who has every used UNIX could explain to you. More later.LINK
_______________________________________________________________________________
STRUCT FF_Link
fsptr refIDlist
fsptr URL
STRUCT END
; refIDlist goes here
; URL text goes here.
__FS.MakeLink ptr_URL
Creates a link in the current directory. You specify a pointer to the name of a URL, it is looked up and it's refIDlist created. The refIDlist and name are placed into the data branch. This function returns the refID of the new link, unless it fails then it returns NULL.
__FS.RemoveLink refID
Removes a link. Operates just like __FS.DeleteFile otherwise.
__FS.ValidateLink refID, trespass
If the target of the link exists locally, then the targets refId is returned. Else NULL is returned. If the target is non-local, then the trespass authority flag must set for the non-local filesystem functions to attempt to verify the link.
________________________________________________________________________________ An archive is almost exactly the same thing as a folder, except for a few minor deviations: You can not execute any objects within them, and most of their files can not be altered beyond simple creations, migrations and deletions. Also, every single file therein is compressed and possibly encrypted. This is in addition to any other compression and/or encryption.A R C H I V E F O L D E R
_______________________________________________________________________________
An archiving operation effects the current folder and all folders and files therein. The functions start at the deepest sub-folders, if any, and work their way up to the current one, arching each file and folder as encountered.
Grail inherently supports archives through the FS hyper device object. While you can wander through the highly-compressed archives just like any other folder, you can not use them. Under the Natural Landscape Metaphor they look like they are encased in ice.
The archive object functions essentially take care of themselves. They will proceed until done, posting it's current status. Because of the time such a function requires however, you'd usually create a separate running active instance (a thread) and monitor it, providing semaphore and messaging information back to the user.
This obect class is bound.
__ARCHIVE_Archive
Archives the current directory and all folders and files contained.
__ARCHIVE_Unarchive
Unarchives all folders and files starting at the current folders down through the heirarchy.
________________________________________________________________________________ This file type is explained in the core document.OBJECT FILE
_______________________________________________________________________________
________________________________________________________________________________ [ed: revise!]DATA FILE
_______________________________________________________________________________
Grail has a general data type of file of course, but also has special recognition (optional) for binary documents, ASCII text document and UNICODE text documents.
TEXT ASCII/UNICODE
Normally, the subtype is not ignored.
As far as Grail is officially concerned, Plaintext has no binary control codes, excepting 13 to denote new lines (ie UNIX), 26 to end the page, 8 to tab, and 0 (NULL) to terminate the entire file. Grail has subtypes accepting either one byte ASCII (0), or two byte UNICODE (1). Technically GrayText, RTF, and HTML could also be considered plaintext, and probably eventually will be, in that order.
DATA FILE OBJECT-ORIENTATION
You can actually load a data file which the same functions that you would use to load an object assembled by GA. A data file can hold in its associatives a list of function names for the data file and the object/instance/function that this maps onto.
To clarify this, say we take our perennial example of Id Software's DOOM2.WAD. We could define it to have an open functions which maps to the object file DOOM][:/Open_Wad. By trying open DOOM2.WAD (clicking on it) will automatically startup the DOOM ][. When we are finished, we simple call the data file's Close function.
open
close
edit
save
load
abort
delete
display
_____________________________________________________________________________ When you move a Grail file, you move three parts, the Binding, The Associative Branch and the Data Branch. And in that order. Moving files locally from folder to folder is no problem. Moving them across a non-local domain such as a modem or IPX network is slightly different, but still no problem if two Grail systems are communicating with each other since the binding/associative/data trio is sent as one bound data stream. When transmitting files for storage on non Grail systems however there are definite problems. If they are not set up to understand GFS, you must package them. When you package a file you create a single file that is composed of a binding, an associative branch, and data branch. Used for transport across other systems or for packing files.PACKAGING:
MOVING FILES ACROSS NONLOCAL DOMAINS
_____________________________________________________________________________
A package, thus, is one single large file containing either one or many other files. The header structure is
CLASS STRUCT
ascii <PACK>
d.8 filespace_bitwidth
fsdptr binding_length
fsdptr entries ;0=file, other is folders
fsdptr folders
STRUCT END
followed by several structs of
CLASS STRUCT
fsdptr folder_name
fsdptr associative
fsdptr data
STRUCT END
After the struct then follows the folder name, if any, then the associative branch and then the data branch. The folder name points to a title:subtitle string which is the name of the folder the following file comes from. If it is NULL, then we use the last declared folder name. If there is no folder name declared in the entire file, then we assume the current folder.
__FS.Package refID
Copies binding, data and associative branch into a new data area and creates a file of package type.
__FS.Unpackage refID
When you receive a Grail archive from a machine that doesn't understand such things it will be held in the package format. Which means after it is transferred to you, you will execute the __FS.Unpackage function which will unpackage the file into an archive and delete the packaged file in the process.
FOLDER.Package
Packs an entire folder and its subfolders.
FOLDER.Unpackage
Unpacks an entire folder and its subfolders.
________________________________________________________________________________ Handles are all pointers to a buffer in memory (header) created specifically for THAT file. Each file opened allocates memory such as:S T R E A M F I L E H A N D L I N G
_______________________________________________________________________________
OPENING SAME FILE MULTIPLE TIMES
You can open a file multiple times without question most of the time. You can also lock the file while you make serious changes. However you do it, you are guarented that each read/write struct will be moved whole. No locking is required.
Note that ....ADAPTIVE CACHING
STREAM HANDLE STRUCTURE
STRUCT HANDLE_STRUCT
binding_struct binding
fsptr position
fsptr position_write
fsptr buffer_length
dbit.32 status
1 write_buffer
1 read_buffer
1 write_status
1 read_status
1 locked
;keep in mem?
1 name
1 data_maplist
dbit end
STRUCT END
; nbytes name
; nbyte buffer
; nbytes data maplist
; nbytes assc maplist
__FS.Open refID, mode, lock, caching
Allocates memory for a filestream header. The function returns a pointer to the file stream structure. A NULL indicates failure. If lock is flagged, then the file will be locked on open. Modes are readonly (0), writeonly (1), readandwrite (2). If caching is 0, then no caching is used. If 1, then adaptive caching scheme is used, which may use up a noticable amount of memory.
__FS.Close handle
By giving this function the handle of a file, you can close the file. The buffer will be flushed and the stream structure deallocated. It returns NULL if it fails, 1 if close, or 2 if it had to flush data when closing.
__FS.ReadStruct handle, fsdptr_length, ptr_destination
Reads in fsdptr length of bytes of data from file handle to the pointer address at ptr_destination. Returns NULL if file not open or open for write only. Also returns (in EBX) the status induced by the read:
0 No problems
1 Not opened/valid
2 Locked
3 BOF
4 EOF
__FS.WriteStruct handle, fsdptr_length, ptr_destination
Writes out fsdptr length of bytes of data from file handle to the pointer address at ptr_destination. Returns NULL if file not open or open for write only. Also returns (in EBX) the status induced by the read:
0 Write to extend
1 Not opened/valid
2 Locked
3 Desync Write to beginning
4 Overwrite
__FS.ReadASCII handle
Returns one binary ascii character back in a byte. Also returns (in EBX) the status induced by the read:
0 No problems
1 Not opened/valid
2 Locked
3 BOF
4 EOF
__FS.WriteASCII handle, char
Puts the ASCII character into the stream of the specified handle. Also returns (in EBX) the status induced by the read:
0 Write to extend
1 Not opened/valid
2 Locked
3 Desync Write to beginning
4 Overwrite
__FS.ReadUnicode handle
Returns one binary unicode word back. Also returns (in EBX) the status induced by the read:
0 No problems
1 Not opened/valid
2 Locked
3 BOF
4 EOF
__FS.WriteUnicode handle, unicode
Places the word-sized unicode character into the stream. Also returns (in EBX) the status induced by the read:
0 Write to extend
1 Not opened/valid
2 Locked
3 Desync Write to beginning
4 Overwrite
__FS.ReadPosition handle
Returns the current position in the file.
__FS.ChangePosition handle, position, method
Changes the position in the file absolutely (0) or relatively (1).
__FS.Position handle
Returns the file position.
__FS.PositionOk? handle
-1 beginning of file detected (BOF)
0 ok
1 end of file detected (EOF)
__FS.Direction handle, direction
Normally a stream instruction will move your position forward in the file. You can set to move backward though as well. Note that for structs, it read the struct in correctly, and only changes position afterward. Forward is 0, backwards is 1.
__FS.Direction? handle
Returns 0 for forward, and 1 for backwards.
__FS.SearchNULL handle, ptr_string, location
Same as __FS.Search but it computes the length by doing a search for NULL first.
__FS.Search handle, ptr_string, location, length
Searches forward in a file (data branch) for the supplied data.
__FS.Cut handle, location, length
Collapses the file by the specified part.
__FS.Insert handle, position, length, ptr_data
Inserts new data into the specificed position of the file, using the data pointed to in memory.
__FS.InsertNULL handle, position, ptr_data
Computes the length of a piece of text data, then inserts it into the specificed position of the file, using the data pointed to in memory.
__FS.Crop handle, location, length
Removes everything from the file but the part bounded here.
__FS.IsLock? handle
Return boolean truth of whether file is locked or not.
__FS.Lock handle
Locks the files so no other processes from the same processor or another one in the symmetric system can use it.
__FS.Unlock handle
Unlocks the file for use.
______________________________________________________________ __FS.Create mode, contiguous, reservedOPERATIONS ON WHOLE FILES
______________________________________________________________
Creates a file, and returns it's refID. The file that is created is simple and unadorned. No data branch at all in fact. Only the binding, and it's associative file. The modes are read, write, and readwrite. If the contiguous flag is set, then the OS wll try to keep the file contiguous. Reserved indicates an amount of fsdptr contiguous filespace that the os should try to reserve for the file.
__FS.Copy refID
Makes a copy of the specified file and places it in the target folder.
__FS.Move refID
Moves refID file from the current source directory to the current target directory.
__FS.Replace refID, refID
Replaces a file with another one.
__FS.Replicate refID, ptr_filename
Makes an exact replicant of a file with a new name.
__FS.Delete refID
Removes the link to the binding from the root, and marks the files binding as deleted. The bind is changed to "bind" (in lower case).
__FS.DeleteSecure refID
Same as __FS.Delete, but forces a secure delete -- zeros all the entire space of the file and then zeros out the binding.
__FS.Append refID, refID
Copies the data branch of refID and tags it onto the end of refID target file.
__FS.Purge refID
Deletes all but the newest version of a file. Also removes tokens.
__FS.PurgeSecure refID
Deletes all but the newest version of a file, but securely -- zeroing out file space.
__FS.Backup refID
Creates a newer version of a file... an exact copy.
__FS.Compress refID
Compresses the file, then sets the compress bit on. From now on, every time this file is accessed or loaded, it must first be uncompressed. Compression is by the standard huffman variant. Uses __COMPRESS.
__FS.Uncompress refID
Uncompresses the file, then turns off the compress bit. Uses __DECOMPRESS.
______________________________________________________________ These functions allow you to simply open a file into memory, modify it, and then close it back out to the file. Simple enough, eh? Pretty much. When you open a file thusly, it allocates an area in memory to hold the contents of the file (it's data branch) and another area to hold a small amount of information on the file itself (the file's name, URL, etc).MEMORY / FILE EXCHANGES
______________________________________________________________
When these function are used on it file, it;s policy is automagically changed to promote high-speed streaming of data over other considerations (ie, contiguous files) but also that buffering is not required.
[min: Those of you who have been following Grail design for a while may notice that Data Godets have disappeared. :( Don't worry. The are safe in GODET.DOC, but because of complications, the concept may not make it into Grail for a while. If they do they will be subsumed by this function set. Godets, for those of you who don't remember, allocated unused address lines and some real physical memory to effectively load files up to 4gb into memory as thier own virtual swapfile system. Wanna mount an entire DVD into memory? Go for it.] __FS.OpenData refID
This open a file into memory. Returns NULL if fails. Otherwise return backbone handle.
__FS.CloseData handle, flush
If flush is 0, then this simply __MMU.Deallocates the data and file handle areas from memory. Otherwise, it first writes this memory back out to the file. If the memory area has been resized, then so too will be the file.
__FS.WriteData refID, handle
After you have created a file (for example, with __FS.Create) you can write out an area of allocated memory to a file.
________________________________________________________________________________ A godet is a very large (read-mostly) file that is opened and mapped into the 4GB (2^32 byte) range of memory through paging. You can specify the amount of real memory to allocate for each godet. The point of this is to be able to access huge data files AS IF they were completely in memory, without creating wasteful swapfile space.D A T A G O D E T
________________________________________________________________________________
Each Godet file opened performs a non-vmmu memory allocation for space, and marks all it's pages as not present. The size of the page table/directory is changed as necessary. ID's WAD files would be good godet candidate. If you had assigned 256kb per godet, then the 14mb DOOM2.WAD would take up only 256kb of memory even though it 'owned' 14mb of the 4gb address space in your system. There is an overhead of about 14kb for additional page tables as well.
Why not just cache it, you say? Well... we sort of are, selectively. But this allows us to drop the annoying fopen/fseek jargon and access our data more naturally. It's a compromise hybrid between caching and virtual memory.
To clear things up, let us say that the average swap file is a public or common structure. A Godet is a specific swapfile which uses a named file that typically is preexisting. The file continues to exist afterward as well. For example look at this sample memory map that has three files open as godets:
VMMU/GODET MEMORY MAP |-----------------------| | | | Unused Address Space | | | |.......................| ---- | GODET #3 | |.......................| | GODET #2 | |.......................| Virtual Memory | GODET #1 | |.......................| | | |Virtual Memory (Common)| | | |.......................| ---- | | | Real Memory | Real Memory | | |-----------------------| A godet allocates three things: An area to hold information on the file where the data is held, ........
__FS.OpenDataGodet ptr_filename, address_size, physical_size, type, lock
This function allocates a block of address space above your linear memory and a certain amount of real DRAM memory. The pages of real memory that it allocates are marked as belonging to a godet through bit 9 of the PTE.
Bit 9 in Grail is used to mark a page as not free for allocation by common VMMU functions.Intel Page Table Entry (PTE) Illustration 31 12 11 0 -------------------------------------------------------------------- | | | | | | | |P|P|U|R| | | Page frame address 31..12 of linear mem |Avail|0 0|D|A|C|W|/|/|P| | | | | | | | |D|T|S|W| | --------------------------------------------------------------------When a Godet is allocated, it also opens a file handle to it which is used to figure where to transfer data. A Godet uses two MMU entries. The second one follows directly after and has a MMU.flag.link of 1. This structure supplies the pointer to the file system file handle. Both MMU entries are chained together thusly through this structure:
STRUCT
ptr handle ;handle is the 32bit offset to memory
ptr FS ; <<-- NOTE
ptr object ;ptr to object handle that created it
dbit.16 flag
1 deny ;denied hardware or core area
1 dma ;normal/DMAable
1 secure ;unsecure/secure (personnel/supervisor)
dbit end
dbit.16 style
4 module
4 align
dbit end
STRUCT END
See description above. Returns a MMU style handle in ESI.
Type...
0 normal1 GODET
Above the __FS file system this simple allocates memory the same size as a file and then copies the data from the file to memory. Returns the MMU handle or NULL if there is a problem.
As an example, this script virtually loads the doom2 wad into memory on a 4mb computer:
wad = __FS.OpenDataGodet "Doom2.wad", 14680064, 524288, godet __FS.CloseDataGodet wad __FS.CloseDataGodet handle
Closes the godet.
_____________________________________________________________________________ The raw data of a file or application, etc. The contents of the file are not the concern of the operating system, unless it's a control, device driver, folder, or link file, which are system constructs. Those are described elsewhere.D A T A B R A N C H
_____________________________________________________________________________
_____________________________________________________________________________ An associative branch is in some sense an extension of the binding information. Within it is held the vital Associative and Data Branch filemaps, system information on the file, application and personnel settings. The binding is some times called the header. The associative and data branch together are called the body.A S S O C I A T I V E B R A N C H
_____________________________________________________________________________
File Illustration
Binding _|________________________ | | Associative Branch Data Branch | |-Associative Filemap |-Data Filemap + |-System |-Application |-Object '-User# An item can multiple instances of it if it makes use of this. If this is 0, then numbering is not used. If it is 4, then a byte prefaces the stream. If a 6 then a dword.
STRUCT FF_Associativeascii <ASSC>
d.8 fs_bitwidth ;2^(n-1)
fsptr FSS_Binding binding ;back-link to binding
fsptr assc_ptr
fsdptr assc_length
fsptr data_ptr
fsdptr data_length
fsptr other_ptr
STRUCT END
STRUCT count
fsdptr system
fsdptr application
fsdptr object
fsdptr user#
fsdptr total
STRUCT END
__FS.AssociativeAdd type, no, refID, ptr_name, ptr_value, length
Add or changes a specifically named group item, depending whether it already existed.
__FS.AssociativeAdd_NULLStream type, no, refID, ptr_name, ptr_value
This is the same as __FS.AssociativeAdd excepting that it looks for a NULL to terminate the stream and computes the length for you. Used when moving around text. Use the other for data. Note that your language policy setting will influence whether it looks for an 8-bit or 16-bit NULL. Actually just computes the length and then calls __FS.AssociativeAdd.
__FS.AssociativeDelete type, no, refID, ptr_name
Deletes the specified item. If no is 0, then all such items are deleted, otherwise only the one matching the numbering.
__FS.AssociativeVerify type, no, refID, ptr_name
Asks if the specified item exists, and how long it is. Returns exist and length such as:
(exist, length) = __FS.AssociativeVerify Personnel, All, "Bookmark"
__FS.AssociativeGet type, no, refID, ptr_name, ptr_dst
If the item exists, this copies it to ptr_dst.
__FS.AssociativeCountNo type, refID
__FS.AssociativeGetEntry type, no, refID
__FS.AssociativePurge type, no, refID
ASSOCIATIVE AND DATA BRANCH FILEMAPS
Many of you may be used to, or know of the FAT Filesystem used by MS-DOS. Grail's filesystem is nothing like that. Each individual file is responsible for it's own mapping onto a drive. Since files can be flagged to be contiguous there is less thrashing about of files, this isn't as much of a problem as you might think.
The filemap is a totally different structure depending on your type of drive. It is an architecture dependant area used directly by the low-level filesystem device objects. It operates in sectors on IDE and floppy drives, but not so with modems.
What happens when your drive does not have enough contiguous space to create a file? You get an error of course. Two things can happen. You can defragment the drive, or you can complain to the user there is too much clutter on it. You can defrag directly, or set up the defaults to automatically attempt a defrag if filespace gets low.
The root contains a list of pointers to the filemap of every single file on the system. That is, for instance, one of my partitions has 4869 files on it. So the root has 19,476 bytes of file pointer info in it. This list is used whenever a file is created or is modified in size so as files don't overlap one another.
The Grail filesystem is designed to quickly read files, though it is slightly slower in creating them.
For an IDE drive the filemap is a dword denoting now many sectors are in the file, the size of a sector, Grail IDE sectors being fixed at 512 bytes, followed by the starting and ending sector numbers.
SYSTEM
Classification
Two ASCIIZ13 lines. First has general classification. Second has specific format used. You should also use the type and subtypes, to give your a four data defination of a file. For example:
Image/JPEG
Image/PNG
Sound/VOC
Animation/FLI
object/script
Data Compression
Is the data branch compressed? Compression effects the entire branch. This is the name of the algorythm to use.
Asscociative Compression
Is the associative branch compressed? Note that unlike the data branch, compression in the associative branch only occurs AFTER the assc compression tags (otherwise you wouldn't know what compression was being used. :)
Encryption
Decryption
Object
Name
One ASCIIZ line. The name given to the file. Can be anything up to 4GB.
Error_log
asciiz13.
History_log
asciiz13.
Registration_key
Application
For data. The name of the application that has created or last edited this file.
Age
APPLICATION
Application
Name of application this object belongs to.
Comment
ASCIIZ13 comment. Usually a description of the file.
Author
ASCIIZ13 about or naming the author.
Legal
ASCIIZ13 legal notice.
Own
A list of the files that the app brought to your system. asciiz13.
Remove
A list of the files that should be deleted when the app is removed from your system. asciiz13. Listed with folders, etc.
Original_Conception
TimeDate of the conception or original start of the project, document, etc.
Issue_Conception
The timedate for this particular issue in a series.
Title= The Warlock Cipher
SubTitle=
Author= Lewis Sellers
Platform= GRAIL/IBM
House/Company= TMG/Grail
Date= 1 July 1995
Technical Support Line= 1(800)999-9998
Fax= phone://1(800)999-9999
Business Hours= 7:00pm to 7:10pm EST
EmailInfo= info@grailos.org
EmailHelp= help@grailos.org
MailingList_Subscribe= infoserver@grailos.org subscribe grailos
MailingList_UnSubscribe= infoserver@grailos.org unsubscribe grailos
WWW= http://www.grailos.org/
FTP= ftp://ftp.grailos.org/pub/
NewsGroup= alt.os.grail.d
NewsGroup_d= alt.os.grail.d
NewsGroup_Binaries= alt.os.grail.binaries
RAM=8mb,16mb
HD=37mb,450mb
CPU=486,Pentium
FPU=No,Yes
Drystones=
OBJECT
path, object, function
open
edit
close
USER# GROUPS
STRUCT
STRUCT Name
fsdptr length
fsptr start
STRUCT END
fsdptr length
fsptr start
d.8 type
d.8 numbering
STRUCT END
Now this is a little different than the other groups. The normal name/data structure is prefixed by a NULL-terminated user name identifying each as uniquely belonging to a certain user. Grail ignores all but the one relevant to the current user. While in supervisor mode you can however effect all the others.
Bookmark (saved game)
this data is what some might called a "saved game". the data is defined by the objects. This item uses the numbering feature, so that you can have multiple bookmarks.
Session (session saved state)
the saved state of the system. fast resumes. A sort of master bookmark.
Guise Position
The actual position of the guise. Whether the metaphor uses everything or not is up to it.
STRUCT guise_positiond.32 x
d.32 y
d.32 z
d.32 xr
d.32 yr
d.32 zr
d.32 ?
d.32 ?
STRUCT END
Guise Iconic
A two-dimensional icon. Grail standards are for images to use an RGB colorwheel mapped to whatever bitdepth is currently used. This allows for fast translation between depths. The header is:
STRUCT guise_icon_header
d.16 width
d.16 height
d.8 bitdepth ;8,16,24
d.8 ?
d.16 ?
STRUCT END
The data then follows logically, starting at x0,y0, progressing positively through the x, and then line by line to the bottom right of the image.
Guise Audial
STRUCT guise_audial_header
d.8 bits ;4,8,16,18,20,24
d.8 channels ;1,2
d.32 frequency
d.8 range
d.8 ?
STRUCT END
The data follows. The channels are lain out next to one another. It is fine to use audial and iconic guises together.
Guise Movie
A movie is a series of icons with same-size clips of audio interspacing them. Data always starts with icon, then audio section. then alternates. The header is:
STRUCT guise_movie_header
d.16 width
d.16 height
d.8 bitdepth
d.8 bits
d.8 channels
d.32 frequency
d.8 range
d.8 ?
STRUCT END
Please note that while MPEG1, MPEG2 and Quicktime are the favored true movie formats for use by Grail, this is the native format that is supported by all versions of Grail. You probably will want to use the other formentioned formats for commercial products.
Guise Interactive
This is actually the name of an object or program that manages the appearance of a guise as an active task. Some are specific to an application, some are generic and work on all programs. The metaphor, if it handles these, will start up the object and send the name of this object to it.
Preface
The Glass Metaphor places this image up on the screen as soon as the primary object of an application is started. You should put these images ONLY on the primary object in an application and no where else. The structure is the same as the Guise Iconic.
_____________________________________________________________________________
SELECTION
_____________________________________________________________________________
Selection
Select.Folder
Select.File
Select.Mask
?
*
Unselection
Unselect.Folder
Unselect.File
Unselect.Mask
Selection Action
struct
{
int total
int processed;
int ignored
int overwritten
int missing //_from_source
};
Selection.TotalLength memory_handle
Selection.TotalSize memory_handle
Returns the total amount of space occupied/required by all the selected files.
Selection.Delete memory_handle
Selection.Copy memory_handle, adversity_response, heirarchy, progression
Every file that is successfully copied, is "tagged". This allows you to more easily create a database of problem files using other selection functions.
Adversity_response,
If file already exists at destination
ignore
overwrite
overwrite with newer only
if source file does not exist when called for,
skip
abort
if can not write to destination (not enough space),
skip
abort
if source device off-line,
abort
wait device cycle
if destination device off-line,
abort
wait device cycle
if destination device saturated,
abort
wait
?
Heirarchy,
relative, starting at current destination folder
absolute, starting at root
Progression,
Continuous
Stop at each action
Stop at each failure
Selection.Move memory_handle, adversity_response, heirarchy, progression
Selection.Continue memory_handle, progression
Selection.Position memory_handle, where
Selection.CurrentEntry memory_handle
Returns the current entry
Selection.PurgeTagged memory_handle
Selection.CropTagged memory_handle
Selection.SplitByTag memory_handle
Selection.Untag memory_handle
This removes the action flag from all files in selection structure.
Selection.SortbyFolder memory_handle