Переглянути джерело

o fixed several Linux ipc bugs, based on patch by Ruben Chaer/
Pablo Alfaro (mantis #14075, also fixes #13363):
* ipc msgtyp is clong, not cint
* TIPC_Perm and TSEMid_ds are different on 64 bit systems
* fixed passing semun arguments (have to be passed by value, not reference)
* fixed the order of parameters to msg* syscalls, and don't use
TIPC_Kludge for msgrcv syscall (only for ipccall.inc variants)
* use new operation variants on 64 bit platforms in ipccall.inc
* introduced use kernel_mode/uid/gid_t types for use by the Linux ipc
records
* fixed type of TSEMid_ds.sem_base for Darwin
* added {$packrecords c} to ipc unit, and {$packrecords 4} around
certain structs for Darwin as in the C headers
* fixed passing semun argument to semctl for libc platforms (by
value, not reference)

git-svn-id: trunk@16336 -

Jonas Maebe 14 роки тому
батько
коміт
36aa39cc38
4 змінених файлів з 110 додано та 61 видалено
  1. 35 27
      rtl/linux/ipccall.inc
  2. 4 13
      rtl/linux/ipcsys.inc
  3. 10 0
      rtl/linux/ostypes.inc
  4. 61 21
      rtl/unix/ipc.pp

+ 35 - 27
rtl/linux/ipccall.inc

@@ -25,37 +25,45 @@ begin
     end;
 end;
 
+{$ifdef linux_ipc32}
+const
+  ipc_api_select = 0;    // 16-bit gid/pid types and old structs
+{$else}
+const
+  ipc_api_select = $100; // 32-bit gid/pid types and newer structs
+{$endif}
+
 Const
-  CALL_SEMOP   = 1;
-  CALL_SEMGET  = 2;
-  CALL_SEMCTL  = 3;
-  CALL_MSGSND  = 11;
-  CALL_MSGRCV  = 12;
-  CALL_MSGGET  = 13;
-  CALL_MSGCTL  = 14;
-  CALL_SHMAT   = 21;
-  CALL_SHMDT   = 22;
-  CALL_SHMGET  = 23;
-  CALL_SHMCTL  = 24;
+  CALL_SEMOP      = 1 +ipc_api_select;
+  CALL_SEMGET     = 2 +ipc_api_select;
+  CALL_SEMCTL     = 3 +ipc_api_select;
+  CALL_SEMTIMEDOP = 4 +ipc_api_select;
+  CALL_MSGSND     = 11+ipc_api_select;
+  CALL_MSGRCV     = 12+ipc_api_select;
+  CALL_MSGGET     = 13+ipc_api_select;
+  CALL_MSGCTL     = 14+ipc_api_select;
+  CALL_SHMAT      = 21+ipc_api_select;
+  CALL_SHMDT      = 22+ipc_api_select;
+  CALL_SHMGET     = 23+ipc_api_select;
+  CALL_SHMCTL     = 24+ipc_api_select;
 
 { generic call that handles all IPC calls }
 
-function ipccall(Call,First,Second,Third : cint; P : Pointer) : ptrint;
+function ipccall(Call: cuint; First: cint; Second,Third : culong; P: pointer; Fifth: clong) : ptrint;
 begin
- ipccall:=do_syscall(syscall_nr_ipc,call,first,second,third,ptrint(P));
-// ipcerror:=fpgetErrno;
+ ipccall:=do_syscall(syscall_nr_ipc,TSysParam(call),TSysParam(first),TSysParam(second),TSysParam(third),TSysParam(P),TSysParam(Fifth));
 end;
 
 function shmget(key: Tkey; size:size_t; flag:cint):cint;
 begin
-  shmget:=ipccall (CALL_SHMGET,key,size,flag,nil);
+  shmget:=ipccall (CALL_SHMGET,key,size,flag,nil,0);
 end;
 
 Function shmat (shmid:cint; shmaddr:pointer; shmflg:cint):pointer;
 Var raddr : pchar;
     error : ptrint;
 begin
-  error:=ipccall(CALL_SHMAT,shmid,shmflg,cint(@raddr),shmaddr);
+  error:=ipccall(CALL_SHMAT,shmid,shmflg,cint(@raddr),shmaddr,0);
   If Error<0 then
     shmat:=pchar(error)
   else
@@ -64,55 +72,55 @@ end;
 
 function shmdt (shmaddr:pointer): cint;
 begin
-  shmdt:=ipccall(CALL_SHMDT,0,0,0,shmaddr);
+  shmdt:=ipccall(CALL_SHMDT,0,0,0,shmaddr,0);
 end;
 
 function shmctl(shmid:cint; cmd:cint; buf: pshmid_ds): cint;
 begin
- shmctl:=ipccall(CALL_SHMCTL,shmid,cmd,0,buf);
+ shmctl:=ipccall(CALL_SHMCTL,shmid,cmd,0,buf,0);
 end;
 
 function msgget(key:Tkey; msgflg:cint):cint;
 begin
-  msgget:=ipccall(CALL_MSGGET,key,msgflg,0,Nil);
+  msgget:=ipccall(CALL_MSGGET,key,msgflg,0,Nil,0);
 end;
 
 function msgsnd(msqid:cint; msgp: PMSGBuf; msgsz: size_t; msgflg:cint):cint;
 begin
-  msgsnd:=ipccall(Call_MSGSND,msqid,msgsz,msgflg,msgp);
+  msgsnd:=ipccall(Call_MSGSND,msqid,msgsz,msgflg,msgp,0);
 end;
 
-function msgrcv(msqid:cint; msgp: PMSGBuf; msgsz: size_t; msgtyp:cint; msgflg:cint):cint;
+function msgrcv(msqid:cint; msgp: PMSGBuf; msgsz: size_t; msgtyp:clong; msgflg:cint):cint;
 Type
   TIPC_Kludge = Record
     msgp   : pmsgbuf;
-    msgtyp : cint;
+    msgtyp : clong;
   end;
 Var
    tmp : TIPC_Kludge;
 begin
   tmp.msgp   := msgp;
   tmp.msgtyp := msgtyp;
-  msgrcv:=ipccall(CALL_MSGRCV,msqid,msgsz,msgflg,@tmp);
+  msgrcv:=ipccall(CALL_MSGRCV,msqid,msgsz,msgflg,@tmp,0);
 end;
 
 Function msgctl(msqid:cint; cmd: cint; buf: PMSQid_ds): cint;
 begin
-  msgctl:=ipccall(CALL_MSGCTL,msqid,cmd,0,buf);
+  msgctl:=ipccall(CALL_MSGCTL,msqid,cmd,0,buf,0);
 end;
 
 Function semget(key:Tkey; nsems:cint; semflg:cint): cint;
 begin
-  semget:=ipccall (CALL_SEMGET,key,nsems,semflg,Nil);
+  semget:=ipccall (CALL_SEMGET,key,nsems,semflg,Nil,0);
 end;
 
 Function semop(semid:cint; sops: psembuf; nsops:cuint): cint;
 begin
-  semop:=ipccall (CALL_SEMOP,semid,cint(nsops),0,Pointer(sops));
+  semop:=ipccall (CALL_SEMOP,semid,cint(nsops),0,Pointer(sops),0);
 end;
 
 Function semctl(semid:cint; semnum:cint; cmd:cint; var arg: tsemun): cint;
 begin
-  semctl:=ipccall(CALL_SEMCTL,semid,semnum,cmd,@arg);
+  semctl:=ipccall(CALL_SEMCTL,semid,semnum,cmd,@arg,0);
 end;
 

+ 4 - 13
rtl/linux/ipcsys.inc

@@ -53,21 +53,12 @@ end;
 
 function msgsnd(msqid:cint; msgp: pmsgbuf; msgsz: size_t; msgflg:cint):cint;
 begin
-  msgsnd:=do_syscall(syscall_nr_MSGSND,TSysParam(msqid),TSysParam(msgsz),TSysParam(msgflg),TSysParam(msgp));
+  msgsnd:=do_syscall(syscall_nr_MSGSND,TSysParam(msqid),TSysParam(msgp),TSysParam(msgsz),TSysParam(msgflg));
 end;
 
-function msgrcv(msqid:cint; msgp: PMSGBuf; msgsz: size_t; msgtyp:cint; msgflg:cint):cint;
-Type
-  TIPC_Kludge = Record
-    msgp   : pmsgbuf;
-    msgtyp : cint;
-  end;
-Var
-   tmp : TIPC_Kludge;
+function msgrcv(msqid:cint; msgp: PMSGBuf; msgsz: size_t; msgtyp:clong; msgflg:cint):cint;
 begin
-  tmp.msgp   := msgp;
-  tmp.msgtyp := msgtyp;
-  msgrcv:=do_syscall(syscall_nr_MSGRCV,TSysParam(msqid),TSysParam(msgsz),TSysParam(msgflg),TSysParam(@tmp));
+msgrcv:=do_syscall(syscall_nr_MSGRCV,TSysParam(msqid),TSysParam(msgp),TSysParam(msgsz),TSysParam(msgtyp),TSysParam(msgflg));
 end;
 
 Function msgctl(msqid:cint; cmd: cint; buf: PMSQid_ds): cint;
@@ -87,7 +78,7 @@ end;
 
 Function semctl(semid:cint; semnum:cint; cmd:cint; var arg: tsemun): cint;
 begin
-  semctl:=do_syscall(syscall_nr_SEMCTL,TSysParam(semid),TSysParam(semnum),TSysParam(cmd),TSysParam(@arg));
+  semctl:=do_syscall(syscall_nr_SEMCTL,TSysParam(semid),TSysParam(semnum),TSysParam(cmd),TSysParam(arg));
 end;
 
 

+ 10 - 0
rtl/linux/ostypes.inc

@@ -140,6 +140,16 @@ type
    kernel_off_t = clong;
    kernel_loff_t = clonglong;
 
+{$if defined(cpu32) and not(defined(cpupowerpc)) and not(defined(cpumips)) and not defined(cpumipsel))}
+   kernel_mode_t = cushort;
+   kernel_uid_t = cushort;
+   kernel_gid_t = cushort;
+{$else}
+   kernel_mode_t = cuint;
+   kernel_uid_t = cuint;
+   kernel_gid_t = cuint;
+{$endif}
+
    FLock     = Record
                 l_type  : cshort;       { lock type: read/write, etc. }
                 l_whence: cshort;       { type of l_start }

