Károly Balogh 21 лет назад
Родитель
Сommit
65223ed162
1 измененных файлов с 243 добавлено и 17 удалено
  1. 243 17
      rtl/morphos/system.pp

+ 243 - 17
rtl/morphos/system.pp

@@ -55,9 +55,14 @@ var
   MOS_DOSBase  : Pointer;
 
   MOS_heapPool : Pointer; { pointer for the OS pool for growing the heap }
+  MOS_origDir  : LongInt; { original directory on startup }
 
 
-{ MorphOS functions }
+{*****************************************************************************
+                           MorphOS functions
+*****************************************************************************}
+
+{ exec.library functions }
 
 function exec_OpenLibrary(libname: PChar location 'a1'; 
                           libver: LongInt location 'd0'): Pointer; SysCall MOS_ExecBase 552;
@@ -72,6 +77,9 @@ function exec_AllocPooled(poolHeader: Pointer location 'a0';
 function exec_SetSignal(newSignals: LongInt location 'd0';
                         signalMask: LongInt location 'd1'): LongInt; SysCall MOS_ExecBase 306;
 
+
+{ dos.library functions }
+
 function dos_Output: LongInt; SysCall MOS_DOSBase 60;
 function dos_Input: LongInt; SysCall MOS_DOSBase 54;
 function dos_IoErr: LongInt; SysCall MOS_DOSBase 132;
@@ -105,13 +113,48 @@ function dos_GetCurrentDirName(buf: PChar location 'd1';
 
 function dos_Lock(lname: PChar location 'd1';
                   accessMode: LongInt location 'd2'): LongInt; SysCall MOS_DOSBase 84;
+procedure dos_Unlock(lock: LongInt location 'd1'); SysCall MOS_DOSBase 90;
+function dos_CurrentDir(lock: LongInt location 'd1'): LongInt; SysCall MOS_DOSBase 126;
+function dos_Examine(lock: LongInt location 'd1';
+                     FileInfoBlock: Pointer location 'd2'): Boolean; SysCall MOS_DOSBase 102;
+function dos_CreateDir(dname: PChar location 'd1'): LongInt; SysCall MOS_DOSBase 120;
+
 
 implementation
 
 {$I system.inc}
 
 
-{ OS dependant parts  }
+{*****************************************************************************
+                    System Dependent Structures/Consts
+*****************************************************************************}
+
+{ Used system structures }
+Type
+  TDateStamp = packed record
+    ds_Days   : LongInt;      { Number of days since Jan. 1, 1978 }
+    ds_Minute : LongInt;      { Number of minutes past midnight }
+    ds_Tick   : LongInt;      { Number of ticks past minute }
+  end;
+  PDateStamp = ^TDateStamp;
+
+  PFileInfoBlock = ^TFileInfoBlock;
+  TFileInfoBlock = packed record
+    fib_DiskKey      : LongInt;
+    fib_DirEntryType : LongInt;
+    { Type of Directory. If < 0, then a plain file. If > 0 a directory }
+    fib_FileName     : Array [0..107] of Char;
+    { Null terminated. Max 30 chars used for now }
+    fib_Protection   : LongInt;
+    { bit mask of protection, rwxd are 3-0. }
+    fib_EntryType    : LongInt;
+    fib_Size         : LongInt;      { Number of bytes in file }
+    fib_NumBlocks    : LongInt;      { Number of blocks in file }
+    fib_Date         : TDateStamp; { Date file last changed }
+    fib_Comment      : Array [0..79] of Char;
+    { Null terminated comment associated with file }
+    fib_Reserved     : Array [0..35] of Char;
+  end;
 
 { Errors from dos_IoErr(), etc. }
 const
@@ -168,6 +211,13 @@ const
   OFFSET_CURRENT   = 0;
   OFFSET_END       = 1;
 
+{ Lock AccessMode }
+const
+  SHARED_LOCK      = -2;
+  ACCESS_READ      = SHARED_LOCK;
+  EXCLUSIVE_LOCK   = -1;
+  ACCESS_WRITE     = EXCLUSIVE_LOCK;
+
 { Memory flags }
 const
   MEMF_ANY      = 0;
@@ -190,6 +240,99 @@ const
   SIGBREAKF_CTRL_C = $1000;   { CTRL-C signal flags }
 
 
+{*****************************************************************************
+                  MorphOS File-handling Support Functions
+*****************************************************************************}
+type
+  { AmigaOS does not automatically close opened files on exit back to  }
+  { the operating system, therefore as a precuation we close all files }
+  { manually on exit.                                                  }
+  PFileList = ^TFileList;
+  TFileList = record { no packed, must be correctly aligned }
+    handle : LongInt;      { Handle to file    }
+    next   : PFileList;      { Next file in list }
+  end;
+
+var
+  MOS_fileList: PFileList; { List pointer to opened files }
+
+{ Function to be called at program shutdown, to close all opened files }
+procedure CloseList(l: PFileList);
+var 
+  tmpNext   : PFileList;
+  tmpHandle : LongInt;
+begin
+  if l=nil then exit;
+
+  { First, close all tracked files }
+  tmpNext:=l^.next;
+  while tmpNext<>nil do begin
+    tmpHandle:=tmpNext^.handle;
+    if (tmpHandle<>StdInputHandle) and (tmpHandle<>StdOutputHandle) 
+       and (tmpHandle<>StdErrorHandle) then begin
+      dos_Close(tmpHandle);
+    end;
+    tmpNext:=tmpNext^.next;
+  end;
+ 
+  { Next, erase the linked list }
+  while l<>nil do begin
+    tmpNext:=l;
+    l:=l^.next;
+    dispose(tmpNext);
+  end;
+end;
+
+{ Function to be called to add a file to the opened file list }
+procedure AddToList(var l: PFileList; h: LongInt);
+var
+  p     : PFileList;
+  inList: Boolean;
+begin
+  inList:=False;
+  if l<>nil then begin
+    { if there is a valid filelist, search for the value }
+    { in the list to avoid double additions }
+    p:=l;
+    while (p^.next<>nil) and (not inList) do
+      if p^.next^.handle=h then inList:=True
+                           else p:=p^.next;
+    p:=nil;
+  end else begin
+    { if the list is not yet allocated, allocate it. }
+    New(l);
+    l^.next:=nil;
+  end;
+
+  if not inList then begin
+    New(p);
+    p^.handle:=h;
+    p^.next:=l^.next;
+    l^.next:=p;
+  end;
+end;
+
+{ Function to be called to remove a file from the list }
+procedure RemoveFromList(var l: PFileList; h: longint);
+var
+  p     : PFileList;
+  inList: Boolean;
+begin
+  if l=nil then exit;
+
+  inList:=False;
+  p:=l;
+  while (p^.next<>nil) and (not inList) do
+    if p^.next^.handle=h then inList:=True
+                         else p:=p^.next;
+
+  if p^.next<>nil then begin
+    dispose(p^.next);
+    p^.next:=p^.next^.next;
+  end;
+end;
+
+
 {*****************************************************************************
                        Misc. System Dependent Functions
 *****************************************************************************}
@@ -198,6 +341,17 @@ procedure haltproc(e:longint);cdecl;external name '_haltproc';
 
 procedure System_exit;
 begin
+  { We must remove the CTRL-C FALG here because halt }
+  { may call I/O routines, which in turn might call  }
+  { halt, so a recursive stack crash                 }
+  if BreakOn then begin
+    if (exec_SetSignal(0,0) and SIGBREAKF_CTRL_C)<>0 then
+      exec_SetSignal(0,SIGBREAKF_CTRL_C);
+  end;
+
+  { Closing opened files }
+  CloseList(MOS_fileList);
+
   if MOS_DOSBase<>NIL then exec_CloseLibrary(MOS_DOSBase);
   if MOS_heapPool<>NIL then exec_DeletePool(MOS_heapPool);
   haltproc(ExitCode);
@@ -261,6 +415,7 @@ begin
   end;
 end;
 
+
 {*****************************************************************************
                               ParamStr/Randomize
 *****************************************************************************}
@@ -303,13 +458,13 @@ var
 { first address of heap }
 function getheapstart:pointer;
 begin
-   getheapstart:=@int_heap;
+  getheapstart:=@int_heap;
 end;
 
 { current length of heap }
 function getheapsize:longint;
 begin
-   getheapsize:=int_heapsize;
+  getheapsize:=int_heapsize;
 end;
 
 { function to allocate size bytes more for the program }
@@ -326,33 +481,98 @@ end;
                            Directory Handling
 *****************************************************************************}
 procedure mkdir(const s : string);[IOCheck];
+var
+  buffer : array[0..255] of char;
+  j : Integer;
+  tmpStr : string;
+  tmpLock : LongInt;
 begin
   checkCTRLC;
-  InOutRes:=1;
+  if (s='') or (InOutRes<>0) then exit;
+  tmpStr:=s;
+
+  for j:=1 to length(tmpStr) do
+    if tmpStr[j]='\' then tmpStr[j]:='/';
+  move(tmpStr[1],buffer,length(tmpStr));
+  buffer[length(tmpStr)]:=#0;
+
+  tmpLock:=dos_CreateDir(buffer);
+  if tmpLock=0 then begin
+    dosError2InOut(dos_IoErr);
+    exit;
+  end;
+  dos_UnLock(tmpLock);
 end;
 
 procedure rmdir(const s : string);[IOCheck];
 var
   buffer : array[0..255] of char;
   j : Integer;
-  temp : string;
+  tmpStr : string;
 begin
   checkCTRLC;
   if (s='.') then InOutRes:=16;
   If (s='') or (InOutRes<>0) then exit;
-  temp:=s;
-  for j:=1 to length(temp) do
-    if temp[j] = '\' then temp[j] := '/';
-  move(temp[1],buffer,length(temp));
-  buffer[length(temp)]:=#0;
+  tmpStr:=s;
+  for j:=1 to length(tmpStr) do
+    if tmpStr[j] = '\' then tmpStr[j] := '/';
+  move(tmpStr[1],buffer,length(tmpStr));
+  buffer[length(tmpStr)]:=#0;
   if not dos_DeleteFile(buffer) then
     dosError2InOut(dos_IoErr);
 end;
 
 procedure chdir(const s : string);[IOCheck];
+var
+  buffer : array[0..255] of char;
+  alock : LongInt;
+  FIB : PFileInfoBlock;
+  j : Integer;
+  tmpStr : string;
 begin
   checkCTRLC;
-  InOutRes:=1;
+  If (s='') or (InOutRes<>0) then exit;
+  tmpStr:=s;
+
+  for j:=1 to length(tmpStr) do
+    if tmpStr[j]='\' then tmpStr[j]:='/';
+
+  { Return parent directory }
+  if s='..' then begin
+    getdir(0,tmpStr);
+    j:=length(tmpStr);
+    { Look through the previous paths }
+    while (tmpStr[j]<>'/') and (tmpStr[j]<>':') and (j>0) do
+      dec(j);
+    if j>0 then
+      tmpStr:=copy(tmpStr,1,j);
+  end;
+  alock:=0;
+
+  move(tmpStr[1],buffer,length(tmpStr));
+  buffer[length(tmpStr)]:=#0;
+  { Changing the directory is a pretty complicated affair }
+  {   1) Obtain a lock on the directory                   }
+  {   2) CurrentDir the lock                              }
+  alock:=dos_Lock(buffer,SHARED_LOCK);
+  if alock=0 then begin
+    dosError2InOut(dos_IoErr);
+    exit;
+  end;
+
+  FIB:=nil;
+  new(FIB);
+ 
+  if (dos_Examine(alock,FIB)=True) and (FIB^.fib_DirEntryType>0) then begin
+    alock := dos_CurrentDir(alock);
+    if MOS_OrigDir=0 then begin
+      MOS_OrigDir:=alock;
+      alock:=0;
+    end;
+  end;
+
+  if alock<>0 then dos_Unlock(alock);
+  if assigned(FIB) then dispose(FIB)
 end;
 
 procedure GetDir (DriveNr: byte; var Dir: ShortString);
