]>
Commit | Line | Data |
---|---|---|
9abd5e4b KZ |
1 | /* |
2 | * SPDX-License-Identifier: GPL-2.0-or-later | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * Copyright (C) 2012 Sami Kerola <kerolasa@iki.fi> | |
10 | * Copyright (C) 2012-2023 Karel Zak <kzak@redhat.com> | |
11 | */ | |
058e8154 SK |
12 | #include <inttypes.h> |
13 | ||
e5995acd | 14 | #include "c.h" |
b5504a3d | 15 | #include "nls.h" |
058e8154 | 16 | #include "xalloc.h" |
e5995acd SK |
17 | #include "path.h" |
18 | #include "pathnames.h" | |
19 | #include "ipcutils.h" | |
56692a67 | 20 | #include "strutils.h" |
e5995acd SK |
21 | |
22 | #ifndef SEMVMX | |
23 | # define SEMVMX 32767 /* <= 32767 semaphore maximum value */ | |
24 | #endif | |
25 | #ifndef SHMMIN | |
26 | # define SHMMIN 1 /* min shared segment size in bytes */ | |
27 | #endif | |
28 | ||
29 | ||
30 | int ipc_msg_get_limits(struct ipc_limits *lim) | |
31 | { | |
970ed62e TW |
32 | memset(lim, 0, sizeof(*lim)); |
33 | ||
77845f7b RM |
34 | if (access(_PATH_PROC_IPC_MSGMNI, F_OK) == 0 && |
35 | access(_PATH_PROC_IPC_MSGMNB, F_OK) == 0 && | |
36 | access(_PATH_PROC_IPC_MSGMAX, F_OK) == 0) { | |
e5995acd | 37 | |
e4c6816c KZ |
38 | if (ul_path_read_s32(NULL, &lim->msgmni, _PATH_PROC_IPC_MSGMNI) != 0) |
39 | return 1; | |
40 | if (ul_path_read_s32(NULL, &lim->msgmnb, _PATH_PROC_IPC_MSGMNB) != 0) | |
41 | return 1; | |
42 | if (ul_path_read_u64(NULL, &lim->msgmax, _PATH_PROC_IPC_MSGMAX) != 0) | |
43 | return 1; | |
e5995acd SK |
44 | } else { |
45 | struct msginfo msginfo; | |
46 | ||
47 | if (msgctl(0, IPC_INFO, (struct msqid_ds *) &msginfo) < 0) | |
48 | return 1; | |
49 | lim->msgmni = msginfo.msgmni; | |
50 | lim->msgmnb = msginfo.msgmnb; | |
51 | lim->msgmax = msginfo.msgmax; | |
52 | } | |
53 | ||
54 | return 0; | |
55 | } | |
56 | ||
57 | int ipc_sem_get_limits(struct ipc_limits *lim) | |
58 | { | |
59 | FILE *f; | |
60 | int rc = 0; | |
61 | ||
62 | lim->semvmx = SEMVMX; | |
63 | ||
f09a98de | 64 | f = fopen(_PATH_PROC_IPC_SEM, "r"); |
e5995acd SK |
65 | if (f) { |
66 | rc = fscanf(f, "%d\t%d\t%d\t%d", | |
67 | &lim->semmsl, &lim->semmns, &lim->semopm, &lim->semmni); | |
68 | fclose(f); | |
e5995acd SK |
69 | } |
70 | ||
53650755 | 71 | if (rc != 4) { |
60ee341b | 72 | struct seminfo seminfo = { .semmni = 0 }; |
e5995acd SK |
73 | union semun arg = { .array = (ushort *) &seminfo }; |
74 | ||
75 | if (semctl(0, 0, IPC_INFO, arg) < 0) | |
76 | return 1; | |
77 | lim->semmni = seminfo.semmni; | |
78 | lim->semmsl = seminfo.semmsl; | |
79 | lim->semmns = seminfo.semmns; | |
80 | lim->semopm = seminfo.semopm; | |
81 | } | |
82 | ||
83 | return 0; | |
84 | } | |
85 | ||
86 | int ipc_shm_get_limits(struct ipc_limits *lim) | |
87 | { | |
88 | lim->shmmin = SHMMIN; | |
89 | ||
77845f7b RM |
90 | if (access(_PATH_PROC_IPC_SHMALL, F_OK) == 0 && |
91 | access(_PATH_PROC_IPC_SHMMAX, F_OK) == 0 && | |
92 | access(_PATH_PROC_IPC_SHMMNI, F_OK) == 0) { | |
e5995acd | 93 | |
f09a98de KZ |
94 | ul_path_read_u64(NULL, &lim->shmall, _PATH_PROC_IPC_SHMALL); |
95 | ul_path_read_u64(NULL, &lim->shmmax, _PATH_PROC_IPC_SHMMAX); | |
96 | ul_path_read_u64(NULL, &lim->shmmni, _PATH_PROC_IPC_SHMMNI); | |
e5995acd SK |
97 | |
98 | } else { | |
929c2575 KZ |
99 | struct shminfo *shminfo; |
100 | struct shmid_ds shmbuf; | |
e5995acd | 101 | |
929c2575 | 102 | if (shmctl(0, IPC_INFO, &shmbuf) < 0) |
e5995acd | 103 | return 1; |
929c2575 KZ |
104 | shminfo = (struct shminfo *) &shmbuf; |
105 | lim->shmmni = shminfo->shmmni; | |
106 | lim->shmall = shminfo->shmall; | |
107 | lim->shmmax = shminfo->shmmax; | |
e5995acd SK |
108 | } |
109 | ||
110 | return 0; | |
111 | } | |
058e8154 | 112 | |
61e14b4a | 113 | int ipc_shm_get_info(int id, struct shm_data **shmds) |
058e8154 SK |
114 | { |
115 | FILE *f; | |
31862cde | 116 | int i = 0, maxid, j; |
97fab80e | 117 | char buf[BUFSIZ]; |
058e8154 | 118 | struct shm_data *p; |
3ce29d6d | 119 | struct shmid_ds dummy; |
058e8154 | 120 | |
7d94d1ce | 121 | p = *shmds = xcalloc(1, sizeof(struct shm_data)); |
058e8154 SK |
122 | p->next = NULL; |
123 | ||
f09a98de | 124 | f = fopen(_PATH_PROC_SYSV_SHM, "r"); |
058e8154 | 125 | if (!f) |
9bcacde1 | 126 | goto shm_fallback; |
058e8154 SK |
127 | |
128 | while (fgetc(f) != '\n'); /* skip header */ | |
129 | ||
97fab80e | 130 | while (fgets(buf, sizeof(buf), f) != NULL) { |
73f4f3d9 RM |
131 | /* scan for the first 14-16 columns (e.g. Linux 2.6.32 has 14) */ |
132 | p->shm_rss = 0xdead; | |
133 | p->shm_swp = 0xdead; | |
97fab80e | 134 | if (sscanf(buf, |
058e8154 | 135 | "%d %d %o %"SCNu64 " %u %u " |
278e7203 | 136 | "%"SCNu64 " %u %u %u %u %"SCNi64 " %"SCNi64 " %"SCNi64 |
058e8154 SK |
137 | " %"SCNu64 " %"SCNu64 "\n", |
138 | &p->shm_perm.key, | |
139 | &p->shm_perm.id, | |
140 | &p->shm_perm.mode, | |
141 | &p->shm_segsz, | |
142 | &p->shm_cprid, | |
143 | &p->shm_lprid, | |
144 | &p->shm_nattch, | |
145 | &p->shm_perm.uid, | |
146 | &p->shm_perm.gid, | |
147 | &p->shm_perm.cuid, | |
148 | &p->shm_perm.cgid, | |
149 | &p->shm_atim, | |
150 | &p->shm_dtim, | |
151 | &p->shm_ctim, | |
152 | &p->shm_rss, | |
73f4f3d9 | 153 | &p->shm_swp) < 14) |
9e930041 | 154 | continue; /* invalid line, skipped */ |
058e8154 | 155 | |
7d94d1ce KZ |
156 | if (id > -1) { |
157 | /* ID specified */ | |
158 | if (id == p->shm_perm.id) { | |
159 | i = 1; | |
160 | break; | |
042f62df RP |
161 | } |
162 | continue; | |
058e8154 | 163 | } |
7d94d1ce KZ |
164 | |
165 | p->next = xcalloc(1, sizeof(struct shm_data)); | |
166 | p = p->next; | |
167 | p->next = NULL; | |
168 | i++; | |
058e8154 SK |
169 | } |
170 | ||
171 | if (i == 0) | |
172 | free(*shmds); | |
173 | fclose(f); | |
174 | return i; | |
175 | ||
176 | /* Fallback; /proc or /sys file(s) missing. */ | |
9bcacde1 | 177 | shm_fallback: |
3ce29d6d | 178 | maxid = shmctl(0, SHM_INFO, &dummy); |
61e14b4a | 179 | |
31862cde | 180 | for (j = 0; j <= maxid; j++) { |
058e8154 SK |
181 | int shmid; |
182 | struct shmid_ds shmseg; | |
183 | struct ipc_perm *ipcp = &shmseg.shm_perm; | |
184 | ||
b507e426 RM |
185 | shmid = shmctl(j, SHM_STAT, &shmseg); |
186 | if (shmid < 0 || (id > -1 && shmid != id)) { | |
058e8154 SK |
187 | continue; |
188 | } | |
189 | ||
b507e426 | 190 | i++; |
058e8154 SK |
191 | p->shm_perm.key = ipcp->KEY; |
192 | p->shm_perm.id = shmid; | |
193 | p->shm_perm.mode = ipcp->mode; | |
194 | p->shm_segsz = shmseg.shm_segsz; | |
195 | p->shm_cprid = shmseg.shm_cpid; | |
196 | p->shm_lprid = shmseg.shm_lpid; | |
197 | p->shm_nattch = shmseg.shm_nattch; | |
198 | p->shm_perm.uid = ipcp->uid; | |
199 | p->shm_perm.gid = ipcp->gid; | |
200 | p->shm_perm.cuid = ipcp->cuid; | |
201 | p->shm_perm.cgid = ipcp->cuid; | |
202 | p->shm_atim = shmseg.shm_atime; | |
203 | p->shm_dtim = shmseg.shm_dtime; | |
204 | p->shm_ctim = shmseg.shm_ctime; | |
205 | p->shm_rss = 0xdead; | |
206 | p->shm_swp = 0xdead; | |
207 | ||
208 | if (id < 0) { | |
7d94d1ce | 209 | p->next = xcalloc(1, sizeof(struct shm_data)); |
058e8154 SK |
210 | p = p->next; |
211 | p->next = NULL; | |
058e8154 | 212 | } else |
b507e426 | 213 | break; |
058e8154 SK |
214 | } |
215 | ||
b507e426 RM |
216 | if (i == 0) |
217 | free(*shmds); | |
058e8154 SK |
218 | return i; |
219 | } | |
220 | ||
221 | void ipc_shm_free_info(struct shm_data *shmds) | |
222 | { | |
223 | while (shmds) { | |
224 | struct shm_data *next = shmds->next; | |
225 | free(shmds); | |
226 | shmds = next; | |
227 | } | |
228 | } | |
229 | ||
b5504a3d SK |
230 | static void get_sem_elements(struct sem_data *p) |
231 | { | |
232 | size_t i; | |
233 | ||
1c9143d0 | 234 | if (!p || !p->sem_nsems || p->sem_nsems > SIZE_MAX || p->sem_perm.id < 0) |
b5504a3d SK |
235 | return; |
236 | ||
237 | p->elements = xcalloc(p->sem_nsems, sizeof(struct sem_elem)); | |
238 | ||
239 | for (i = 0; i < p->sem_nsems; i++) { | |
240 | struct sem_elem *e = &p->elements[i]; | |
241 | union semun arg = { .val = 0 }; | |
242 | ||
243 | e->semval = semctl(p->sem_perm.id, i, GETVAL, arg); | |
244 | if (e->semval < 0) | |
245 | err(EXIT_FAILURE, _("%s failed"), "semctl(GETVAL)"); | |
246 | ||
247 | e->ncount = semctl(p->sem_perm.id, i, GETNCNT, arg); | |
248 | if (e->ncount < 0) | |
249 | err(EXIT_FAILURE, _("%s failed"), "semctl(GETNCNT)"); | |
250 | ||
251 | e->zcount = semctl(p->sem_perm.id, i, GETZCNT, arg); | |
252 | if (e->zcount < 0) | |
253 | err(EXIT_FAILURE, _("%s failed"), "semctl(GETZCNT)"); | |
254 | ||
255 | e->pid = semctl(p->sem_perm.id, i, GETPID, arg); | |
256 | if (e->pid < 0) | |
257 | err(EXIT_FAILURE, _("%s failed"), "semctl(GETPID)"); | |
258 | } | |
259 | } | |
260 | ||
1e2418a2 SK |
261 | int ipc_sem_get_info(int id, struct sem_data **semds) |
262 | { | |
263 | FILE *f; | |
31862cde | 264 | int i = 0, maxid, j; |
1e2418a2 SK |
265 | struct sem_data *p; |
266 | struct seminfo dummy; | |
267 | union semun arg; | |
268 | ||
269 | p = *semds = xcalloc(1, sizeof(struct sem_data)); | |
270 | p->next = NULL; | |
271 | ||
f09a98de | 272 | f = fopen(_PATH_PROC_SYSV_SEM, "r"); |
1e2418a2 SK |
273 | if (!f) |
274 | goto sem_fallback; | |
275 | ||
276 | while (fgetc(f) != '\n') ; /* skip header */ | |
277 | ||
278 | while (feof(f) == 0) { | |
279 | if (fscanf(f, | |
278e7203 KZ |
280 | "%d %d %o %" SCNu64 " %u %u %u %u %" |
281 | SCNi64 " %" SCNi64 "\n", | |
1e2418a2 SK |
282 | &p->sem_perm.key, |
283 | &p->sem_perm.id, | |
284 | &p->sem_perm.mode, | |
285 | &p->sem_nsems, | |
286 | &p->sem_perm.uid, | |
287 | &p->sem_perm.gid, | |
288 | &p->sem_perm.cuid, | |
289 | &p->sem_perm.cgid, | |
290 | &p->sem_otime, | |
291 | &p->sem_ctime) != 10) | |
292 | continue; | |
293 | ||
294 | if (id > -1) { | |
295 | /* ID specified */ | |
296 | if (id == p->sem_perm.id) { | |
b5504a3d | 297 | get_sem_elements(p); |
1e2418a2 SK |
298 | i = 1; |
299 | break; | |
042f62df RP |
300 | } |
301 | continue; | |
1e2418a2 SK |
302 | } |
303 | ||
304 | p->next = xcalloc(1, sizeof(struct sem_data)); | |
305 | p = p->next; | |
306 | p->next = NULL; | |
307 | i++; | |
308 | } | |
309 | ||
310 | if (i == 0) | |
311 | free(*semds); | |
312 | fclose(f); | |
313 | return i; | |
314 | ||
315 | /* Fallback; /proc or /sys file(s) missing. */ | |
9bcacde1 | 316 | sem_fallback: |
1e2418a2 SK |
317 | arg.array = (ushort *) (void *)&dummy; |
318 | maxid = semctl(0, 0, SEM_INFO, arg); | |
1e2418a2 | 319 | |
31862cde | 320 | for (j = 0; j <= maxid; j++) { |
1e2418a2 SK |
321 | int semid; |
322 | struct semid_ds semseg; | |
323 | struct ipc_perm *ipcp = &semseg.sem_perm; | |
324 | arg.buf = (struct semid_ds *)&semseg; | |
325 | ||
5078a0d3 RM |
326 | semid = semctl(j, 0, SEM_STAT, arg); |
327 | if (semid < 0 || (id > -1 && semid != id)) { | |
1e2418a2 SK |
328 | continue; |
329 | } | |
330 | ||
5078a0d3 | 331 | i++; |
1e2418a2 SK |
332 | p->sem_perm.key = ipcp->KEY; |
333 | p->sem_perm.id = semid; | |
334 | p->sem_perm.mode = ipcp->mode; | |
335 | p->sem_nsems = semseg.sem_nsems; | |
336 | p->sem_perm.uid = ipcp->uid; | |
337 | p->sem_perm.gid = ipcp->gid; | |
338 | p->sem_perm.cuid = ipcp->cuid; | |
339 | p->sem_perm.cgid = ipcp->cuid; | |
340 | p->sem_otime = semseg.sem_otime; | |
341 | p->sem_ctime = semseg.sem_ctime; | |
342 | ||
343 | if (id < 0) { | |
344 | p->next = xcalloc(1, sizeof(struct sem_data)); | |
345 | p = p->next; | |
346 | p->next = NULL; | |
347 | i++; | |
b5504a3d SK |
348 | } else { |
349 | get_sem_elements(p); | |
5078a0d3 | 350 | break; |
b5504a3d | 351 | } |
1e2418a2 SK |
352 | } |
353 | ||
5078a0d3 RM |
354 | if (i == 0) |
355 | free(*semds); | |
1e2418a2 SK |
356 | return i; |
357 | } | |
358 | ||
359 | void ipc_sem_free_info(struct sem_data *semds) | |
360 | { | |
361 | while (semds) { | |
362 | struct sem_data *next = semds->next; | |
b5504a3d | 363 | free(semds->elements); |
1e2418a2 SK |
364 | free(semds); |
365 | semds = next; | |
366 | } | |
367 | } | |
368 | ||
35118dfc SK |
369 | int ipc_msg_get_info(int id, struct msg_data **msgds) |
370 | { | |
371 | FILE *f; | |
31862cde | 372 | int i = 0, maxid, j; |
35118dfc SK |
373 | struct msg_data *p; |
374 | struct msqid_ds dummy; | |
2bd2f79d | 375 | struct msqid_ds msgseg; |
35118dfc SK |
376 | |
377 | p = *msgds = xcalloc(1, sizeof(struct msg_data)); | |
378 | p->next = NULL; | |
379 | ||
f09a98de | 380 | f = fopen(_PATH_PROC_SYSV_MSG, "r"); |
35118dfc SK |
381 | if (!f) |
382 | goto msg_fallback; | |
383 | ||
384 | while (fgetc(f) != '\n') ; /* skip header */ | |
385 | ||
386 | while (feof(f) == 0) { | |
387 | if (fscanf(f, | |
278e7203 KZ |
388 | "%d %d %o %" SCNu64 " %" SCNu64 |
389 | " %u %u %u %u %u %u %" SCNi64 " %" SCNi64 " %" SCNi64 "\n", | |
35118dfc SK |
390 | &p->msg_perm.key, |
391 | &p->msg_perm.id, | |
392 | &p->msg_perm.mode, | |
393 | &p->q_cbytes, | |
394 | &p->q_qnum, | |
395 | &p->q_lspid, | |
396 | &p->q_lrpid, | |
397 | &p->msg_perm.uid, | |
398 | &p->msg_perm.gid, | |
399 | &p->msg_perm.cuid, | |
400 | &p->msg_perm.cgid, | |
401 | &p->q_stime, | |
402 | &p->q_rtime, | |
403 | &p->q_ctime) != 14) | |
404 | continue; | |
405 | ||
406 | if (id > -1) { | |
407 | /* ID specified */ | |
408 | if (id == p->msg_perm.id) { | |
2bd2f79d SK |
409 | if (msgctl(id, IPC_STAT, &msgseg) != -1) |
410 | p->q_qbytes = msgseg.msg_qbytes; | |
35118dfc SK |
411 | i = 1; |
412 | break; | |
042f62df RP |
413 | } |
414 | continue; | |
35118dfc SK |
415 | } |
416 | ||
417 | p->next = xcalloc(1, sizeof(struct msg_data)); | |
418 | p = p->next; | |
419 | p->next = NULL; | |
420 | i++; | |
421 | } | |
422 | ||
423 | if (i == 0) | |
424 | free(*msgds); | |
425 | fclose(f); | |
426 | return i; | |
427 | ||
428 | /* Fallback; /proc or /sys file(s) missing. */ | |
9bcacde1 | 429 | msg_fallback: |
08e7d10b | 430 | maxid = msgctl(0, MSG_INFO, &dummy); |
35118dfc | 431 | |
31862cde | 432 | for (j = 0; j <= maxid; j++) { |
35118dfc | 433 | int msgid; |
35118dfc SK |
434 | struct ipc_perm *ipcp = &msgseg.msg_perm; |
435 | ||
08e7d10b RM |
436 | msgid = msgctl(j, MSG_STAT, &msgseg); |
437 | if (msgid < 0 || (id > -1 && msgid != id)) { | |
35118dfc SK |
438 | continue; |
439 | } | |
440 | ||
08e7d10b | 441 | i++; |
35118dfc SK |
442 | p->msg_perm.key = ipcp->KEY; |
443 | p->msg_perm.id = msgid; | |
444 | p->msg_perm.mode = ipcp->mode; | |
445 | p->q_cbytes = msgseg.msg_cbytes; | |
446 | p->q_qnum = msgseg.msg_qnum; | |
447 | p->q_lspid = msgseg.msg_lspid; | |
448 | p->q_lrpid = msgseg.msg_lrpid; | |
449 | p->msg_perm.uid = ipcp->uid; | |
450 | p->msg_perm.gid = ipcp->gid; | |
451 | p->msg_perm.cuid = ipcp->cuid; | |
452 | p->msg_perm.cgid = ipcp->cgid; | |
453 | p->q_stime = msgseg.msg_stime; | |
454 | p->q_rtime = msgseg.msg_rtime; | |
455 | p->q_ctime = msgseg.msg_ctime; | |
2bd2f79d | 456 | p->q_qbytes = msgseg.msg_qbytes; |
35118dfc SK |
457 | |
458 | if (id < 0) { | |
459 | p->next = xcalloc(1, sizeof(struct msg_data)); | |
460 | p = p->next; | |
461 | p->next = NULL; | |
35118dfc | 462 | } else |
08e7d10b | 463 | break; |
35118dfc SK |
464 | } |
465 | ||
08e7d10b RM |
466 | if (i == 0) |
467 | free(*msgds); | |
35118dfc SK |
468 | return i; |
469 | } | |
470 | ||
471 | void ipc_msg_free_info(struct msg_data *msgds) | |
472 | { | |
473 | while (msgds) { | |
474 | struct msg_data *next = msgds->next; | |
475 | free(msgds); | |
476 | msgds = next; | |
477 | } | |
478 | } | |
479 | ||
058e8154 SK |
480 | void ipc_print_perms(FILE *f, struct ipc_stat *is) |
481 | { | |
482 | struct passwd *pw; | |
483 | struct group *gr; | |
484 | ||
485 | fprintf(f, "%-10d %-10o", is->id, is->mode & 0777); | |
486 | ||
487 | if ((pw = getpwuid(is->cuid))) | |
488 | fprintf(f, " %-10s", pw->pw_name); | |
489 | else | |
490 | fprintf(f, " %-10u", is->cuid); | |
491 | ||
492 | if ((gr = getgrgid(is->cgid))) | |
493 | fprintf(f, " %-10s", gr->gr_name); | |
494 | else | |
495 | fprintf(f, " %-10u", is->cgid); | |
496 | ||
497 | if ((pw = getpwuid(is->uid))) | |
498 | fprintf(f, " %-10s", pw->pw_name); | |
499 | else | |
500 | fprintf(f, " %-10u", is->uid); | |
501 | ||
502 | if ((gr = getgrgid(is->gid))) | |
503 | fprintf(f, " %-10s\n", gr->gr_name); | |
504 | else | |
505 | fprintf(f, " %-10u\n", is->gid); | |
506 | } | |
56692a67 | 507 | |
873e7a59 | 508 | void ipc_print_size(int unit, char *msg, uint64_t size, const char *end, |
56692a67 SK |
509 | int width) |
510 | { | |
873e7a59 | 511 | char format[32]; |
56692a67 SK |
512 | |
513 | if (!msg) | |
514 | /* NULL */ ; | |
515 | else if (msg[strlen(msg) - 1] == '=') | |
516 | printf("%s", msg); | |
517 | else if (unit == IPC_UNIT_BYTES) | |
518 | printf(_("%s (bytes) = "), msg); | |
519 | else if (unit == IPC_UNIT_KB) | |
520 | printf(_("%s (kbytes) = "), msg); | |
521 | else | |
522 | printf("%s = ", msg); | |
523 | ||
524 | switch (unit) { | |
525 | case IPC_UNIT_DEFAULT: | |
526 | case IPC_UNIT_BYTES: | |
34cf0aa5 | 527 | snprintf(format, sizeof(format), "%%%dju", width); |
56692a67 SK |
528 | printf(format, size); |
529 | break; | |
530 | case IPC_UNIT_KB: | |
34cf0aa5 | 531 | snprintf(format, sizeof(format), "%%%dju", width); |
56692a67 SK |
532 | printf(format, size / 1024); |
533 | break; | |
534 | case IPC_UNIT_HUMAN: | |
9d4f78ef KZ |
535 | { |
536 | char *tmp; | |
34cf0aa5 | 537 | snprintf(format, sizeof(format), "%%%ds", width); |
9d4f78ef KZ |
538 | printf(format, (tmp = size_to_human_string(SIZE_SUFFIX_1LETTER, size))); |
539 | free(tmp); | |
56692a67 | 540 | break; |
9d4f78ef | 541 | } |
56692a67 SK |
542 | default: |
543 | /* impossible occurred */ | |
544 | abort(); | |
545 | } | |
546 | ||
547 | if (end) | |
548 | printf("%s", end); | |
549 | } |