+ 61 - 21
rtl/unix/ipc.pp

@@ -32,6 +32,8 @@ Uses
 //Var
 //  IPCError : longint;
 
+{$packrecords c}
+
 Type
 
    {$IFDEF FreeBSD}
@@ -76,6 +78,9 @@ Const
 
 type
   PIPC_Perm = ^TIPC_Perm;
+{$ifdef darwin}
+{$packrecords 4}
+{$endif}
 {$if defined(FreeBSD) or defined(Darwin)}
   TIPC_Perm = record
         cuid  : cushort;  { creator user id }
@@ -86,32 +91,48 @@ type
         seq   : cushort;  { sequence # (to generate unique msg/sem/shm id) }
         key   : key_t;    { user specified msg/sem/shm key }
   End;
+{$ifdef darwin}
+{$packrecords c}
+{$endif}
 {$else} // linux
-{$ifdef cpux86_64}
+
+{$ifdef cpu32}
+  {$ifndef linux_ipc64}
+    {$define linux_ipc32}
+  {$endif}
+{$endif}
+
+{$if not defined(linux_ipc32) and not defined(FPC_USE_LIBC)}
   TIPC_Perm = record
         key   : TKey;
-        uid   : uid_t;
-        gid   : gid_t;
-        cuid  : uid_t;
-        cgid  : gid_t;
-        mode  : mode_t;
-        __pad1    : cushort;
+        uid   : kernel_uid_t;
+        gid   : kernel_gid_t;
+        cuid  : kernel_uid_t;
+        cgid  : kernel_gid_t;
+        mode  : kernel_mode_t;
+{$if sizeof(kernel_mode_t) < 4}
+        __pad1    : array[1..4-sizeof(mode_t)];
+{$endif}
+{$ifdef cpupowerpc}
+        seq       : cuint;
+{$else}
         seq       : cushort;
+{$endif}
         __pad2    : cushort;
         __unused1 : culong;
         __unused2 : culong;
   End;
-{$else cpux86_64}  
+{$else not(linux_ipc32) and not(FPC_USE_LIBC)}
   TIPC_Perm = record
         key   : TKey;
-        uid   : uid_t;
-        gid   : gid_t;
-        cuid  : uid_t;
-        cgid  : gid_t;
-        mode  : mode_t;
+        uid   : kernel_uid_t;
+        gid   : kernel_gid_t;
+        cuid  : kernel_uid_t;
+        cgid  : kernel_gid_t;
+        mode  : kernel_mode_t;
         seq   : cushort;
   End;
-{$endif cpux86_64}
+{$endif not(linux_ipc32) and not(FPC_USE_LIBC)}
 {$endif}
 
 
@@ -140,6 +161,7 @@ Type
 {$endif}
 
 {$ifdef Darwin}
+{$packrecords 4}
   TShmid_ds = record
     shm_perm  : TIPC_Perm;
     shm_segsz : size_t;
@@ -151,6 +173,7 @@ Type
     shm_ctime : time_t;
     shm_internal : pointer;
   end;
+{$packrecords c}
 {$endif}
 
 {$ifdef Linux}
@@ -298,6 +321,7 @@ type
   end;
 {$else}
   {$ifdef Darwin}
+{$packrecords 4}
      PMSQid_ds = ^TMSQid_ds;
      TMSQid_ds = record
        msg_perm   : TIPC_perm;
@@ -316,6 +340,7 @@ type
        msg_pad3   : cint32;
        msg_pad4   : array [0..3] of cint32;
      end;
+{$packrecords c}
   {$else}
      PMSQid_ds = ^TMSQid_ds;
      TMSQid_ds = record
@@ -370,7 +395,7 @@ type
 
 Function msgget(key: TKey; msgflg:cint):cint; {$ifdef FPC_USE_LIBC} cdecl; external clib name 'msgget'; {$endif}
 Function msgsnd(msqid:cint; msgp: PMSGBuf; msgsz: size_t; msgflg:cint): cint; {$ifdef FPC_USE_LIBC} cdecl; external clib name 'msgsnd'; {$endif}
-Function msgrcv(msqid:cint; msgp: PMSGBuf; msgsz: size_t; msgtyp:cint; msgflg:cint): {$ifdef Darwin}ssize_t;{$else}cint;{$endif} {$ifdef FPC_USE_LIBC} cdecl; external clib name 'msgrcv'; {$endif}
+Function msgrcv(msqid:cint; msgp: PMSGBuf; msgsz: size_t; msgtyp:clong; msgflg:cint): {$ifdef Darwin}ssize_t;{$else}cint;{$endif} {$ifdef FPC_USE_LIBC} cdecl; external clib name 'msgrcv'; {$endif}
 Function msgctl(msqid:cint; cmd: cint; buf: PMSQid_ds): cint; {$ifdef FPC_USE_LIBC} cdecl; external clib name 'msgctl'; {$endif}
 
 { ----------------------------------------------------------------------
@@ -413,10 +438,24 @@ const
 
 type
 {$ifdef Linux}
+
+{$ifndef linux_ipc32}
+ PSEMid_ds = ^TSEMid_ds;
+ TSEMid_ds = record
+   sem_perm  : tipc_perm;
+   sem_otime : time_t;   // kernel
+   unused1   : culong;
+   sem_ctime : time_t;
+   unused2   : culong;
+   sem_nsems : culong;
+   unused3   : culong;
+   unused4   : culong;
+  end;
+{$else not linux_ipc32}
   PSEMid_ds = ^TSEMid_ds;
   TSEMid_ds = record
     sem_perm : tipc_perm;
-    sem_otime : time_t;
+    sem_otime : time_t;   // kernel
     sem_ctime : time_t;
     sem_base         : pointer;
     sem_pending      : pointer;
@@ -424,7 +463,8 @@ type
     undo             : pointer;
     sem_nsems : cushort;
   end;
-{$else}
+{$endif not linux_ipc32}
+{$else Linux}
    {$ifdef Darwin}
      PSEM = ^TSEM;
      TSEM = record
@@ -433,11 +473,11 @@ type
        semncnt : cushort;
        semzcnt : cushort;
      end;
-     
+{$packrecords 4}
      PSEMid_ds = ^TSEMid_ds;
      TSEMid_ds = record
              sem_perm : tipc_perm;
-             sem_base : PSEM;
+             sem_base : cint32;
              sem_nsems : cushort;
              sem_otime : time_t;
              sem_pad1 : cint32;
@@ -445,7 +485,7 @@ type
              sem_pad2 : cint32;
              sem_pad3 : array[0..3] of cint32;
           end;
-
+{$packrecords c}
    {$else}
      PSEM = ^TSEM;
      TSEM = record end; // opague
@@ -533,7 +573,7 @@ Function real_semctl(semid:cint; semnum:cint; cmd:cint): cint; {$ifdef FPC_USE_L
 
 Function semctl(semid:cint; semnum:cint; cmd:cint; var arg: tsemun): cint;
   begin
-    semctl := real_semctl(semid,semnum,cmd,pointer(@arg));
+    semctl := real_semctl(semid,semnum,cmd,pointer(arg));
   end;
 {$endif}