1 /* fhandler_procsysvipc.cc: fhandler for /proc/sysvipc virtual filesystem
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12 #include <sys/cygwin.h>
14 #include "cygserver.h"
18 #include "fhandler_virtual.h"
20 #include "shared_info.h"
26 #include <sys/param.h>
38 static off_t
format_procsysvipc_msg (void *, char *&);
39 static off_t
format_procsysvipc_sem (void *, char *&);
40 static off_t
format_procsysvipc_shm (void *, char *&);
42 static const virt_tab_t procsysvipc_tab
[] =
44 { _VN ("."), FH_PROCSYSVIPC
, virt_directory
, NULL
},
45 { _VN (".."), FH_PROCSYSVIPC
, virt_directory
, NULL
},
46 { _VN ("msg"), FH_PROCSYSVIPC
, virt_file
, format_procsysvipc_msg
},
47 { _VN ("sem"), FH_PROCSYSVIPC
, virt_file
, format_procsysvipc_sem
},
48 { _VN ("shm"), FH_PROCSYSVIPC
, virt_file
, format_procsysvipc_shm
},
49 { NULL
, 0, FH_NADA
, virt_none
, NULL
}
52 static const int PROCSYSVIPC_LINK_COUNT
=
53 (sizeof (procsysvipc_tab
) / sizeof (virt_tab_t
)) - 1;
56 fhandler_procsysvipc::exists ()
58 const char *path
= get_name ();
59 debug_printf ("exists (%s)", path
);
61 while (*path
!= 0 && !isdirsep (*path
))
69 virt_tab_t
*entry
= virt_tab_search (path
+ 1, true, procsysvipc_tab
,
70 PROCSYSVIPC_LINK_COUNT
);
76 if (entry
->type
== virt_file
)
78 if (cygserver_running
!= CYGSERVER_OK
)
81 fileid () = entry
- procsysvipc_tab
;
88 fhandler_procsysvipc::fhandler_procsysvipc ():
94 fhandler_procsysvipc::fstat (struct stat
*buf
)
96 fhandler_base::fstat (buf
);
97 buf
->st_mode
&= ~_IFMT
& NO_W
;
98 int file_type
= exists ();
106 buf
->st_mode
|= S_IFDIR
| S_IXUSR
| S_IXGRP
| S_IXOTH
;
111 buf
->st_mode
|= S_IFREG
| S_IRUSR
| S_IRGRP
| S_IROTH
;
117 fhandler_procsysvipc::readdir (DIR *dir
, dirent
*de
)
120 if (dir
->__d_position
>= PROCSYSVIPC_LINK_COUNT
)
124 if (cygserver_running
!= CYGSERVER_OK
)
127 strcpy (de
->d_name
, procsysvipc_tab
[dir
->__d_position
].name
);
128 de
->d_type
= virt_ftype_to_dtype (procsysvipc_tab
[dir
->__d_position
].type
);
130 dir
->__flags
|= dirent_saw_dot
| dirent_saw_dot_dot
;
133 syscall_printf ("%d = readdir(%p, %p) (%s)", res
, dir
, de
, de
->d_name
);
138 fhandler_procsysvipc::open (int flags
, mode_t mode
)
140 int res
= fhandler_virtual::open (flags
, mode
);
147 path
= get_name () + proc_len
+ 1;
149 while (*path
!= 0 && !isdirsep (*path
))
154 if ((flags
& (O_CREAT
| O_EXCL
)) == (O_CREAT
| O_EXCL
))
160 else if (flags
& O_WRONLY
)
174 entry
= virt_tab_search (path
+ 1, true, procsysvipc_tab
, PROCSYSVIPC_LINK_COUNT
);
177 set_errno ((flags
& O_CREAT
) ? EROFS
: ENOENT
);
181 if (flags
& O_WRONLY
)
188 fileid () = entry
- procsysvipc_tab
;
189 if (!fill_filebuf ())
195 if (flags
& O_APPEND
)
202 set_flags ((flags
& ~O_TEXT
) | O_BINARY
);
205 syscall_printf ("%d = fhandler_proc::open(%p, 0%o)", res
, flags
, mode
);
210 fhandler_procsysvipc::fill_filebuf ()
212 if (procsysvipc_tab
[fileid ()].format_func
)
214 filesize
= procsysvipc_tab
[fileid ()].format_func (NULL
, filebuf
);
220 #define MSG_HEADLINE " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n"
223 format_procsysvipc_msg (void *, char *&destbuf
)
226 struct msginfo msginfo
;
227 struct msqid_ds
*xmsqids
;
229 msgctl (0, IPC_INFO
, (struct msqid_ds
*) &msginfo
);
230 /* Don't use tmp_pathbuf. The required buffer sizes can be up to 128K! */
231 xmsqids
= (struct msqid_ds
*) malloc (sizeof (struct msqid_ds
)
235 /* buf size = sizeof headline + 128 bytes per msg queue entry. */
236 buf
= (char *) malloc (sizeof (MSG_HEADLINE
) + msginfo
.msgmni
* 128);
243 char *bufptr
= stpcpy (buf
, MSG_HEADLINE
);
244 msgctl (msginfo
.msgmni
, IPC_INFO
, (struct msqid_ds
*) xmsqids
);
245 for (int i
= 0; i
< msginfo
.msgmni
; i
++)
247 if (xmsqids
[i
].msg_qbytes
!= 0)
249 bufptr
+= sprintf (bufptr
,
250 "%10llu %10u %5o %11u %10u %5d %5d %5u %5u %5u %5u "
251 "%10ld %10ld %10ld\n",
252 xmsqids
[i
].msg_perm
.key
,
253 IXSEQ_TO_IPCID(i
, xmsqids
[i
].msg_perm
),
254 xmsqids
[i
].msg_perm
.mode
,
255 xmsqids
[i
].msg_cbytes
,
257 xmsqids
[i
].msg_lspid
,
258 xmsqids
[i
].msg_lrpid
,
259 (unsigned) xmsqids
[i
].msg_perm
.uid
,
260 (unsigned) xmsqids
[i
].msg_perm
.gid
,
261 (unsigned) xmsqids
[i
].msg_perm
.cuid
,
262 (unsigned) xmsqids
[i
].msg_perm
.cgid
,
263 xmsqids
[i
].msg_stime
,
264 xmsqids
[i
].msg_rtime
,
265 xmsqids
[i
].msg_ctime
);
269 off_t size
= bufptr
- buf
;
270 destbuf
= (char *) crealloc_abort (destbuf
, size
);
271 memcpy (destbuf
, buf
, size
);
279 #define SEM_HEADLINE " key semid perms nsems uid gid cuid cgid otime ctime\n"
282 format_procsysvipc_sem (void *, char *&destbuf
)
286 struct seminfo seminfo
;
287 struct semid_ds
*xsemids
;
289 semun
.buf
= (struct semid_ds
*) &seminfo
;
290 semctl (0, 0, IPC_INFO
, semun
);
291 /* Don't use tmp_pathbuf. The required buffer sizes can be up to 96K! */
292 xsemids
= (struct semid_ds
*) malloc (sizeof (struct semid_ds
)
296 /* buf size = sizeof headline + 96 bytes per semaphore entry. */
297 buf
= (char *) malloc (sizeof (SEM_HEADLINE
) + seminfo
.semmni
* 96);
304 char *bufptr
= stpcpy (buf
, SEM_HEADLINE
);
306 semctl (seminfo
.semmni
, 0, IPC_INFO
, semun
);
307 for (int i
= 0; i
< seminfo
.semmni
; i
++)
309 if ((xsemids
[i
].sem_perm
.mode
& SEM_ALLOC
) != 0)
311 bufptr
+= sprintf (bufptr
,
312 "%10llu %10u %5o %10d %5u %5u %5u %5u %10ld %10ld\n",
313 xsemids
[i
].sem_perm
.key
,
314 IXSEQ_TO_IPCID(i
, xsemids
[i
].sem_perm
),
315 xsemids
[i
].sem_perm
.mode
,
316 xsemids
[i
].sem_nsems
,
317 (unsigned) xsemids
[i
].sem_perm
.uid
,
318 (unsigned) xsemids
[i
].sem_perm
.gid
,
319 (unsigned) xsemids
[i
].sem_perm
.cuid
,
320 (unsigned) xsemids
[i
].sem_perm
.cgid
,
321 xsemids
[i
].sem_otime
,
322 xsemids
[i
].sem_ctime
);
326 off_t size
= bufptr
- buf
;
327 destbuf
= (char *) crealloc_abort (destbuf
, size
);
328 memcpy (destbuf
, buf
, size
);
336 #define SHM_HEADLINE " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n"
339 format_procsysvipc_shm (void *, char *&destbuf
)
342 struct shminfo shminfo
;
343 struct shmid_ds
*xshmids
;
345 shmctl (0, IPC_INFO
, (struct shmid_ds
*) &shminfo
);
346 /* Don't use tmp_pathbuf. The required buffer sizes can be up to 120K! */
347 xshmids
= (struct shmid_ds
*) malloc (sizeof (struct shmid_ds
)
351 /* buf size = sizeof headline + 120 bytes per shmem entry. */
352 buf
= (char *) malloc (sizeof (SHM_HEADLINE
) + shminfo
.shmmni
* 120);
359 char *bufptr
= stpcpy (buf
, SHM_HEADLINE
);
360 shmctl (shminfo
.shmmni
, IPC_INFO
, (struct shmid_ds
*) xshmids
);
361 for (int i
= 0; i
< shminfo
.shmmni
; i
++)
363 if (xshmids
[i
].shm_perm
.mode
& 0x0800)
365 bufptr
+= sprintf (bufptr
,
366 "%10llu %10u %5o %10u %5d %5d %6u %5u %5u %5u %5u "
367 "%10ld %10ld %10ld\n",
368 xshmids
[i
].shm_perm
.key
,
369 IXSEQ_TO_IPCID(i
, xshmids
[i
].shm_perm
),
370 xshmids
[i
].shm_perm
.mode
,
371 xshmids
[i
].shm_segsz
,
374 xshmids
[i
].shm_nattch
,
375 (unsigned) xshmids
[i
].shm_perm
.uid
,
376 (unsigned) xshmids
[i
].shm_perm
.gid
,
377 (unsigned) xshmids
[i
].shm_perm
.cuid
,
378 (unsigned) xshmids
[i
].shm_perm
.cgid
,
379 xshmids
[i
].shm_atime
,
380 xshmids
[i
].shm_dtime
,
381 xshmids
[i
].shm_ctime
);
385 off_t size
= bufptr
- buf
;
386 destbuf
= (char *) crealloc_abort (destbuf
, size
);
387 memcpy (destbuf
, buf
, size
);