@@ -375,6 +595,7 @@ end;
 { close a file from the handle value }
 procedure do_close(handle : longint);
 begin
+  RemoveFromList(MOS_fileList,handle);
   { Do _NOT_ check CTRL_C on Close, because it will conflict 
     with System_Exit! }
   if not dos_Close(handle) then
@@ -493,7 +714,7 @@ procedure do_open(var f;p:pchar;flags:longint);
 }
 var
   i,j : LongInt;
-  openflags: LongInt;
+  openflags : LongInt;
   path : String;
   buffer : array[0..255] of Char;
   index : Integer;
@@ -511,7 +732,7 @@ begin
       delete(path,1,3);
       getdir(0,s);
       j:=length(s);
-      while (s[j] <> '/') AND (s[j] <> ':') AND (j > 0 ) do
+      while (s[j]<>'/') and (s[j]<>':') and (j>0) do
         dec(j);
       if j > 0 then
         s:=copy(s,1,j);
@@ -524,7 +745,7 @@ begin
     begin
       delete(path,1,2);
       getdir(0,s);
-      if (s[length(s)] <> '/') and (s[length(s)] <> ':') then
+      if (s[length(s)]<>'/') and (s[length(s)]<>':') then
         s:=s+'/';
       path:=s+path;
     end;
@@ -581,7 +802,7 @@ begin
     begin
       dosError2InOut(dos_IoErr);
     end else begin
-      {AddToList(FileList,i);}
+      AddToList(MOS_fileList,i);
       filerec(f).handle:=i;
     end;
 
@@ -694,11 +915,16 @@ Begin
 {$ifdef HASVARIANT}
   initvariantmanager;
 {$endif HASVARIANT}
+  MOS_origDir:=0;
+  MOS_fileList:=nil;
 End.
 
 {
   $Log$
-  Revision 1.4  2004-05-02 02:06:57  karoly
+  Revision 1.5  2004-05-09 02:02:42  karoly
+    * more things got implemented
+
+  Revision 1.4  2004/05/02 02:06:57  karoly
     + most of file I/O calls implemented
 
   Revision 1.3  2004/05/01 15:09:47  karoly