Fork me on GitHub

root/kernel/syscalls/msgctl.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_msgctl

   1 /*
   2  * fiwix/kernel/syscalls/msgctl.c
   3  *
   4  * Copyright 2022, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/config.h>
   9 #include <fiwix/kernel.h>
  10 #include <fiwix/types.h>
  11 #include <fiwix/string.h>
  12 #include <fiwix/process.h>
  13 #include <fiwix/sched.h>
  14 #include <fiwix/errno.h>
  15 #include <fiwix/ipc.h>
  16 #include <fiwix/msg.h>
  17 
  18 #ifdef __DEBUG__
  19 #include <fiwix/stdio.h>
  20 #include <fiwix/process.h>
  21 #endif /*__DEBUG__ */
  22 
  23 #ifdef CONFIG_SYSVIPC
  24 int sys_msgctl(int msqid, int cmd, struct msqid_ds *buf)
  25 {
  26         struct msqid_ds *mq;
  27         struct msginfo *mi;
  28         struct ipc_perm *perm;
  29         struct msg *m, *mn;
  30         int errno;
  31 
  32 #ifdef __DEBUG__
  33         printk("(pid %d) sys_msgctl(%d, %d, 0x%x)\n", current->pid, msqid, cmd, (int)buf);
  34 #endif /*__DEBUG__ */
  35 
  36         if(msqid < 0) {
  37                 return -EINVAL;
  38         }
  39 
  40         switch(cmd) {   
  41                 case MSG_STAT:
  42                 case IPC_STAT:
  43                         if((errno = check_user_area(VERIFY_WRITE, buf, sizeof(struct msqid_ds)))) {
  44                                 return errno;
  45                         }
  46                         mq = msgque[msqid % MSGMNI];
  47                         if(mq == IPC_UNUSED) {
  48                                 return -EINVAL;
  49                         }
  50                         if(!ipc_has_perms(&mq->msg_perm, IPC_R)) {
  51                                 return -EACCES;
  52                         }
  53                         memcpy_b(buf, mq, sizeof(struct msqid_ds));
  54                         if(cmd == MSG_STAT) {
  55                                 return (mq->msg_perm.seq * MSGMNI) + msqid;
  56                         }
  57                         return 0;
  58 
  59                 case IPC_SET:
  60                         if((errno = check_user_area(VERIFY_READ, buf, sizeof(struct msqid_ds)))) {
  61                                 return errno;
  62                         }
  63                         mq = msgque[msqid % MSGMNI];
  64                         if(mq == IPC_UNUSED) {
  65                                 return -EINVAL;
  66                         }
  67                         perm = &mq->msg_perm;
  68                         if(!IS_SUPERUSER && current->euid != perm->uid && current->euid != perm->cuid) {
  69                                 return -EPERM;
  70                         }
  71                         if(!IS_SUPERUSER && buf->msg_qbytes > MSGMNB) {
  72                                 return -EPERM;
  73                         }
  74                         mq->msg_qbytes = buf->msg_qbytes;
  75                         perm->uid = buf->msg_perm.uid;
  76                         perm->gid = buf->msg_perm.gid;
  77                         perm->mode = (perm->mode & ~0777) | (buf->msg_perm.mode & 0777);
  78                         mq->msg_ctime = CURRENT_TIME;
  79                         return 0;
  80 
  81                 case IPC_RMID:
  82                         mq = msgque[msqid % MSGMNI];
  83                         if(mq == IPC_UNUSED) {
  84                                 return -EINVAL;
  85                         }
  86                         perm = &mq->msg_perm;
  87                         if(!IS_SUPERUSER && current->euid != perm->uid && current->euid != perm->cuid) {
  88                                 return -EPERM;
  89                         }
  90                         if((m = mq->msg_first)) {
  91                                 do {
  92                                         mq->msg_qnum--;
  93                                         mq->msg_cbytes -= m->msg_ts;
  94                                         num_msgs--;
  95                                         mn = m->msg_next;
  96                                         msg_release_md(m);
  97                                         m = mn;
  98                                 } while(m);
  99                         }
 100                         msg_release_mq(mq);
 101                         msgque[msqid % MSGMNI] = (struct msqid_ds *)IPC_UNUSED;
 102                         num_queues--;
 103                         msg_seq++;
 104                         if((msqid % MSGMNI) == max_mqid) {
 105                                 while(max_mqid) {
 106                                         if(msgque[max_mqid] != IPC_UNUSED) {
 107                                                 break;
 108                                         }
 109                                         max_mqid--;
 110                                 }
 111                         }
 112                         wakeup(mq);
 113                         return 0;
 114 
 115                 case MSG_INFO:
 116                 case IPC_INFO:
 117                         if((errno = check_user_area(VERIFY_WRITE, buf, sizeof(struct msqid_ds)))) {
 118                                 return errno;
 119                         }
 120                         mi = (struct msginfo *)buf;
 121                         if(cmd == MSG_INFO) {
 122                                 mi->msgpool = num_queues;
 123                                 mi->msgmap = num_msgs;
 124                                 mi->msgssz = 0;         /* FIXME: pending to do */
 125                                 mi->msgtql = 0;         /* FIXME: pending to do */
 126                                 mi->msgseg = 0;         /* FIXME: pending to do */
 127                         } else {
 128                                 mi->msgpool = 0;        /* FIXME: pending to do */
 129                                 mi->msgmap = 0;         /* FIXME: pending to do */
 130                                 mi->msgssz = 0;         /* FIXME: pending to do */
 131                                 mi->msgtql = MSGTQL;
 132                                 mi->msgseg = 0;         /* FIXME: pending to do */
 133                         }
 134                         mi->msgmax = MSGMAX;
 135                         mi->msgmnb = MSGMNB;
 136                         mi->msgmni = MSGMNI;
 137                         return max_mqid;
 138         }
 139 
 140         return -EINVAL;
 141 }
 142 #endif /* CONFIG_SYSVIPC */

/* [previous][next][first][last][top][bottom][index][help] */