ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Linux-Clone/Clone.xs
Revision: 1.12
Committed: Wed Apr 8 20:28:06 2026 UTC (5 months, 3 weeks ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.11: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include <errno.h>
6 #include <sys/mman.h>
7
8 #undef _GNU_SOURCE
9 #define _GNU_SOURCE
10 #include <sched.h>
11 #include <unistd.h>
12 #include <sys/syscall.h>
13
14 #include <sched.h>
15
16 #include <sys/ioctl.h>
17 #include <net/if.h>
18
19 #ifdef __has_include
20 #if !__has_include("linux/kcmp.h") // use "" as GCC wrongly expands macros
21 #undef SYS_kcmp
22 #endif
23 #endif
24
25 #ifdef SYS_kcmp
26 #include "linux/kcmp.h"
27 #define kcmp(pid1,pid2,type,idx1,idx2) \
28 syscall (SYS_kcmp, (pid_t)pid1, (pid_t)pid2, \
29 (int)type, (unsigned long)idx1, (unsigned long)idx2)
30 #else
31 #define kcmp(pid1,pid2,type,idx1,idx2) \
32 (errno = ENOSYS, -1)
33 #endif
34
35 /* kcmp.h does not define symbols, so there is no way to detect preesence of enum */
36 /* members, so we just hardcode new symbols here. */
37 #ifndef KCMP_EPOLL_TFD
38 #define KCMP_EPOLL_TFD 7
39 #endif
40
41 /* from schmorp.h */
42 static int
43 s_fileno (SV *fh, int wr)
44 {
45 dTHX;
46 SvGETMAGIC (fh);
47
48 if (SvROK (fh))
49 {
50 fh = SvRV (fh);
51 SvGETMAGIC (fh);
52 }
53
54 if (SvTYPE (fh) == SVt_PVGV)
55 return PerlIO_fileno (wr ? IoOFP (sv_2io (fh)) : IoIFP (sv_2io (fh)));
56
57 if (SvOK (fh) && (SvIV (fh) >= 0) && (SvIV (fh) < 0x7fffffffL))
58 return SvIV (fh);
59
60 return -1;
61 }
62
63 static int
64 clone_cb (void *arg)
65 {
66 dSP;
67
68 PUSHMARK (SP);
69
70 PUTBACK;
71 int count = call_sv (sv_2mortal ((SV *)arg), G_SCALAR);
72 SPAGAIN;
73 int retval = count ? SvIV (POPs) : 0;
74 PUTBACK;
75
76 return retval;
77 }
78
79 MODULE = Linux::Clone PACKAGE = Linux::Clone
80
81 PROTOTYPES: ENABLE
82
83 BOOT:
84 HV *stash = gv_stashpv ("Linux::Clone", 1);
85
86 static const struct {
87 const char *name;
88 IV iv;
89 } *civ, const_iv[] = {
90 # define const_iv(name) { # name, (IV)name },
91 # define const_iv_clone(name) { # name, (IV) CLONE_ ## name },
92 # ifdef CSIGNAL
93 const_iv (CSIGNAL)
94 # endif
95 # ifdef CLONE_FILES
96 const_iv_clone (FILES)
97 # endif
98 # ifdef CLONE_FS
99 const_iv_clone (FS)
100 # endif
101 # ifdef CLONE_NEWNS
102 const_iv_clone (NEWNS)
103 # endif
104 # ifdef CLONE_VM
105 const_iv_clone (VM)
106 # endif
107 # ifdef CLONE_THREAD
108 const_iv_clone (THREAD)
109 # endif
110 # ifdef CLONE_SIGHAND
111 const_iv_clone (SIGHAND)
112 # endif
113 # ifdef CLONE_SYSVSEM
114 const_iv_clone (SYSVSEM)
115 # endif
116 # ifdef CLONE_NEWUTS
117 const_iv_clone (NEWUTS)
118 # endif
119 # ifdef CLONE_NEWIPC
120 const_iv_clone (NEWIPC)
121 # endif
122 # ifdef CLONE_NEWNET
123 const_iv_clone (NEWNET)
124 # endif
125 # ifdef CLONE_NEWTIME
126 const_iv_clone (NEWTIME)
127 # endif
128 # ifdef CLONE_PTRACE
129 const_iv_clone (PTRACE)
130 # endif
131 # ifdef CLONE_VFORK
132 const_iv_clone (VFORK)
133 # endif
134 # ifdef CLONE_SETTLS
135 const_iv_clone (SETTLS)
136 # endif
137 # ifdef CLONE_PARENT_SETTID
138 const_iv_clone (PARENT_SETTID)
139 # endif
140 # ifdef CLONE_CHILD_CLEARTID
141 const_iv_clone (CHILD_CLEARTID)
142 # endif
143 # ifdef CLONE_DETACHED
144 const_iv_clone (DETACHED)
145 # endif
146 # ifdef CLONE_UNTRACED
147 const_iv_clone (UNTRACED)
148 # endif
149 # ifdef CLONE_CHILD_SETTID
150 const_iv_clone (CHILD_SETTID)
151 # endif
152 # ifdef CLONE_NEWUSER
153 const_iv_clone (NEWUSER)
154 # endif
155 # ifdef CLONE_NEWPID
156 const_iv_clone (NEWPID)
157 # endif
158 # ifdef CLONE_IO
159 const_iv_clone (IO)
160 # endif
161 # ifdef CLONE_NEWCGROUP
162 const_iv_clone (NEWCGROUP)
163 # endif
164 # ifdef CLONE_PIDFD
165 const_iv_clone (PIDFD)
166 # endif
167 # ifdef SYS_kcmp
168 const_iv (KCMP_FILE)
169 const_iv (KCMP_VM)
170 const_iv (KCMP_FILES)
171 const_iv (KCMP_FS)
172 const_iv (KCMP_SIGHAND)
173 const_iv (KCMP_IO)
174 const_iv (KCMP_SYSVSEM)
175 const_iv (KCMP_EPOLL_TFD)
176 # endif
177 # ifdef NS_GET_USERNS
178 const_iv (NS_GET_USERNS)
179 # endif
180 # ifdef NS_GET_PARENT
181 const_iv (NS_GET_PARENT)
182 # endif
183 # ifdef NS_GET_NSTYPE
184 const_iv (NS_GET_NSTYPE)
185 # endif
186 # ifdef NS_OWNER_UID
187 const_iv (NS_OWNER_UID
188 # endif
189 };
190
191 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
192 newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
193
194 int
195 clone (SV *sub, IV stacksize, int flags, SV *ptid = 0, SV *tls = &PL_sv_undef)
196 CODE:
197 {
198 if (!stacksize)
199 stacksize = 4 << 20;
200
201 pid_t ptid_;
202 char *stack_ptr = mmap (0, stacksize, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_STACK, -1, 0);
203
204 #ifndef __hppa
205 stack_ptr += stacksize - 16; /* be safe and put the sp at 16 bytes below the end */
206 #endif
207
208 RETVAL = -1;
209 if (stack_ptr != (void *)-1)
210 {
211 SV *my_sub = newSVsv (sub);
212
213 RETVAL = clone (clone_cb, (void *)stack_ptr, flags, (void *)my_sub, &ptid, SvOK (tls) ? SvPV_nolen (tls) : 0, 0);
214
215 if (ptid) sv_setiv (ptid, (IV)ptid_);
216
217 if ((flags & (CLONE_VM | CLONE_VFORK)) != CLONE_VM)
218 {
219 int old_errno = errno;
220 munmap (stack_ptr, stacksize);
221 errno = old_errno;
222 }
223 }
224 }
225 OUTPUT: RETVAL
226
227 int
228 unshare (int flags)
229 PROTOTYPE: @
230
231 int
232 setns (SV *fh_or_fd, int nstype = 0)
233 C_ARGS: s_fileno (fh_or_fd, 0), nstype
234
235 int
236 pivot_root (SV *new_root, SV *old_root)
237 CODE:
238 RETVAL = syscall (SYS_pivot_root,
239 (const char *)SvPVbyte_nolen (new_root),
240 (const char *)SvPVbyte_nolen (old_root));
241 OUTPUT: RETVAL
242
243 int
244 kcmp (IV pid1, IV pid2, IV type, UV idx1 = 0, UV idx2 = 0)
245
246 int
247 siocsifflags (char *ifname, U32 flags = IFF_UP)
248 CODE:
249 {
250 int saved_errno;
251 struct ifreq ifr;
252 int fd = socket (AF_INET, SOCK_DGRAM, 0);
253 strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
254 RETVAL = ioctl (fd, SIOCSIFFLAGS, &ifr);
255 saved_errno = errno;
256 close (fd);
257 errno = saved_errno;
258 }
259 OUTPUT: RETVAL
260