runshare 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +38 -0
- data/LICENSE.txt +21 -0
- data/README.md +103 -0
- data/Rakefile +14 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/runshare/extconf.rb +33 -0
- data/ext/runshare/include/all-io.h +115 -0
- data/ext/runshare/include/c.h +479 -0
- data/ext/runshare/include/caputils.h +34 -0
- data/ext/runshare/include/namespace.h +56 -0
- data/ext/runshare/include/pathnames.h +218 -0
- data/ext/runshare/include/pwdutils.h +14 -0
- data/ext/runshare/include/signames.h +8 -0
- data/ext/runshare/include/strutils.h +393 -0
- data/ext/runshare/runshare.c +261 -0
- data/ext/runshare/unshare.c +498 -0
- data/ext/runshare/unshare.h +82 -0
- data/lib/runshare/version.rb +3 -0
- data/lib/runshare.rb +7 -0
- data/runshare.gemspec +44 -0
- metadata +231 -0
@@ -0,0 +1,218 @@
|
|
1
|
+
/*
|
2
|
+
* No copyright is claimed. This code is in the public domain; do with
|
3
|
+
* it what you wish.
|
4
|
+
*/
|
5
|
+
#ifndef PATHNAMES_H
|
6
|
+
#define PATHNAMES_H
|
7
|
+
|
8
|
+
#ifdef HAVE_PATHS_H
|
9
|
+
# include <paths.h>
|
10
|
+
#endif
|
11
|
+
|
12
|
+
#ifndef __STDC__
|
13
|
+
# error "we need an ANSI compiler"
|
14
|
+
#endif
|
15
|
+
|
16
|
+
/* used by kernel in /proc (e.g. /proc/swaps) for deleted files */
|
17
|
+
#define PATH_DELETED_SUFFIX " (deleted)"
|
18
|
+
|
19
|
+
/* DEFPATHs from <paths.h> don't include /usr/local */
|
20
|
+
#undef _PATH_DEFPATH
|
21
|
+
|
22
|
+
#ifdef USE_USRDIR_PATHS_ONLY
|
23
|
+
# define _PATH_DEFPATH "/usr/local/bin:/usr/bin"
|
24
|
+
#else
|
25
|
+
# define _PATH_DEFPATH "/usr/local/bin:/bin:/usr/bin"
|
26
|
+
#endif
|
27
|
+
|
28
|
+
#undef _PATH_DEFPATH_ROOT
|
29
|
+
|
30
|
+
#ifdef USE_USRDIR_PATHS_ONLY
|
31
|
+
# define _PATH_DEFPATH_ROOT "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
|
32
|
+
#else
|
33
|
+
# define _PATH_DEFPATH_ROOT "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
|
34
|
+
#endif
|
35
|
+
|
36
|
+
#define _PATH_HUSHLOGIN ".hushlogin"
|
37
|
+
#define _PATH_HUSHLOGINS "/etc/hushlogins"
|
38
|
+
|
39
|
+
#define _PATH_NOLOGIN_TXT "/etc/nologin.txt"
|
40
|
+
|
41
|
+
#ifndef _PATH_MAILDIR
|
42
|
+
# define _PATH_MAILDIR "/var/spool/mail"
|
43
|
+
#endif
|
44
|
+
#define _PATH_MOTDFILE "/usr/share/misc/motd:/run/motd:/etc/motd"
|
45
|
+
#ifndef _PATH_NOLOGIN
|
46
|
+
# define _PATH_NOLOGIN "/etc/nologin"
|
47
|
+
#endif
|
48
|
+
#define _PATH_VAR_NOLOGIN "/var/run/nologin"
|
49
|
+
|
50
|
+
#ifndef _PATH_LOGIN
|
51
|
+
# define _PATH_LOGIN "/bin/login"
|
52
|
+
#endif
|
53
|
+
#define _PATH_SHUTDOWN "/sbin/shutdown"
|
54
|
+
#define _PATH_POWEROFF "/sbin/poweroff"
|
55
|
+
|
56
|
+
#define _PATH_TERMCOLORS_DIRNAME "terminal-colors.d"
|
57
|
+
#define _PATH_TERMCOLORS_DIR "/etc/" _PATH_TERMCOLORS_DIRNAME
|
58
|
+
|
59
|
+
/* login paths */
|
60
|
+
#define _PATH_PASSWD "/etc/passwd"
|
61
|
+
#define _PATH_GSHADOW "/etc/gshadow"
|
62
|
+
#define _PATH_GROUP "/etc/group"
|
63
|
+
#define _PATH_SHADOW_PASSWD "/etc/shadow"
|
64
|
+
#define _PATH_SHELLS "/etc/shells"
|
65
|
+
|
66
|
+
#ifndef _PATH_TMP
|
67
|
+
# define _PATH_TMP "/tmp/"
|
68
|
+
#endif
|
69
|
+
|
70
|
+
#ifndef _PATH_BTMP
|
71
|
+
# define _PATH_BTMP "/var/log/btmp"
|
72
|
+
#endif
|
73
|
+
|
74
|
+
#define _PATH_ISSUE_FILENAME "issue"
|
75
|
+
#define _PATH_ISSUE_DIRNAME _PATH_ISSUE_FILENAME ".d"
|
76
|
+
|
77
|
+
#define _PATH_ISSUE "/etc/" _PATH_ISSUE_FILENAME
|
78
|
+
#define _PATH_ISSUEDIR "/etc/" _PATH_ISSUE_DIRNAME
|
79
|
+
|
80
|
+
#define _PATH_OS_RELEASE_ETC "/etc/os-release"
|
81
|
+
#define _PATH_OS_RELEASE_USR "/usr/lib/os-release"
|
82
|
+
#define _PATH_NUMLOCK_ON _PATH_RUNSTATEDIR "/numlock-on"
|
83
|
+
#define _PATH_LOGINDEFS "/etc/login.defs"
|
84
|
+
|
85
|
+
/* misc paths */
|
86
|
+
#define _PATH_WORDS "/usr/share/dict/words"
|
87
|
+
#define _PATH_WORDS_ALT "/usr/share/dict/web2"
|
88
|
+
|
89
|
+
/* mount paths */
|
90
|
+
#define _PATH_FILESYSTEMS "/etc/filesystems"
|
91
|
+
#define _PATH_PROC_SWAPS "/proc/swaps"
|
92
|
+
#define _PATH_PROC_FILESYSTEMS "/proc/filesystems"
|
93
|
+
#define _PATH_PROC_MOUNTS "/proc/mounts"
|
94
|
+
#define _PATH_PROC_PARTITIONS "/proc/partitions"
|
95
|
+
#define _PATH_PROC_DEVICES "/proc/devices"
|
96
|
+
#define _PATH_PROC_MOUNTINFO "/proc/self/mountinfo"
|
97
|
+
#define _PATH_PROC_LOCKS "/proc/locks"
|
98
|
+
#define _PATH_PROC_CDROMINFO "/proc/sys/dev/cdrom/info"
|
99
|
+
|
100
|
+
#define _PATH_PROC_UIDMAP "/proc/self/uid_map"
|
101
|
+
#define _PATH_PROC_GIDMAP "/proc/self/gid_map"
|
102
|
+
#define _PATH_PROC_SETGROUPS "/proc/self/setgroups"
|
103
|
+
|
104
|
+
#define _PATH_PROC_FDDIR "/proc/self/fd"
|
105
|
+
|
106
|
+
#define _PATH_PROC_ATTR_CURRENT "/proc/self/attr/current"
|
107
|
+
#define _PATH_PROC_ATTR_EXEC "/proc/self/attr/exec"
|
108
|
+
#define _PATH_PROC_CAPLASTCAP "/proc/sys/kernel/cap_last_cap"
|
109
|
+
|
110
|
+
|
111
|
+
#define _PATH_SYS_BLOCK "/sys/block"
|
112
|
+
#define _PATH_SYS_DEVBLOCK "/sys/dev/block"
|
113
|
+
#define _PATH_SYS_DEVCHAR "/sys/dev/char"
|
114
|
+
#define _PATH_SYS_CLASS "/sys/class"
|
115
|
+
#define _PATH_SYS_SCSI "/sys/bus/scsi"
|
116
|
+
|
117
|
+
#define _PATH_SYS_SELINUX "/sys/fs/selinux"
|
118
|
+
#define _PATH_SYS_APPARMOR "/sys/kernel/security/apparmor"
|
119
|
+
|
120
|
+
#ifndef _PATH_MOUNTED
|
121
|
+
# ifdef MOUNTED /* deprecated */
|
122
|
+
# define _PATH_MOUNTED MOUNTED
|
123
|
+
# else
|
124
|
+
# define _PATH_MOUNTED "/etc/mtab"
|
125
|
+
# endif
|
126
|
+
#endif
|
127
|
+
|
128
|
+
#ifndef _PATH_MNTTAB
|
129
|
+
# ifdef MNTTAB /* deprecated */
|
130
|
+
# define _PATH_MNTTAB MNTTAB
|
131
|
+
# else
|
132
|
+
# define _PATH_MNTTAB "/etc/fstab"
|
133
|
+
# endif
|
134
|
+
#endif
|
135
|
+
|
136
|
+
#ifndef _PATH_DEV
|
137
|
+
/*
|
138
|
+
* The tailing '/' in _PATH_DEV is there for compatibility with libc.
|
139
|
+
*/
|
140
|
+
# define _PATH_DEV "/dev/"
|
141
|
+
#endif
|
142
|
+
|
143
|
+
#define _PATH_DEV_MAPPER "/dev/mapper"
|
144
|
+
|
145
|
+
#define _PATH_DEV_MEM "/dev/mem"
|
146
|
+
|
147
|
+
#define _PATH_DEV_LOOP "/dev/loop"
|
148
|
+
#define _PATH_DEV_LOOPCTL "/dev/loop-control"
|
149
|
+
|
150
|
+
/* udev paths */
|
151
|
+
#define _PATH_DEV_BYLABEL "/dev/disk/by-label"
|
152
|
+
#define _PATH_DEV_BYUUID "/dev/disk/by-uuid"
|
153
|
+
#define _PATH_DEV_BYID "/dev/disk/by-id"
|
154
|
+
#define _PATH_DEV_BYPATH "/dev/disk/by-path"
|
155
|
+
#define _PATH_DEV_BYPARTLABEL "/dev/disk/by-partlabel"
|
156
|
+
#define _PATH_DEV_BYPARTUUID "/dev/disk/by-partuuid"
|
157
|
+
|
158
|
+
/* hwclock paths */
|
159
|
+
#ifdef CONFIG_ADJTIME_PATH
|
160
|
+
# define _PATH_ADJTIME CONFIG_ADJTIME_PATH
|
161
|
+
#else
|
162
|
+
# define _PATH_ADJTIME "/etc/adjtime"
|
163
|
+
#endif
|
164
|
+
|
165
|
+
#ifdef __ia64__
|
166
|
+
# define _PATH_RTC_DEV "/dev/efirtc"
|
167
|
+
#else
|
168
|
+
# define _PATH_RTC_DEV "/dev/rtc0"
|
169
|
+
#endif
|
170
|
+
|
171
|
+
/* raw paths*/
|
172
|
+
#define _PATH_RAWDEVDIR "/dev/raw/"
|
173
|
+
#define _PATH_RAWDEVCTL _PATH_RAWDEVDIR "rawctl"
|
174
|
+
/* deprecated */
|
175
|
+
#define _PATH_RAWDEVCTL_OLD "/dev/rawctl"
|
176
|
+
|
177
|
+
#define _PATH_PROC_KERNEL "/proc/sys/kernel"
|
178
|
+
|
179
|
+
/* ipc paths */
|
180
|
+
#define _PATH_PROC_SYSV_MSG "/proc/sysvipc/msg"
|
181
|
+
#define _PATH_PROC_SYSV_SEM "/proc/sysvipc/sem"
|
182
|
+
#define _PATH_PROC_SYSV_SHM "/proc/sysvipc/shm"
|
183
|
+
#define _PATH_PROC_IPC_MSGMAX _PATH_PROC_KERNEL "/msgmax"
|
184
|
+
#define _PATH_PROC_IPC_MSGMNB _PATH_PROC_KERNEL "/msgmnb"
|
185
|
+
#define _PATH_PROC_IPC_MSGMNI _PATH_PROC_KERNEL "/msgmni"
|
186
|
+
#define _PATH_PROC_IPC_SEM _PATH_PROC_KERNEL "/sem"
|
187
|
+
#define _PATH_PROC_IPC_SHMALL _PATH_PROC_KERNEL "/shmall"
|
188
|
+
#define _PATH_PROC_IPC_SHMMAX _PATH_PROC_KERNEL "/shmmax"
|
189
|
+
#define _PATH_PROC_IPC_SHMMNI _PATH_PROC_KERNEL "/shmmni"
|
190
|
+
|
191
|
+
/* util clamp */
|
192
|
+
#define _PATH_PROC_UCLAMP_MIN _PATH_PROC_KERNEL "/sched_util_clamp_min"
|
193
|
+
#define _PATH_PROC_UCLAMP_MAX _PATH_PROC_KERNEL "/sched_util_clamp_max"
|
194
|
+
|
195
|
+
/* irqtop paths */
|
196
|
+
#define _PATH_PROC_INTERRUPTS "/proc/interrupts"
|
197
|
+
#define _PATH_PROC_SOFTIRQS "/proc/softirqs"
|
198
|
+
#define _PATH_PROC_UPTIME "/proc/uptime"
|
199
|
+
|
200
|
+
/* kernel command line */
|
201
|
+
#define _PATH_PROC_CMDLINE "/proc/cmdline"
|
202
|
+
|
203
|
+
|
204
|
+
/* logger paths */
|
205
|
+
#define _PATH_DEVLOG "/dev/log"
|
206
|
+
|
207
|
+
/* ctrlaltdel paths */
|
208
|
+
#define _PATH_PROC_CTRL_ALT_DEL "/proc/sys/kernel/ctrl-alt-del"
|
209
|
+
|
210
|
+
/* lscpu paths */
|
211
|
+
#define _PATH_PROC_CPUINFO "/proc/cpuinfo"
|
212
|
+
|
213
|
+
/* rfkill paths */
|
214
|
+
#define _PATH_DEV_RFKILL "/dev/rfkill"
|
215
|
+
#define _PATH_SYS_RFKILL "/sys/class/rfkill"
|
216
|
+
|
217
|
+
|
218
|
+
#endif /* PATHNAMES_H */
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#ifndef UTIL_LINUX_PWDUTILS_H
|
2
|
+
#define UTIL_LINUX_PWDUTILS_H
|
3
|
+
|
4
|
+
#include <sys/types.h>
|
5
|
+
#include <pwd.h>
|
6
|
+
#include <grp.h>
|
7
|
+
|
8
|
+
extern struct passwd *xgetpwnam(const char *username, char **pwdbuf);
|
9
|
+
extern struct group *xgetgrnam(const char *groupname, char **grpbuf);
|
10
|
+
extern struct passwd *xgetpwuid(uid_t uid, char **pwdbuf);
|
11
|
+
extern char *xgetlogin(void);
|
12
|
+
|
13
|
+
#endif /* UTIL_LINUX_PWDUTILS_H */
|
14
|
+
|
@@ -0,0 +1,393 @@
|
|
1
|
+
#ifndef UTIL_LINUX_STRUTILS
|
2
|
+
#define UTIL_LINUX_STRUTILS
|
3
|
+
|
4
|
+
#include <stdlib.h>
|
5
|
+
#include <inttypes.h>
|
6
|
+
#include <string.h>
|
7
|
+
#include <sys/types.h>
|
8
|
+
#include <ctype.h>
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <errno.h>
|
11
|
+
#include <time.h>
|
12
|
+
|
13
|
+
#include "c.h"
|
14
|
+
|
15
|
+
/* initialize a custom exit code for all *_or_err functions */
|
16
|
+
extern void strutils_set_exitcode(int exit_code);
|
17
|
+
|
18
|
+
extern int parse_size(const char *str, uintmax_t *res, int *power);
|
19
|
+
extern int strtosize(const char *str, uintmax_t *res);
|
20
|
+
extern uintmax_t strtosize_or_err(const char *str, const char *errmesg);
|
21
|
+
|
22
|
+
extern int ul_strtos64(const char *str, int64_t *num, int base);
|
23
|
+
extern int ul_strtou64(const char *str, uint64_t *num, int base);
|
24
|
+
extern int ul_strtos32(const char *str, int32_t *num, int base);
|
25
|
+
extern int ul_strtou32(const char *str, uint32_t *num, int base);
|
26
|
+
|
27
|
+
extern int64_t str2num_or_err(const char *str, int base, const char *errmesg, int64_t low, int64_t up);
|
28
|
+
extern uint64_t str2unum_or_err(const char *str, int base, const char *errmesg, uint64_t up);
|
29
|
+
|
30
|
+
#define strtos64_or_err(_s, _e) str2num_or_err(_s, 10, _e, 0, 0)
|
31
|
+
#define strtou64_or_err(_s, _e) str2unum_or_err(_s, 10, _e, 0)
|
32
|
+
#define strtox64_or_err(_s, _e) str2unum_or_err(_s, 16, _e, 0)
|
33
|
+
|
34
|
+
#define strtos32_or_err(_s, _e) (int32_t) str2num_or_err(_s, 10, _e, INT32_MIN, INT32_MAX)
|
35
|
+
#define strtou32_or_err(_s, _e) (uint32_t) str2unum_or_err(_s, 10, _e, UINT32_MAX)
|
36
|
+
#define strtox32_or_err(_s, _e) (uint32_t) str2unum_or_err(_s, 16, _e, UINT32_MAX)
|
37
|
+
|
38
|
+
#define strtos16_or_err(_s, _e) (int16_t) str2num_or_err(_s, 10, _e, INT16_MIN, INT16_MAX)
|
39
|
+
#define strtou16_or_err(_s, _e) (uint16_t) str2unum_or_err(_s, 10, _e, UINT16_MAX)
|
40
|
+
#define strtox16_or_err(_s, _e) (uint16_t) str2unum_or_err(_s, 16, _e, UINT16_MAX)
|
41
|
+
|
42
|
+
extern double strtod_or_err(const char *str, const char *errmesg);
|
43
|
+
extern long double strtold_or_err(const char *str, const char *errmesg);
|
44
|
+
|
45
|
+
extern long strtol_or_err(const char *str, const char *errmesg);
|
46
|
+
extern unsigned long strtoul_or_err(const char *str, const char *errmesg);
|
47
|
+
|
48
|
+
extern void strtotimeval_or_err(const char *str, struct timeval *tv,
|
49
|
+
const char *errmesg);
|
50
|
+
extern time_t strtotime_or_err(const char *str, const char *errmesg);
|
51
|
+
|
52
|
+
extern int isdigit_strend(const char *str, const char **end);
|
53
|
+
#define isdigit_string(_s) isdigit_strend(_s, NULL)
|
54
|
+
|
55
|
+
extern int isxdigit_strend(const char *str, const char **end);
|
56
|
+
#define isxdigit_string(_s) isxdigit_strend(_s, NULL)
|
57
|
+
|
58
|
+
|
59
|
+
extern int parse_switch(const char *arg, const char *errmesg, ...);
|
60
|
+
|
61
|
+
#ifndef HAVE_MEMPCPY
|
62
|
+
extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n);
|
63
|
+
#endif
|
64
|
+
#ifndef HAVE_STRNLEN
|
65
|
+
extern size_t strnlen(const char *s, size_t maxlen);
|
66
|
+
#endif
|
67
|
+
#ifndef HAVE_STRNDUP
|
68
|
+
extern char *strndup(const char *s, size_t n);
|
69
|
+
#endif
|
70
|
+
#ifndef HAVE_STRNCHR
|
71
|
+
extern char *strnchr(const char *s, size_t maxlen, int c);
|
72
|
+
#endif
|
73
|
+
|
74
|
+
/* caller guarantees n > 0 */
|
75
|
+
static inline void xstrncpy(char *dest, const char *src, size_t n)
|
76
|
+
{
|
77
|
+
size_t len = src ? strlen(src) : 0;
|
78
|
+
|
79
|
+
if (!len)
|
80
|
+
return;
|
81
|
+
len = min(len, n - 1);
|
82
|
+
memcpy(dest, src, len);
|
83
|
+
dest[len] = 0;
|
84
|
+
}
|
85
|
+
|
86
|
+
/* This is like strncpy(), but based on memcpy(), so compilers and static
|
87
|
+
* analyzers do not complain when sizeof(destination) is the same as 'n' and
|
88
|
+
* result is not terminated by zero.
|
89
|
+
*
|
90
|
+
* Use this function to copy string to logs with fixed sizes (wtmp/utmp. ...)
|
91
|
+
* where string terminator is optional.
|
92
|
+
*/
|
93
|
+
static inline void *str2memcpy(void *dest, const char *src, size_t n)
|
94
|
+
{
|
95
|
+
size_t bytes = strlen(src) + 1;
|
96
|
+
|
97
|
+
if (bytes > n)
|
98
|
+
bytes = n;
|
99
|
+
|
100
|
+
memcpy(dest, src, bytes);
|
101
|
+
return dest;
|
102
|
+
}
|
103
|
+
|
104
|
+
static inline char *mem2strcpy(char *dest, const void *src, size_t n, size_t nmax)
|
105
|
+
{
|
106
|
+
if (n + 1 > nmax)
|
107
|
+
n = nmax - 1;
|
108
|
+
|
109
|
+
memcpy(dest, src, n);
|
110
|
+
dest[nmax-1] = '\0';
|
111
|
+
return dest;
|
112
|
+
}
|
113
|
+
|
114
|
+
/* Reallocate @str according to @newstr and copy @newstr to @str; returns new @str.
|
115
|
+
* The @str is not modified if reallocation failed (like classic realloc()).
|
116
|
+
*/
|
117
|
+
static inline char * __attribute__((warn_unused_result))
|
118
|
+
strrealloc(char *str, const char *newstr)
|
119
|
+
{
|
120
|
+
size_t nsz, osz;
|
121
|
+
|
122
|
+
if (!str)
|
123
|
+
return newstr ? strdup(newstr) : NULL;
|
124
|
+
if (!newstr)
|
125
|
+
return NULL;
|
126
|
+
|
127
|
+
osz = strlen(str);
|
128
|
+
nsz = strlen(newstr);
|
129
|
+
|
130
|
+
if (nsz > osz)
|
131
|
+
str = realloc(str, nsz + 1);
|
132
|
+
if (str)
|
133
|
+
memcpy(str, newstr, nsz + 1);
|
134
|
+
return str;
|
135
|
+
}
|
136
|
+
|
137
|
+
/* Copy string @str to struct @stru to member addressed by @offset */
|
138
|
+
static inline int strdup_to_offset(void *stru, size_t offset, const char *str)
|
139
|
+
{
|
140
|
+
char **o;
|
141
|
+
char *p = NULL;
|
142
|
+
|
143
|
+
if (!stru)
|
144
|
+
return -EINVAL;
|
145
|
+
|
146
|
+
o = (char **) ((char *) stru + offset);
|
147
|
+
if (str) {
|
148
|
+
p = strdup(str);
|
149
|
+
if (!p)
|
150
|
+
return -ENOMEM;
|
151
|
+
}
|
152
|
+
|
153
|
+
free(*o);
|
154
|
+
*o = p;
|
155
|
+
return 0;
|
156
|
+
}
|
157
|
+
|
158
|
+
/* Copy string __str to struct member _m of the struct _s */
|
159
|
+
#define strdup_to_struct_member(_s, _m, _str) \
|
160
|
+
strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str)
|
161
|
+
|
162
|
+
/* Copy string addressed by @offset between two structs */
|
163
|
+
static inline int strdup_between_offsets(void *stru_dst, void *stru_src, size_t offset)
|
164
|
+
{
|
165
|
+
char **src;
|
166
|
+
char **dst;
|
167
|
+
char *p = NULL;
|
168
|
+
|
169
|
+
if (!stru_src || !stru_dst)
|
170
|
+
return -EINVAL;
|
171
|
+
|
172
|
+
src = (char **) ((char *) stru_src + offset);
|
173
|
+
dst = (char **) ((char *) stru_dst + offset);
|
174
|
+
|
175
|
+
if (*src) {
|
176
|
+
p = strdup(*src);
|
177
|
+
if (!p)
|
178
|
+
return -ENOMEM;
|
179
|
+
}
|
180
|
+
|
181
|
+
free(*dst);
|
182
|
+
*dst = p;
|
183
|
+
return 0;
|
184
|
+
}
|
185
|
+
|
186
|
+
/* Copy string addressed by struct member between two instances of the same
|
187
|
+
* struct type */
|
188
|
+
#define strdup_between_structs(_dst, _src, _m) \
|
189
|
+
strdup_between_offsets((void *)_dst, (void *)_src, offsetof(__typeof__(*(_src)), _m))
|
190
|
+
|
191
|
+
|
192
|
+
extern char *xstrmode(mode_t mode, char *str);
|
193
|
+
|
194
|
+
/* Options for size_to_human_string() */
|
195
|
+
enum
|
196
|
+
{
|
197
|
+
SIZE_SUFFIX_1LETTER = 0,
|
198
|
+
SIZE_SUFFIX_3LETTER = (1 << 0),
|
199
|
+
SIZE_SUFFIX_SPACE = (1 << 1),
|
200
|
+
SIZE_DECIMAL_2DIGITS = (1 << 2)
|
201
|
+
};
|
202
|
+
|
203
|
+
extern char *size_to_human_string(int options, uint64_t bytes);
|
204
|
+
|
205
|
+
extern int string_to_idarray(const char *list, int ary[], size_t arysz,
|
206
|
+
int (name2id)(const char *, size_t));
|
207
|
+
extern int string_add_to_idarray(const char *list, int ary[],
|
208
|
+
size_t arysz, size_t *ary_pos,
|
209
|
+
int (name2id)(const char *, size_t));
|
210
|
+
|
211
|
+
extern int string_to_bitarray(const char *list, char *ary,
|
212
|
+
int (*name2bit)(const char *, size_t));
|
213
|
+
|
214
|
+
extern int string_to_bitmask(const char *list,
|
215
|
+
unsigned long *mask,
|
216
|
+
long (*name2flag)(const char *, size_t));
|
217
|
+
extern int parse_range(const char *str, int *lower, int *upper, int def);
|
218
|
+
|
219
|
+
extern int streq_paths(const char *a, const char *b);
|
220
|
+
|
221
|
+
/*
|
222
|
+
* Match string beginning.
|
223
|
+
*/
|
224
|
+
static inline const char *startswith(const char *s, const char *prefix)
|
225
|
+
{
|
226
|
+
size_t sz = prefix ? strlen(prefix) : 0;
|
227
|
+
|
228
|
+
if (s && sz && strncmp(s, prefix, sz) == 0)
|
229
|
+
return s + sz;
|
230
|
+
return NULL;
|
231
|
+
}
|
232
|
+
|
233
|
+
/*
|
234
|
+
* Case insensitive match string beginning.
|
235
|
+
*/
|
236
|
+
static inline const char *startswith_no_case(const char *s, const char *prefix)
|
237
|
+
{
|
238
|
+
size_t sz = prefix ? strlen(prefix) : 0;
|
239
|
+
|
240
|
+
if (s && sz && strncasecmp(s, prefix, sz) == 0)
|
241
|
+
return s + sz;
|
242
|
+
return NULL;
|
243
|
+
}
|
244
|
+
|
245
|
+
/*
|
246
|
+
* Match string ending.
|
247
|
+
*/
|
248
|
+
static inline const char *endswith(const char *s, const char *postfix)
|
249
|
+
{
|
250
|
+
size_t sl = s ? strlen(s) : 0;
|
251
|
+
size_t pl = postfix ? strlen(postfix) : 0;
|
252
|
+
|
253
|
+
if (pl == 0)
|
254
|
+
return s + sl;
|
255
|
+
if (sl < pl)
|
256
|
+
return NULL;
|
257
|
+
if (memcmp(s + sl - pl, postfix, pl) != 0)
|
258
|
+
return NULL;
|
259
|
+
return s + sl - pl;
|
260
|
+
}
|
261
|
+
|
262
|
+
/*
|
263
|
+
* Skip leading white space.
|
264
|
+
*/
|
265
|
+
static inline const char *skip_space(const char *p)
|
266
|
+
{
|
267
|
+
while (isspace(*p))
|
268
|
+
++p;
|
269
|
+
return p;
|
270
|
+
}
|
271
|
+
|
272
|
+
static inline const char *skip_blank(const char *p)
|
273
|
+
{
|
274
|
+
while (isblank(*p))
|
275
|
+
++p;
|
276
|
+
return p;
|
277
|
+
}
|
278
|
+
|
279
|
+
|
280
|
+
/* Removes whitespace from the right-hand side of a string (trailing
|
281
|
+
* whitespace).
|
282
|
+
*
|
283
|
+
* Returns size of the new string (without \0).
|
284
|
+
*/
|
285
|
+
static inline size_t rtrim_whitespace(unsigned char *str)
|
286
|
+
{
|
287
|
+
size_t i;
|
288
|
+
|
289
|
+
if (!str)
|
290
|
+
return 0;
|
291
|
+
i = strlen((char *) str);
|
292
|
+
while (i) {
|
293
|
+
i--;
|
294
|
+
if (!isspace(str[i])) {
|
295
|
+
i++;
|
296
|
+
break;
|
297
|
+
}
|
298
|
+
}
|
299
|
+
str[i] = '\0';
|
300
|
+
return i;
|
301
|
+
}
|
302
|
+
|
303
|
+
/* Removes whitespace from the left-hand side of a string.
|
304
|
+
*
|
305
|
+
* Returns size of the new string (without \0).
|
306
|
+
*/
|
307
|
+
static inline size_t ltrim_whitespace(unsigned char *str)
|
308
|
+
{
|
309
|
+
size_t len;
|
310
|
+
unsigned char *p;
|
311
|
+
|
312
|
+
if (!str)
|
313
|
+
return 0;
|
314
|
+
for (p = str; *p && isspace(*p); p++);
|
315
|
+
|
316
|
+
len = strlen((char *) p);
|
317
|
+
|
318
|
+
if (p > str)
|
319
|
+
memmove(str, p, len + 1);
|
320
|
+
|
321
|
+
return len;
|
322
|
+
}
|
323
|
+
|
324
|
+
/* Removes left-hand, right-hand and repeating whitespaces.
|
325
|
+
*/
|
326
|
+
static inline size_t __normalize_whitespace(
|
327
|
+
const unsigned char *src,
|
328
|
+
size_t sz,
|
329
|
+
unsigned char *dst,
|
330
|
+
size_t len)
|
331
|
+
{
|
332
|
+
size_t i, x = 0;
|
333
|
+
int nsp = 0, intext = 0;
|
334
|
+
|
335
|
+
if (!sz)
|
336
|
+
goto done;
|
337
|
+
|
338
|
+
for (i = 0, x = 0; i < sz && x < len - 1; ) {
|
339
|
+
if (isspace(src[i]))
|
340
|
+
nsp++;
|
341
|
+
else
|
342
|
+
nsp = 0, intext = 1;
|
343
|
+
|
344
|
+
if (nsp > 1 || (nsp && !intext))
|
345
|
+
i++;
|
346
|
+
else
|
347
|
+
dst[x++] = src[i++];
|
348
|
+
}
|
349
|
+
if (nsp && x > 0) /* tailing space */
|
350
|
+
x--;
|
351
|
+
done:
|
352
|
+
dst[x] = '\0';
|
353
|
+
return x;
|
354
|
+
}
|
355
|
+
|
356
|
+
static inline size_t normalize_whitespace(unsigned char *str)
|
357
|
+
{
|
358
|
+
size_t sz = strlen((char *) str);
|
359
|
+
return __normalize_whitespace(str, sz, str, sz + 1);
|
360
|
+
}
|
361
|
+
|
362
|
+
static inline void strrep(char *s, int find, int replace)
|
363
|
+
{
|
364
|
+
while (s && *s && (s = strchr(s, find)) != NULL)
|
365
|
+
*s++ = replace;
|
366
|
+
}
|
367
|
+
|
368
|
+
static inline void strrem(char *s, int rem)
|
369
|
+
{
|
370
|
+
char *p;
|
371
|
+
|
372
|
+
if (!s)
|
373
|
+
return;
|
374
|
+
for (p = s; *s; s++) {
|
375
|
+
if (*s != rem)
|
376
|
+
*p++ = *s;
|
377
|
+
}
|
378
|
+
*p = '\0';
|
379
|
+
}
|
380
|
+
|
381
|
+
extern char *strnconcat(const char *s, const char *suffix, size_t b);
|
382
|
+
extern char *strconcat(const char *s, const char *suffix);
|
383
|
+
extern char *strfconcat(const char *s, const char *format, ...)
|
384
|
+
__attribute__ ((__format__ (__printf__, 2, 3)));
|
385
|
+
|
386
|
+
extern int strappend(char **a, const char *b);
|
387
|
+
|
388
|
+
extern const char *split(const char **state, size_t *l, const char *separator, int quoted);
|
389
|
+
|
390
|
+
extern int skip_fline(FILE *fp);
|
391
|
+
extern int ul_stralnumcmp(const char *p1, const char *p2);
|
392
|
+
|
393
|
+
#endif
|