runshare 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|