]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/compat/linuxkpi/common/src/linux_seq_file.c
Merge ^/vendor/compiler-rt/dist up to its last change, and resolve conflicts.
[FreeBSD/FreeBSD.git] / sys / compat / linuxkpi / common / src / linux_seq_file.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2016-2018, Matthew Macy <mmacy@freebsd.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/types.h>
33 #include <sys/systm.h>
34 #include <sys/param.h>
35 #include <sys/sbuf.h>
36 #include <sys/syslog.h>
37 #include <sys/vnode.h>
38
39 #include <linux/seq_file.h>
40 #include <linux/file.h>
41
42 #undef file
43 MALLOC_DEFINE(M_LSEQ, "seq_file", "seq_file");
44
45 ssize_t
46 seq_read(struct linux_file *f, char *ubuf, size_t size, off_t *ppos)
47 {
48         struct seq_file *m = f->private_data;
49         void *p;
50         int rc;
51         off_t pos = 0;
52
53         p = m->op->start(m, &pos);
54         rc = m->op->show(m, p);
55         if (rc)
56                 return (rc);
57         return (size);
58 }
59
60 int
61 seq_write(struct seq_file *seq, const void *data, size_t len)
62 {
63
64         return (sbuf_bcpy(seq->buf, data, len));
65 }
66
67 /*
68  * This only needs to be a valid address for lkpi
69  * drivers it should never actually be called
70  */
71 off_t
72 seq_lseek(struct linux_file *file, off_t offset, int whence)
73 {
74
75         panic("%s not supported\n", __FUNCTION__);
76         return (0);
77 }
78
79 static void *
80 single_start(struct seq_file *p, off_t *pos)
81 {
82
83         return ((void *)(uintptr_t)(*pos == 0));
84 }
85
86 static void *
87 single_next(struct seq_file *p, void *v, off_t *pos)
88 {
89
90         ++*pos;
91         return (NULL);
92 }
93
94 static void
95 single_stop(struct seq_file *p, void *v)
96 {
97 }
98
99 int
100 seq_open(struct linux_file *f, const struct seq_operations *op)
101 {
102         struct seq_file *p;
103
104         if (f->private_data != NULL)
105                 log(LOG_WARNING, "%s private_data not NULL", __func__);
106
107         if ((p = malloc(sizeof(*p), M_LSEQ, M_NOWAIT|M_ZERO)) == NULL)
108                 return (-ENOMEM);
109
110         f->private_data = p;
111         p->op = op;
112         p->file = f;
113         return (0);
114 }
115
116 int
117 single_open(struct linux_file *f, int (*show)(struct seq_file *, void *), void *d)
118 {
119         struct seq_operations *op;
120         int rc = -ENOMEM;
121
122         op = malloc(sizeof(*op), M_LSEQ, M_NOWAIT);
123         if (op) {
124                 op->start = single_start;
125                 op->next = single_next;
126                 op->stop = single_stop;
127                 op->show = show;
128                 rc = seq_open(f, op);
129                 if (rc)
130                         free(op, M_LSEQ);
131                 else
132                         ((struct seq_file *)f->private_data)->private = d;
133
134         }
135         return (rc);
136 }
137
138 int
139 seq_release(struct inode *inode __unused, struct linux_file *file)
140 {
141         struct seq_file *m;
142
143         m = file->private_data;
144         free(m, M_LSEQ);
145         return (0);
146 }
147
148 int
149 single_release(struct vnode *v, struct linux_file *f)
150 {
151         const struct seq_operations *op = ((struct seq_file *)f->private_data)->op;
152         int rc;
153
154         rc = seq_release(v, f);
155         free(__DECONST(void *, op), M_LSEQ);
156         return (rc);
157 }