1 /*
2 * lsfd-fifo.c - handle associations opening fifo objects
3 *
4 * Copyright (C) 2021 Red Hat, Inc. All rights reserved.
5 * Written by Masatake YAMATO <yamato@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it would be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include "xalloc.h"
23 #include "nls.h"
24 #include "libsmartcols.h"
25
26 #include "lsfd.h"
27
28 struct fifo {
29 struct file file;
30 struct ipc_endpoint endpoint;
31 };
32
33 struct fifo_ipc {
34 struct ipc ipc;
35 ino_t ino;
36 };
37
38 static inline char *fifo_xstrendpoint(struct file *file)
39 {
40 char *str = NULL;
41 xasprintf(&str, "%d,%s,%d%c%c",
42 file->proc->pid, file->proc->command, file->association,
43 (file->mode & S_IRUSR)? 'r': '-',
44 (file->mode & S_IWUSR)? 'w': '-');
45 return str;
46 }
47
48 static bool fifo_fill_column(struct proc *proc __attribute__((__unused__)),
49 struct file *file,
50 struct libscols_line *ln,
51 int column_id,
52 size_t column_index)
53 {
54 char *str = NULL;
55
56 switch(column_id) {
57 case COL_TYPE:
58 if (scols_line_set_data(ln, column_index, "FIFO"))
59 err(EXIT_FAILURE, _("failed to add output data"));
60 return true;
61 case COL_SOURCE:
62 if (major(file->stat.st_dev) == 0
63 && strncmp(file->name, "pipe:", 5) == 0) {
64 str = xstrdup("pipefs");
65 break;
66 }
67 return false;
68 case COL_ENDPOINTS: {
69 struct fifo *this = (struct fifo *)file;
70 struct list_head *e;
71 char *estr;
72 list_for_each_backwardly(e, &this->endpoint.ipc->endpoints) {
73 struct fifo *other = list_entry(e, struct fifo, endpoint.endpoints);
74 if (this == other)
75 continue;
76 if (str)
77 xstrputc(&str, '\n');
78 estr = fifo_xstrendpoint(&other->file);
79 xstrappend(&str, estr);
80 free(estr);
81 }
82 if (!str)
83 return false;
84 break;
85 }
86 default:
87 return false;
88 }
89
90 if (!str)
91 err(EXIT_FAILURE, _("failed to add output data"));
92 if (scols_line_refer_data(ln, column_index, str))
93 err(EXIT_FAILURE, _("failed to add output data"));
94 return true;
95 }
96
97 static unsigned int fifo_get_hash(struct file *file)
98 {
99 return (unsigned int)(file->stat.st_ino % UINT_MAX);
100 }
101
102 static bool fifo_is_suitable_ipc(struct ipc *ipc, struct file *file)
103 {
104 return ((struct fifo_ipc *)ipc)->ino == file->stat.st_ino;
105 }
106
107 static const struct ipc_class *fifo_get_ipc_class(struct file *file __attribute__((__unused__)))
108 {
109 static const struct ipc_class fifo_ipc_class = {
110 .get_hash = fifo_get_hash,
111 .is_suitable_ipc = fifo_is_suitable_ipc,
112 .free = NULL,
113 };
114 return &fifo_ipc_class;
115 }
116
117 static void fifo_initialize_content(struct file *file)
118 {
119 struct fifo *fifo = (struct fifo *)file;
120 struct ipc *ipc;
121 unsigned int hash;
122
123 INIT_LIST_HEAD(&fifo->endpoint.endpoints);
124 ipc = get_ipc(file);
125 if (ipc)
126 goto link;
127
128 ipc = xmalloc(sizeof(struct fifo_ipc));
129 ipc->class = fifo_get_ipc_class(file);
130 INIT_LIST_HEAD(&ipc->endpoints);
131 INIT_LIST_HEAD(&ipc->ipcs);
132 ((struct fifo_ipc *)ipc)->ino = file->stat.st_ino;
133
134 hash = fifo_get_hash(file);
135 add_ipc(ipc, hash);
136 link:
137 fifo->endpoint.ipc = ipc;
138 list_add(&fifo->endpoint.endpoints, &ipc->endpoints);
139 }
140
141 const struct file_class fifo_class = {
142 .super = &file_class,
143 .size = sizeof(struct fifo),
144 .fill_column = fifo_fill_column,
145 .initialize_content = fifo_initialize_content,
146 .free_content = NULL,
147 .get_ipc_class = fifo_get_ipc_class,
148 };