summaryrefslogtreecommitdiff
path: root/src/misc
diff options
context:
space:
mode:
Diffstat (limited to 'src/misc')
-rw-r--r--src/misc/getentropy.c2
-rw-r--r--src/misc/getopt.c3
-rw-r--r--src/misc/getrlimit.c8
-rw-r--r--src/misc/initgroups.c26
-rw-r--r--src/misc/ioctl.c149
-rw-r--r--src/misc/lockf.c2
-rw-r--r--src/misc/mntent.c56
-rw-r--r--src/misc/nftw.c28
-rw-r--r--src/misc/realpath.c159
-rw-r--r--src/misc/setrlimit.c45
-rw-r--r--src/misc/syslog.c5
11 files changed, 395 insertions, 88 deletions
diff --git a/src/misc/getentropy.c b/src/misc/getentropy.c
index d2f282ce..651ea95f 100644
--- a/src/misc/getentropy.c
+++ b/src/misc/getentropy.c
@@ -6,7 +6,7 @@
int getentropy(void *buffer, size_t len)
{
- int cs, ret;
+ int cs, ret = 0;
char *pos = buffer;
if (len > 256) {
diff --git a/src/misc/getopt.c b/src/misc/getopt.c
index c3f66995..b02b81c3 100644
--- a/src/misc/getopt.c
+++ b/src/misc/getopt.c
@@ -87,7 +87,8 @@ int getopt(int argc, char * const argv[], const char *optstring)
if (optstring[i] == ':') {
optarg = 0;
if (optstring[i+1] != ':' || optpos) {
- optarg = argv[optind++] + optpos;
+ optarg = argv[optind++];
+ if (optpos) optarg += optpos;
optpos = 0;
}
if (optind > argc) {
diff --git a/src/misc/getrlimit.c b/src/misc/getrlimit.c
index 2ab2f0f4..a5558d81 100644
--- a/src/misc/getrlimit.c
+++ b/src/misc/getrlimit.c
@@ -6,12 +6,13 @@
int getrlimit(int resource, struct rlimit *rlim)
{
- unsigned long k_rlim[2];
int ret = syscall(SYS_prlimit64, 0, resource, 0, rlim);
if (!ret) {
FIX(rlim->rlim_cur);
FIX(rlim->rlim_max);
}
+#ifdef SYS_getrlimit
+ unsigned long k_rlim[2];
if (!ret || errno != ENOSYS)
return ret;
if (syscall(SYS_getrlimit, resource, k_rlim) < 0)
@@ -21,6 +22,7 @@ int getrlimit(int resource, struct rlimit *rlim)
FIX(rlim->rlim_cur);
FIX(rlim->rlim_max);
return 0;
+#else
+ return ret;
+#endif
}
-
-weak_alias(getrlimit, getrlimit64);
diff --git a/src/misc/initgroups.c b/src/misc/initgroups.c
index 922a9581..101f5c7b 100644
--- a/src/misc/initgroups.c
+++ b/src/misc/initgroups.c
@@ -1,11 +1,29 @@
#define _GNU_SOURCE
#include <grp.h>
#include <limits.h>
+#include <stdlib.h>
int initgroups(const char *user, gid_t gid)
{
- gid_t groups[NGROUPS_MAX];
- int count = NGROUPS_MAX;
- if (getgrouplist(user, gid, groups, &count) < 0) return -1;
- return setgroups(count, groups);
+ gid_t buf[32], *groups = buf;
+ int count = sizeof buf / sizeof *buf, prev_count = count;
+ while (getgrouplist(user, gid, groups, &count) < 0) {
+ if (groups != buf) free(groups);
+
+ /* Return if failure isn't buffer size */
+ if (count <= prev_count)
+ return -1;
+
+ /* Always increase by at least 50% to limit to
+ * logarithmically many retries on TOCTOU races. */
+ if (count < prev_count + (prev_count>>1))
+ count = prev_count + (prev_count>>1);
+
+ groups = calloc(count, sizeof *groups);
+ if (!groups) return -1;
+ prev_count = count;
+ }
+ int ret = setgroups(count, groups);
+ if (groups != buf) free(groups);
+ return ret;
}
diff --git a/src/misc/ioctl.c b/src/misc/ioctl.c
index 6f31d4bc..35804f02 100644
--- a/src/misc/ioctl.c
+++ b/src/misc/ioctl.c
@@ -3,8 +3,128 @@
#include <errno.h>
#include <time.h>
#include <sys/time.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <endian.h>
#include "syscall.h"
+#define alignof(t) offsetof(struct { char c; t x; }, x)
+
+#define W 1
+#define R 2
+#define WR 3
+
+struct ioctl_compat_map {
+ int new_req, old_req;
+ unsigned char old_size, dir, force_align, noffs;
+ unsigned char offsets[8];
+};
+
+#define NINTH(a,b,c,d,e,f,g,h,i,...) i
+#define COUNT(...) NINTH(__VA_ARGS__,8,7,6,5,4,3,2,1,0)
+#define OFFS(...) COUNT(__VA_ARGS__), { __VA_ARGS__ }
+
+/* yields a type for a struct with original size n, with a misaligned
+ * timeval/timespec expanded from 32- to 64-bit. for use with ioctl
+ * number producing macros; only size of result is meaningful. */
+#define new_misaligned(n) struct { int i; time_t t; char c[(n)-4]; }
+
+struct v4l2_event {
+ uint32_t a;
+ uint64_t b[8];
+ uint32_t c[2], ts[2], d[9];
+};
+
+static const struct ioctl_compat_map compat_map[] = {
+ { SIOCGSTAMP, SIOCGSTAMP_OLD, 8, R, 0, OFFS(0, 4) },
+ { SIOCGSTAMPNS, SIOCGSTAMPNS_OLD, 8, R, 0, OFFS(0, 4) },
+
+ /* SNDRV_TIMER_IOCTL_STATUS */
+ { _IOR('T', 0x14, char[96]), _IOR('T', 0x14, 88), 88, R, 0, OFFS(0,4) },
+
+ /* SNDRV_PCM_IOCTL_STATUS[_EXT] */
+ { _IOR('A', 0x20, char[128]), _IOR('A', 0x20, char[108]), 108, R, 1, OFFS(4,8,12,16,52,56,60,64) },
+ { _IOWR('A', 0x24, char[128]), _IOWR('A', 0x24, char[108]), 108, WR, 1, OFFS(4,8,12,16,52,56,60,64) },
+
+ /* SNDRV_RAWMIDI_IOCTL_STATUS */
+ { _IOWR('W', 0x20, char[48]), _IOWR('W', 0x20, char[36]), 36, WR, 1, OFFS(4,8) },
+
+ /* SNDRV_PCM_IOCTL_SYNC_PTR - with 3 subtables */
+ { _IOWR('A', 0x23, char[136]), _IOWR('A', 0x23, char[132]), 0, WR, 1, 0 },
+ { 0, 0, 4, WR, 1, 0 }, /* snd_pcm_sync_ptr (flags only) */
+ { 0, 0, 32, WR, 1, OFFS(8,12,16,24,28) }, /* snd_pcm_mmap_status */
+ { 0, 0, 4, WR, 1, 0 }, /* snd_pcm_mmap_control (each member) */
+
+ /* VIDIOC_QUERYBUF, VIDIOC_QBUF, VIDIOC_DQBUF, VIDIOC_PREPARE_BUF */
+ { _IOWR('V', 9, new_misaligned(68)), _IOWR('V', 9, char[68]), 68, WR, 1, OFFS(20, 24) },
+ { _IOWR('V', 15, new_misaligned(68)), _IOWR('V', 15, char[68]), 68, WR, 1, OFFS(20, 24) },
+ { _IOWR('V', 17, new_misaligned(68)), _IOWR('V', 17, char[68]), 68, WR, 1, OFFS(20, 24) },
+ { _IOWR('V', 93, new_misaligned(68)), _IOWR('V', 93, char[68]), 68, WR, 1, OFFS(20, 24) },
+
+ /* VIDIOC_DQEVENT */
+ { _IOR('V', 89, new_misaligned(120)), _IOR('V', 89, struct v4l2_event), sizeof(struct v4l2_event),
+ R, 0, OFFS(offsetof(struct v4l2_event, ts[0]), offsetof(struct v4l2_event, ts[1])) },
+
+ /* VIDIOC_OMAP3ISP_STAT_REQ */
+ { _IOWR('V', 192+6, char[32]), _IOWR('V', 192+6, char[24]), 22, WR, 0, OFFS(0,4) },
+
+ /* PPPIOCGIDLE */
+ { _IOR('t', 63, char[16]), _IOR('t', 63, char[8]), 8, R, 0, OFFS(0,4) },
+
+ /* PPGETTIME, PPSETTIME */
+ { _IOR('p', 0x95, char[16]), _IOR('p', 0x95, char[8]), 8, R, 0, OFFS(0,4) },
+ { _IOW('p', 0x96, char[16]), _IOW('p', 0x96, char[8]), 8, W, 0, OFFS(0,4) },
+
+ /* LPSETTIMEOUT */
+ { _IOW(0x6, 0xf, char[16]), 0x060f, 8, W, 0, OFFS(0,4) },
+};
+
+static void convert_ioctl_struct(const struct ioctl_compat_map *map, char *old, char *new, int dir)
+{
+ int new_offset = 0;
+ int old_offset = 0;
+ int old_size = map->old_size;
+ if (!(dir & map->dir)) return;
+ if (!map->old_size) {
+ /* offsets hard-coded for SNDRV_PCM_IOCTL_SYNC_PTR;
+ * if another exception appears this needs changing. */
+ convert_ioctl_struct(map+1, old, new, dir);
+ convert_ioctl_struct(map+2, old+4, new+8, dir);
+ /* snd_pcm_mmap_control, special-cased due to kernel
+ * type definition having been botched. */
+ int adj = BYTE_ORDER==BIG_ENDIAN ? 4 : 0;
+ convert_ioctl_struct(map+3, old+68, new+72+adj, dir);
+ convert_ioctl_struct(map+3, old+72, new+76+3*adj, dir);
+ return;
+ }
+ for (int i=0; i < map->noffs; i++) {
+ int ts_offset = map->offsets[i];
+ int len = ts_offset-old_offset;
+ if (dir==W) memcpy(old+old_offset, new+new_offset, len);
+ else memcpy(new+new_offset, old+old_offset, len);
+ new_offset += len;
+ old_offset += len;
+ long long new_ts;
+ long old_ts;
+ int align = map->force_align ? sizeof(time_t) : alignof(time_t);
+ new_offset += (align-1) & -new_offset;
+ if (dir==W) {
+ memcpy(&new_ts, new+new_offset, sizeof new_ts);
+ old_ts = new_ts;
+ memcpy(old+old_offset, &old_ts, sizeof old_ts);
+ } else {
+ memcpy(&old_ts, old+old_offset, sizeof old_ts);
+ new_ts = old_ts;
+ memcpy(new+new_offset, &new_ts, sizeof new_ts);
+ }
+ new_offset += sizeof new_ts;
+ old_offset += sizeof old_ts;
+ }
+ if (dir==W) memcpy(old+old_offset, new+new_offset, old_size-old_offset);
+ else memcpy(new+new_offset, old+old_offset, old_size-old_offset);
+}
+
int ioctl(int fd, int req, ...)
{
void *arg;
@@ -13,23 +133,18 @@ int ioctl(int fd, int req, ...)
arg = va_arg(ap, void *);
va_end(ap);
int r = __syscall(SYS_ioctl, fd, req, arg);
- if (r==-ENOTTY) switch (req) {
- case SIOCGSTAMP:
- case SIOCGSTAMPNS:
- if (SIOCGSTAMP==SIOCGSTAMP_OLD) break;
- if (req==SIOCGSTAMP) req=SIOCGSTAMP_OLD;
- if (req==SIOCGSTAMPNS) req=SIOCGSTAMPNS_OLD;
- long t32[2];
- r = __syscall(SYS_ioctl, fd, req, t32);
- if (r<0) break;
- if (req==SIOCGSTAMP_OLD) {
- struct timeval *tv = arg;
- tv->tv_sec = t32[0];
- tv->tv_usec = t32[1];
- } else {
- struct timespec *ts = arg;
- ts->tv_sec = t32[0];
- ts->tv_nsec = t32[1];
+ if (SIOCGSTAMP != SIOCGSTAMP_OLD && req && r==-ENOTTY) {
+ for (int i=0; i<sizeof compat_map/sizeof *compat_map; i++) {
+ if (compat_map[i].new_req != req) continue;
+ union {
+ long long align;
+ char buf[256];
+ } u;
+ convert_ioctl_struct(&compat_map[i], u.buf, arg, W);
+ r = __syscall(SYS_ioctl, fd, compat_map[i].old_req, u.buf);
+ if (r<0) break;
+ convert_ioctl_struct(&compat_map[i], u.buf, arg, R);
+ break;
}
}
return __syscall_ret(r);
diff --git a/src/misc/lockf.c b/src/misc/lockf.c
index 16a80bec..0162442b 100644
--- a/src/misc/lockf.c
+++ b/src/misc/lockf.c
@@ -28,5 +28,3 @@ int lockf(int fd, int op, off_t size)
errno = EINVAL;
return -1;
}
-
-weak_alias(lockf, lockf64);
diff --git a/src/misc/mntent.c b/src/misc/mntent.c
index eabb8200..78bf0cd0 100644
--- a/src/misc/mntent.c
+++ b/src/misc/mntent.c
@@ -2,6 +2,7 @@
#include <string.h>
#include <mntent.h>
#include <errno.h>
+#include <limits.h>
static char *internal_buf;
static size_t internal_bufsize;
@@ -19,9 +20,46 @@ int endmntent(FILE *f)
return 1;
}
+static char *unescape_ent(char *beg)
+{
+ char *dest = beg;
+ const char *src = beg;
+ while (*src) {
+ const char *val;
+ unsigned char cval = 0;
+ if (*src != '\\') {
+ *dest++ = *src++;
+ continue;
+ }
+ if (src[1] == '\\') {
+ ++src;
+ *dest++ = *src++;
+ continue;
+ }
+ val = src + 1;
+ for (int i = 0; i < 3; ++i) {
+ if (*val >= '0' && *val <= '7') {
+ cval <<= 3;
+ cval += *val++ - '0';
+ } else {
+ break;
+ }
+ }
+ if (cval) {
+ *dest++ = cval;
+ src = val;
+ } else {
+ *dest++ = *src++;
+ }
+ }
+ *dest = 0;
+ return beg;
+}
+
struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen)
{
- int cnt, n[8], use_internal = (linebuf == SENTINEL);
+ int n[8], use_internal = (linebuf == SENTINEL);
+ size_t len, i;
mnt->mnt_freq = 0;
mnt->mnt_passno = 0;
@@ -39,20 +77,24 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle
errno = ERANGE;
return 0;
}
- cnt = sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
+
+ len = strlen(linebuf);
+ if (len > INT_MAX) continue;
+ for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len;
+ sscanf(linebuf, " %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %d %d",
n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
&mnt->mnt_freq, &mnt->mnt_passno);
- } while (cnt < 2 || linebuf[n[0]] == '#');
+ } while (linebuf[n[0]] == '#' || n[1]==len);
linebuf[n[1]] = 0;
linebuf[n[3]] = 0;
linebuf[n[5]] = 0;
linebuf[n[7]] = 0;
- mnt->mnt_fsname = linebuf+n[0];
- mnt->mnt_dir = linebuf+n[2];
- mnt->mnt_type = linebuf+n[4];
- mnt->mnt_opts = linebuf+n[6];
+ mnt->mnt_fsname = unescape_ent(linebuf+n[0]);
+ mnt->mnt_dir = unescape_ent(linebuf+n[2]);
+ mnt->mnt_type = unescape_ent(linebuf+n[4]);
+ mnt->mnt_opts = unescape_ent(linebuf+n[6]);
return mnt;
}
diff --git a/src/misc/nftw.c b/src/misc/nftw.c
index 0a464100..71bc62ee 100644
--- a/src/misc/nftw.c
+++ b/src/misc/nftw.c
@@ -1,5 +1,6 @@
#include <ftw.h>
#include <dirent.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
@@ -26,16 +27,19 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
struct history new;
int type;
int r;
+ int dfd;
+ int err;
struct FTW lev;
+ st.st_dev = st.st_ino = 0;
+
if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st))
type = FTW_SLN;
else if (errno != EACCES) return -1;
else type = FTW_NS;
} else if (S_ISDIR(st.st_mode)) {
- if (access(path, R_OK) < 0) type = FTW_DNR;
- else if (flags & FTW_DEPTH) type = FTW_DP;
+ if (flags & FTW_DEPTH) type = FTW_DP;
else type = FTW_D;
} else if (S_ISLNK(st.st_mode)) {
if (flags & FTW_PHYS) type = FTW_SL;
@@ -44,7 +48,7 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
type = FTW_F;
}
- if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev)
+ if ((flags & FTW_MOUNT) && h && type != FTW_NS && st.st_dev != h->dev)
return 0;
new.chain = h;
@@ -63,6 +67,13 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
lev.base = k;
}
+ if (type == FTW_D || type == FTW_DP) {
+ dfd = open(path, O_RDONLY);
+ err = errno;
+ if (dfd < 0 && err == EACCES) type = FTW_DNR;
+ if (!fd_limit) close(dfd);
+ }
+
if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
return r;
@@ -71,7 +82,11 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
return 0;
if ((type == FTW_D || type == FTW_DP) && fd_limit) {
- DIR *d = opendir(path);
+ if (dfd < 0) {
+ errno = err;
+ return -1;
+ }
+ DIR *d = fdopendir(dfd);
if (d) {
struct dirent *de;
while ((de = readdir(d))) {
@@ -92,7 +107,8 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
}
}
closedir(d);
- } else if (errno != EACCES) {
+ } else {
+ close(dfd);
return -1;
}
}
@@ -124,5 +140,3 @@ int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, str
pthread_setcancelstate(cs, 0);
return r;
}
-
-weak_alias(nftw, nftw64);
diff --git a/src/misc/realpath.c b/src/misc/realpath.c
index d2708e59..db8b74dc 100644
--- a/src/misc/realpath.c
+++ b/src/misc/realpath.c
@@ -1,43 +1,156 @@
#include <stdlib.h>
#include <limits.h>
-#include <sys/stat.h>
-#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
-#include "syscall.h"
+
+static size_t slash_len(const char *s)
+{
+ const char *s0 = s;
+ while (*s == '/') s++;
+ return s-s0;
+}
char *realpath(const char *restrict filename, char *restrict resolved)
{
- int fd;
- ssize_t r;
- struct stat st1, st2;
- char buf[15+3*sizeof(int)];
- char tmp[PATH_MAX];
+ char stack[PATH_MAX+1];
+ char output[PATH_MAX];
+ size_t p, q, l, l0, cnt=0, nup=0;
+ int check_dir=0;
if (!filename) {
errno = EINVAL;
return 0;
}
+ l = strnlen(filename, sizeof stack);
+ if (!l) {
+ errno = ENOENT;
+ return 0;
+ }
+ if (l >= PATH_MAX) goto toolong;
+ p = sizeof stack - l - 1;
+ q = 0;
+ memcpy(stack+p, filename, l+1);
+
+ /* Main loop. Each iteration pops the next part from stack of
+ * remaining path components and consumes any slashes that follow.
+ * If not a link, it's moved to output; if a link, contents are
+ * pushed to the stack. */
+restart:
+ for (; ; p+=slash_len(stack+p)) {
+ /* If stack starts with /, the whole component is / or //
+ * and the output state must be reset. */
+ if (stack[p] == '/') {
+ check_dir=0;
+ nup=0;
+ q=0;
+ output[q++] = '/';
+ p++;
+ /* Initial // is special. */
+ if (stack[p] == '/' && stack[p+1] != '/')
+ output[q++] = '/';
+ continue;
+ }
+
+ char *z = __strchrnul(stack+p, '/');
+ l0 = l = z-(stack+p);
- fd = sys_open(filename, O_PATH|O_NONBLOCK|O_CLOEXEC);
- if (fd < 0) return 0;
- __procfdname(buf, fd);
+ if (!l && !check_dir) break;
- r = readlink(buf, tmp, sizeof tmp - 1);
- if (r < 0) goto err;
- tmp[r] = 0;
+ /* Skip any . component but preserve check_dir status. */
+ if (l==1 && stack[p]=='.') {
+ p += l;
+ continue;
+ }
- fstat(fd, &st1);
- r = stat(tmp, &st2);
- if (r<0 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
- if (!r) errno = ELOOP;
- goto err;
+ /* Copy next component onto output at least temporarily, to
+ * call readlink, but wait to advance output position until
+ * determining it's not a link. */
+ if (q && output[q-1] != '/') {
+ if (!p) goto toolong;
+ stack[--p] = '/';
+ l++;
+ }
+ if (q+l >= PATH_MAX) goto toolong;
+ memcpy(output+q, stack+p, l);
+ output[q+l] = 0;
+ p += l;
+
+ int up = 0;
+ if (l0==2 && stack[p-2]=='.' && stack[p-1]=='.') {
+ up = 1;
+ /* Any non-.. path components we could cancel start
+ * after nup repetitions of the 3-byte string "../";
+ * if there are none, accumulate .. components to
+ * later apply to cwd, if needed. */
+ if (q <= 3*nup) {
+ nup++;
+ q += l;
+ continue;
+ }
+ /* When previous components are already known to be
+ * directories, processing .. can skip readlink. */
+ if (!check_dir) goto skip_readlink;
+ }
+ ssize_t k = readlink(output, stack, p);
+ if (k==p) goto toolong;
+ if (!k) {
+ errno = ENOENT;
+ return 0;
+ }
+ if (k<0) {
+ if (errno != EINVAL) return 0;
+skip_readlink:
+ check_dir = 0;
+ if (up) {
+ while(q && output[q-1]!='/') q--;
+ if (q>1 && (q>2 || output[0]!='/')) q--;
+ continue;
+ }
+ if (l0) q += l;
+ check_dir = stack[p];
+ continue;
+ }
+ if (++cnt == SYMLOOP_MAX) {
+ errno = ELOOP;
+ return 0;
+ }
+
+ /* If link contents end in /, strip any slashes already on
+ * stack to avoid /->// or //->/// or spurious toolong. */
+ if (stack[k-1]=='/') while (stack[p]=='/') p++;
+ p -= k;
+ memmove(stack+p, stack, k);
+
+ /* Skip the stack advancement in case we have a new
+ * absolute base path. */
+ goto restart;
}
- __syscall(SYS_close, fd);
- return resolved ? strcpy(resolved, tmp) : strdup(tmp);
-err:
- __syscall(SYS_close, fd);
+ output[q] = 0;
+
+ if (output[0] != '/') {
+ if (!getcwd(stack, sizeof stack)) return 0;
+ l = strlen(stack);
+ /* Cancel any initial .. components. */
+ p = 0;
+ while (nup--) {
+ while(l>1 && stack[l-1]!='/') l--;
+ if (l>1) l--;
+ p += 2;
+ if (p<q) p++;
+ }
+ if (q-p && stack[l-1]!='/') stack[l++] = '/';
+ if (l + (q-p) + 1 >= PATH_MAX) goto toolong;
+ memmove(output + l, output + p, q - p + 1);
+ memcpy(output, stack, l);
+ q = l + q-p;
+ }
+
+ if (resolved) return memcpy(resolved, output, q+1);
+ else return strdup(output);
+
+toolong:
+ errno = ENAMETOOLONG;
return 0;
}
diff --git a/src/misc/setrlimit.c b/src/misc/setrlimit.c
index 7a66ab29..edb413fa 100644
--- a/src/misc/setrlimit.c
+++ b/src/misc/setrlimit.c
@@ -6,45 +6,46 @@
#define MIN(a, b) ((a)<(b) ? (a) : (b))
#define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0)
-static int __setrlimit(int resource, const struct rlimit *rlim)
-{
- unsigned long k_rlim[2];
- struct rlimit tmp;
- if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
- tmp = *rlim;
- FIX(tmp.rlim_cur);
- FIX(tmp.rlim_max);
- rlim = &tmp;
- }
- int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
- if (ret != -ENOSYS) return ret;
- k_rlim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY));
- k_rlim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY));
- return __syscall(SYS_setrlimit, resource, k_rlim);
-}
-
struct ctx {
- const struct rlimit *rlim;
+ unsigned long lim[2];
int res;
int err;
};
+#ifdef SYS_setrlimit
static void do_setrlimit(void *p)
{
struct ctx *c = p;
if (c->err>0) return;
- c->err = -__setrlimit(c->res, c->rlim);
+ c->err = -__syscall(SYS_setrlimit, c->res, c->lim);
}
+#endif
int setrlimit(int resource, const struct rlimit *rlim)
{
- struct ctx c = { .res = resource, .rlim = rlim, .err = -1 };
+ struct rlimit tmp;
+ if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
+ tmp = *rlim;
+ FIX(tmp.rlim_cur);
+ FIX(tmp.rlim_max);
+ rlim = &tmp;
+ }
+ int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
+#ifdef SYS_setrlimit
+ if (ret != -ENOSYS) return __syscall_ret(ret);
+
+ struct ctx c = {
+ .lim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY)),
+ .lim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY)),
+ .res = resource, .err = -1
+ };
__synccall(do_setrlimit, &c);
if (c.err) {
if (c.err>0) errno = c.err;
return -1;
}
return 0;
+#else
+ return __syscall_ret(ret);
+#endif
}
-
-weak_alias(setrlimit, setrlimit64);
diff --git a/src/misc/syslog.c b/src/misc/syslog.c
index 13d4b0a6..710202f9 100644
--- a/src/misc/syslog.c
+++ b/src/misc/syslog.c
@@ -10,6 +10,8 @@
#include <errno.h>
#include <fcntl.h>
#include "lock.h"
+#include "fork_impl.h"
+#include "locale_impl.h"
static volatile int lock[1];
static char log_ident[32];
@@ -17,6 +19,7 @@ static int log_opt;
static int log_facility = LOG_USER;
static int log_mask = 0xff;
static int log_fd = -1;
+volatile int *const __syslog_lockptr = lock;
int setlogmask(int maskpri)
{
@@ -97,7 +100,7 @@ static void _vsyslog(int priority, const char *message, va_list ap)
now = time(NULL);
gmtime_r(&now, &tm);
- strftime(timebuf, sizeof timebuf, "%b %e %T", &tm);
+ strftime_l(timebuf, sizeof timebuf, "%b %e %T", &tm, C_LOCALE);
pid = (log_opt & LOG_PID) ? getpid() : 0;
l = snprintf(buf, sizeof buf, "<%d>%s %n%s%s%.0d%s: ",