-
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2012 Sami Kerola <kerolasa@iki.fi>
+ * Copyright (C) 2012-2023 Karel Zak <kzak@redhat.com>
+ */
#include <inttypes.h>
#include "c.h"
int ipc_msg_get_limits(struct ipc_limits *lim)
{
- if (path_exist(_PATH_PROC_IPC_MSGMNI) &&
- path_exist(_PATH_PROC_IPC_MSGMNB) &&
- path_exist(_PATH_PROC_IPC_MSGMAX)) {
+ memset(lim, 0, sizeof(*lim));
+
+ if (access(_PATH_PROC_IPC_MSGMNI, F_OK) == 0 &&
+ access(_PATH_PROC_IPC_MSGMNB, F_OK) == 0 &&
+ access(_PATH_PROC_IPC_MSGMAX, F_OK) == 0) {
- lim->msgmni = path_read_s32(_PATH_PROC_IPC_MSGMNI);
- lim->msgmnb = path_read_s32(_PATH_PROC_IPC_MSGMNB);
- lim->msgmax = path_read_s32(_PATH_PROC_IPC_MSGMAX);
+ if (ul_path_read_s32(NULL, &lim->msgmni, _PATH_PROC_IPC_MSGMNI) != 0)
+ return 1;
+ if (ul_path_read_s32(NULL, &lim->msgmnb, _PATH_PROC_IPC_MSGMNB) != 0)
+ return 1;
+ if (ul_path_read_u64(NULL, &lim->msgmax, _PATH_PROC_IPC_MSGMAX) != 0)
+ return 1;
} else {
struct msginfo msginfo;
lim->semvmx = SEMVMX;
- f = path_fopen("r", 0, _PATH_PROC_IPC_SEM);
+ f = fopen(_PATH_PROC_IPC_SEM, "r");
if (f) {
rc = fscanf(f, "%d\t%d\t%d\t%d",
&lim->semmsl, &lim->semmns, &lim->semopm, &lim->semmni);
fclose(f);
-
}
- if (rc == 4) {
- struct seminfo seminfo;
+ if (rc != 4) {
+ struct seminfo seminfo = { .semmni = 0 };
union semun arg = { .array = (ushort *) &seminfo };
if (semctl(0, 0, IPC_INFO, arg) < 0)
{
lim->shmmin = SHMMIN;
- if (path_exist(_PATH_PROC_IPC_SHMALL) &&
- path_exist(_PATH_PROC_IPC_SHMMAX) &&
- path_exist(_PATH_PROC_IPC_SHMMNI)) {
+ if (access(_PATH_PROC_IPC_SHMALL, F_OK) == 0 &&
+ access(_PATH_PROC_IPC_SHMMAX, F_OK) == 0 &&
+ access(_PATH_PROC_IPC_SHMMNI, F_OK) == 0) {
- lim->shmall = path_read_u64(_PATH_PROC_IPC_SHMALL);
- lim->shmmax = path_read_u64(_PATH_PROC_IPC_SHMMAX);
- lim->shmmni = path_read_u64(_PATH_PROC_IPC_SHMMNI);
+ ul_path_read_u64(NULL, &lim->shmall, _PATH_PROC_IPC_SHMALL);
+ ul_path_read_u64(NULL, &lim->shmmax, _PATH_PROC_IPC_SHMMAX);
+ ul_path_read_u64(NULL, &lim->shmmni, _PATH_PROC_IPC_SHMMNI);
} else {
- struct shminfo shminfo;
+ struct shminfo *shminfo;
+ struct shmid_ds shmbuf;
- if (shmctl(0, IPC_INFO, (struct shmid_ds *) &shminfo) < 0)
+ if (shmctl(0, IPC_INFO, &shmbuf) < 0)
return 1;
- lim->shmmni = shminfo.shmmni;
- lim->shmall = shminfo.shmall;
+ shminfo = (struct shminfo *) &shmbuf;
+ lim->shmmni = shminfo->shmmni;
+ lim->shmall = shminfo->shmall;
+ lim->shmmax = shminfo->shmmax;
}
return 0;
int ipc_shm_get_info(int id, struct shm_data **shmds)
{
FILE *f;
- int i = 0, maxid;
+ int i = 0, maxid, j;
+ char buf[BUFSIZ];
struct shm_data *p;
struct shmid_ds dummy;
p = *shmds = xcalloc(1, sizeof(struct shm_data));
p->next = NULL;
- f = path_fopen("r", 0, _PATH_PROC_SYSV_SHM);
+ f = fopen(_PATH_PROC_SYSV_SHM, "r");
if (!f)
goto shm_fallback;
while (fgetc(f) != '\n'); /* skip header */
- while (feof(f) == 0) {
- if (fscanf(f,
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ /* scan for the first 14-16 columns (e.g. Linux 2.6.32 has 14) */
+ p->shm_rss = 0xdead;
+ p->shm_swp = 0xdead;
+ if (sscanf(buf,
"%d %d %o %"SCNu64 " %u %u "
"%"SCNu64 " %u %u %u %u %"SCNi64 " %"SCNi64 " %"SCNi64
" %"SCNu64 " %"SCNu64 "\n",
&p->shm_dtim,
&p->shm_ctim,
&p->shm_rss,
- &p->shm_swp) != 16)
- continue;
+ &p->shm_swp) < 14)
+ continue; /* invalid line, skipped */
if (id > -1) {
/* ID specified */
if (id == p->shm_perm.id) {
i = 1;
break;
- } else
- continue;
+ }
+ continue;
}
p->next = xcalloc(1, sizeof(struct shm_data));
shm_fallback:
maxid = shmctl(0, SHM_INFO, &dummy);
- for (int j = 0; j <= maxid; j++) {
+ for (j = 0; j <= maxid; j++) {
int shmid;
struct shmid_ds shmseg;
struct ipc_perm *ipcp = &shmseg.shm_perm;
{
size_t i;
- if (!p || !p->sem_nsems || p->sem_perm.id < 0)
+ if (!p || !p->sem_nsems || p->sem_nsems > SIZE_MAX || p->sem_perm.id < 0)
return;
p->elements = xcalloc(p->sem_nsems, sizeof(struct sem_elem));
int ipc_sem_get_info(int id, struct sem_data **semds)
{
FILE *f;
- int i = 0, maxid;
+ int i = 0, maxid, j;
struct sem_data *p;
struct seminfo dummy;
union semun arg;
p = *semds = xcalloc(1, sizeof(struct sem_data));
p->next = NULL;
- f = path_fopen("r", 0, _PATH_PROC_SYSV_SEM);
+ f = fopen(_PATH_PROC_SYSV_SEM, "r");
if (!f)
goto sem_fallback;
get_sem_elements(p);
i = 1;
break;
- } else
- continue;
+ }
+ continue;
}
p->next = xcalloc(1, sizeof(struct sem_data));
arg.array = (ushort *) (void *)&dummy;
maxid = semctl(0, 0, SEM_INFO, arg);
- for (int j = 0; j <= maxid; j++) {
+ for (j = 0; j <= maxid; j++) {
int semid;
struct semid_ds semseg;
struct ipc_perm *ipcp = &semseg.sem_perm;
int ipc_msg_get_info(int id, struct msg_data **msgds)
{
FILE *f;
- int i = 0, maxid;
+ int i = 0, maxid, j;
struct msg_data *p;
struct msqid_ds dummy;
struct msqid_ds msgseg;
p = *msgds = xcalloc(1, sizeof(struct msg_data));
p->next = NULL;
- f = path_fopen("r", 0, _PATH_PROC_SYSV_MSG);
+ f = fopen(_PATH_PROC_SYSV_MSG, "r");
if (!f)
goto msg_fallback;
if (id > -1) {
/* ID specified */
if (id == p->msg_perm.id) {
- /*
- * FIXME: q_qbytes are not in /proc
- *
- */
if (msgctl(id, IPC_STAT, &msgseg) != -1)
p->q_qbytes = msgseg.msg_qbytes;
i = 1;
break;
- } else
- continue;
+ }
+ continue;
}
p->next = xcalloc(1, sizeof(struct msg_data));
msg_fallback:
maxid = msgctl(0, MSG_INFO, &dummy);
- for (int j = 0; j <= maxid; j++) {
+ for (j = 0; j <= maxid; j++) {
int msgid;
struct ipc_perm *ipcp = &msgseg.msg_perm;
switch (unit) {
case IPC_UNIT_DEFAULT:
case IPC_UNIT_BYTES:
- sprintf(format, "%%%dju", width);
+ snprintf(format, sizeof(format), "%%%dju", width);
printf(format, size);
break;
case IPC_UNIT_KB:
- sprintf(format, "%%%dju", width);
+ snprintf(format, sizeof(format), "%%%dju", width);
printf(format, size / 1024);
break;
case IPC_UNIT_HUMAN:
- sprintf(format, "%%%ds", width);
- printf(format, size_to_human_string(SIZE_SUFFIX_1LETTER, size));
+ {
+ char *tmp;
+ snprintf(format, sizeof(format), "%%%ds", width);
+ printf(format, (tmp = size_to_human_string(SIZE_SUFFIX_1LETTER, size)));
+ free(tmp);
break;
+ }
default:
/* impossible occurred */
abort();