XenevaOS
Loading...
Searching...
No Matches
seq_file.h
Go to the documentation of this file.
1#ifndef __LINUX_SEQ_FILE_H__
2#define __LINUX_SEQ_FILE_H__
3
4/* loff_t, for seq_operations' start/next -- it lives in kernel.h (typedef
5 * uint64_t loff_t) and this header had no includes of its own. */
6#include <linux/kernel.h>
7#include <linux/string.h> /* memcpy, strchr -- seq_write() and mangle_path() */
8
9/*
10 * DCL <linux/seq_file.h> -- serial_core.c's uart_proc_show() writes with
11 * seq_printf()/seq_puts() (serial_core.c:1983-2050), so both must exist even
12 * though DCL has no procfs for them to land in.
13 *
14 * The signatures here deliberately match the stubs already sitting in
15 * DCL/linux_cdev_shim.c (seq_printf/seq_read/seq_lseek), taking `const void*`
16 * rather than mainline's `struct seq_file *`: those stubs are linked into the
17 * kernel already, and two declarations of one symbol with different pointer
18 * types is the kind of mismatch a C linker will happily accept and a reader
19 * will never spot. The header bends to the existing body, not the other way
20 * round -- the call sites pass a seq_file*, which converts to void* freely.
21 *
22 * seq_puts is declared here and defined beside them (see that file).
23 */
24
25struct file;
26struct inode;
27
28/*
29 * struct seq_file -- complete, where this header used to carry only the
30 * forward declaration.
31 *
32 * virtio_console.c:1264 is the first ported source that reads a member of
33 * one (`struct port *port = s->private;`), and a forward declaration makes
34 * that "incomplete definition of type 'struct seq_file'". mainline's struct
35 * is the whole /proc iterator state -- buf, size, from, count, version,
36 * index, op, lock, private -- and none of the rest has a referent here: DCL
37 * has no procfs (the header's own note above), seq_printf() takes `const
38 * void*` so no member of this type is read from any header, and the only
39 * member a ported source names is `private`, which is what single_open()
40 * writes the show callback's data into.
41 *
42 * So the members below are the ones a *reader* of this header could
43 * plausibly name, in mainline's spelling for the ones that are kept, and the
44 * layout is deliberately not mainline's: nothing in this tree passes a
45 * seq_file across a boundary that already has an opinion about its size.
46 */
47struct seq_file {
48 char* buf;
49 size_t size;
50 size_t count;
52 void* private;
53};
54
55/*
56 * struct seq_operations -- the four callbacks a /proc reader drives. Added
57 * because tty_ldisc.c:215 defines `const struct seq_operations
58 * tty_ldiscs_seq_ops` and the type was incomplete without it.
59 *
60 * Field order and types are mainline's; the one thing worth naming is that
61 * start()/next() return `void*` and stop() takes one, which is how the
62 * iterator hands a `loff_t*` back as an opaque token -- tty_ldiscs_seq_show()
63 * casts it straight back to `(loff_t *)v` (:208), so anything that changed
64 * the indirection here would still compile and would read the wrong integer.
65 *
66 * DCL has no procfs, so nothing ever calls these; they exist so the file that
67 * registers them compiles.
68 */
70 void* (*start)(struct seq_file* m, loff_t* pos);
71 void (*stop)(struct seq_file* m, void* v);
72 void* (*next)(struct seq_file* m, void* v, loff_t* pos);
73 int (*show)(struct seq_file* m, void* v);
74};
75
76void seq_printf(const void* m, const char* fmt, ...);
77void seq_puts(const void* m, const char* s);
78long seq_read(const void* m, char* buf, unsigned long count, long long* ppos);
79long seq_lseek(const void* m, long off, int whence);
80
81/*
82 * single_open() / single_release() -- the "one screen, no iteration" pair.
83 *
84 * They are here rather than in <linux/fs.h> for the same reason every other
85 * declaration in this port is somewhere other than <linux/fs.h>: that header
86 * is pinned by static asserts and does not move.
87 *
88 * mainline's single_open() is `m->private = data; m->op = &single_operations;`
89 * and returns single_start() so the first read calls show() once. DCL's body
90 * (DCL/linux_cdev_shim.c) records data and reports "one record", which is the
91 * same contract as far as a stub that never serves a read needs to keep.
92 *
93 * The show callback type is mainline's: `int (*)(struct seq_file *, void *)`,
94 * which is what DEFINE_SHOW_ATTRIBUTE() below passes it.
95 */
96int single_open(struct file* file, int (*show)(struct seq_file*, void*),
97 void* data);
98int single_release(struct inode* inode, struct file* file);
99
100/*
101 * DEFINE_SHOW_ATTRIBUTE(__name) -- mainline's, minus the inode.
102 *
103 * mainline expands to `<name>_open()` followed by `<name>_fops`, and the open
104 * arm is
105 *
106 * return single_open(file, __name##_show, inode->i_private);
107 *
108 * where i_private is what debugfs_create_file()'s `data` argument was stored
109 * in. DCL's struct inode (fs.h:128) is a pinned blob with no i_private to
110 * read -- the field is inside `_head[76]` -- so the data is passed as NULL
111 * instead, and that is not a live difference: DCL's debugfs_create_file() is
112 * a stub (DCL/linux_cdev_shim.c) that installs no file and opens no inode, so
113 * there is no path by which this fops table is ever entered and no
114 * show callback that would dereference a NULL port.
115 *
116 * The five members of the fops table are the ones mainline sets. `owner`,
117 * `read` and `llseek` are assigned across types that differ from mainline's
118 * (fs.h types llseek as `void*`, and THIS_MODULE is `(void*)0`) -- accepted
119 * pointer warnings, not errors, and the same shape mem.c's fops already
120 * produce.
121 */
122#define DEFINE_SHOW_ATTRIBUTE(__name) \
123 static int __name##_open(struct inode* inode, struct file* file) \
124 { \
125 (void)inode; \
126 return single_open(file, __name##_show, NULL); \
127 } \
128 static const struct file_operations __name##_fops = { \
129 .owner = THIS_MODULE, \
130 .open = __name##_open, \
131 .read = seq_read, \
132 .llseek = seq_lseek, \
133 .release = single_release, \
134 }
135
136/*
137 * seq_write(seq, data, len) -- append a block to a seq_file's buffer.
138 *
139 * mainline's body from fs/seq_file.c:824, verbatim except for one line: the
140 * overflow arm spells `seq_set_overflow(seq)`, which is mainline's own inline
141 * for `m->count = m->size` (include/linux/seq_file.h). Writing the member
142 * directly is the same store with no second name to carry for it, and DCL's
143 * struct seq_file above has exactly the two members that line touches.
144 *
145 * Callers are lib/seq_buf.c:54 and drm_debugfs.c's edid dump at :2272, and
146 * both test the return -- 0 for written, non-zero for "did not fit" -- so the
147 * two answers have to stay distinct rather than both being 0.
148 */
149static inline int seq_write(struct seq_file* seq, const void* data, size_t len)
150{
151 if (seq->count + len < seq->size) {
152 memcpy(seq->buf + seq->count, data, len);
153 seq->count += len;
154 return 0;
155 }
156 seq->count = seq->size; /* mainline's seq_set_overflow() */
157 return -1;
158}
159
160/*
161 * mangle_path(s, p, esc) -- write the pathname `p` into buffer `s`, escaping
162 * every character found in the set `esc` as a backslash and three octal
163 * digits, and return where the output ended (or NULL if it would not fit).
164 *
165 * mainline's body from fs/seq_file.c:441, and the part worth reading twice is
166 * that this is an *in-place* transform: seq_buf.c:324 calls
167 * `mangle_path(buf, p, esc)` where `p` is d_path()'s return, which points
168 * into that same buffer. So `s` trails `p` as it writes, and the two bounds
169 * are what stop it running off the end: `s <= p` says the write head has not
170 * passed the read head, and `s + 4 > p` says there is room for a full
171 * four-character escape before it would. Neither is a redundant check -- the
172 * first is only meaningful because the two pointers share a buffer, and the
173 * second is what makes an escape that would overwrite an unescaped byte
174 * behind it come back NULL instead of corrupting the path.
175 *
176 * Escaping in octal rather than doubling the backslash is mainline's choice,
177 * kept because the output is read by the same /proc consumers upstream has.
178 */
179static inline char* mangle_path(char* s, const char* p, const char* esc)
180{
181 while (s <= p) {
182 char c = *p++;
183
184 if (!c) {
185 return s;
186 } else if (!strchr(esc, c)) {
187 *s++ = c;
188 } else if (s + 4 > p) {
189 break;
190 } else {
191 *s++ = '\\';
192 *s++ = (char)('0' + ((c & 0300) >> 6));
193 *s++ = (char)('0' + ((c & 070) >> 3));
194 *s++ = (char)('0' + (c & 07));
195 }
196 }
197 return NULL;
198}
199
200#endif /* __LINUX_SEQ_FILE_H__ */
char * strchr(const char *String, int ch)
locates first occurance of character in string
Definition utclib.c:611
#define NULL
Definition actypes.h:561
size_t size
Definition drm_bridge.h:1299
const char * fmt
Definition drm_file.h:466
size_t len
Definition initial.c:23
void memcpy(void)
void * data
Definition kthread.h:30
uint64_t loff_t
Definition kernel.h:49
void seq_printf(const void *m, const char *fmt,...)
long seq_lseek(const void *m, long off, int whence)
void seq_puts(const void *m, const char *s)
int single_open(struct file *file, int(*show)(struct seq_file *, void *), void *data)
int single_release(struct inode *inode, struct file *file)
long seq_read(const void *m, char *buf, unsigned long count, long long *ppos)
Definition fs.h:142
Definition fs.h:183
Definition seq_file.h:47
loff_t index
Definition seq_file.h:51
size_t size
Definition seq_file.h:49
char * buf
Definition seq_file.h:48
size_t count
Definition seq_file.h:50
Definition seq_file.h:69
int(* show)(struct seq_file *m, void *v)
Definition seq_file.h:73
void(* stop)(struct seq_file *m, void *v)
Definition seq_file.h:71