aboutsummaryrefslogtreecommitdiff
path: root/lib/lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lib.c')
-rw-r--r--lib/lib.c469
1 files changed, 1 insertions, 468 deletions
diff --git a/lib/lib.c b/lib/lib.c
index af347ca5..52c95147 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -1,28 +1,10 @@
-/* lib.c - reusable stuff.
- *
- * Functions with the x prefix are wrappers for library functions. They either
- * succeed or kill the program with an error message, but never return failure.
- * They usually have the same arguments and return value as the function they
- * wrap.
+/* lib.c - various reusable stuff.
*
* Copyright 2006 Rob Landley <rob@landley.net>
*/
#include "toys.h"
-// Strcpy with size checking: exit if there's not enough space for the string.
-void xstrncpy(char *dest, char *src, size_t size)
-{
- if (strlen(src)+1 > size) error_exit("xstrcpy");
- strcpy(dest, src);
-}
-
-void xexit(void)
-{
- if (toys.rebound) longjmp(*toys.rebound, 1);
- else exit(toys.exitval);
-}
-
void verror_msg(char *msg, int err, va_list va)
{
char *s = ": %s";
@@ -67,7 +49,6 @@ void error_exit(char *msg, ...)
xexit();
}
-
// Die with an error message and strerror(errno)
void perror_exit(char *msg, ...)
{
@@ -80,153 +61,6 @@ void perror_exit(char *msg, ...)
xexit();
}
-// Die unless we can allocate memory.
-void *xmalloc(size_t size)
-{
- void *ret = malloc(size);
- if (!ret) error_exit("xmalloc");
-
- return ret;
-}
-
-// Die unless we can allocate prezeroed memory.
-void *xzalloc(size_t size)
-{
- void *ret = xmalloc(size);
- memset(ret, 0, size);
- return ret;
-}
-
-// Die unless we can change the size of an existing allocation, possibly
-// moving it. (Notice different arguments from libc function.)
-void *xrealloc(void *ptr, size_t size)
-{
- ptr = realloc(ptr, size);
- if (!ptr) error_exit("xrealloc");
-
- return ptr;
-}
-
-// Die unless we can allocate a copy of this many bytes of string.
-char *xstrndup(char *s, size_t n)
-{
- char *ret = xmalloc(++n);
- strncpy(ret, s, n);
- ret[--n]=0;
-
- return ret;
-}
-
-// Die unless we can allocate a copy of this string.
-char *xstrdup(char *s)
-{
- return xstrndup(s, strlen(s));
-}
-
-// Die unless we can allocate enough space to sprintf() into.
-char *xmsprintf(char *format, ...)
-{
- va_list va, va2;
- int len;
- char *ret;
-
- va_start(va, format);
- va_copy(va2, va);
-
- // How long is it?
- len = vsnprintf(0, 0, format, va);
- len++;
- va_end(va);
-
- // Allocate and do the sprintf()
- ret = xmalloc(len);
- vsnprintf(ret, len, format, va2);
- va_end(va2);
-
- return ret;
-}
-
-void xprintf(char *format, ...)
-{
- va_list va;
- va_start(va, format);
-
- vprintf(format, va);
- if (ferror(stdout)) perror_exit("write");
-}
-
-void xputs(char *s)
-{
- if (EOF == puts(s) || fflush(stdout)) perror_exit("write");
-}
-
-void xputc(char c)
-{
- if (EOF == fputc(c, stdout) || fflush(stdout)) perror_exit("write");
-}
-
-void xflush(void)
-{
- if (fflush(stdout)) perror_exit("write");;
-}
-
-// Die unless we can exec argv[] (or run builtin command). Note that anything
-// with a path isn't a builtin, so /bin/sh won't match the builtin sh.
-void xexec(char **argv)
-{
- toy_exec(argv);
- execvp(argv[0], argv);
-
- perror_exit("exec %s", argv[0]);
-}
-
-void xaccess(char *path, int flags)
-{
- if (access(path, flags)) perror_exit("Can't access '%s'", path);
-}
-
-// Die unless we can delete a file. (File must exist to be deleted.)
-void xunlink(char *path)
-{
- if (unlink(path)) perror_exit("unlink '%s'", path);
-}
-
-// Die unless we can open/create a file, returning file descriptor.
-int xcreate(char *path, int flags, int mode)
-{
- int fd = open(path, flags, mode);
- if (fd == -1) perror_exit("%s", path);
- return fd;
-}
-
-// Die unless we can open a file, returning file descriptor.
-int xopen(char *path, int flags)
-{
- return xcreate(path, flags, 0);
-}
-
-void xclose(int fd)
-{
- if (close(fd)) perror_exit("xclose");
-}
-
-int xdup(int fd)
-{
- if (fd != -1) {
- fd = dup(fd);
- if (fd == -1) perror_exit("xdup");
- }
- return fd;
-}
-
-// Die unless we can open/create a file, returning FILE *.
-FILE *xfopen(char *path, char *mode)
-{
- FILE *f = fopen(path, mode);
- if (!f) perror_exit("No file %s", path);
- return f;
-}
-
// Keep reading until full or EOF
ssize_t readall(int fd, void *buf, size_t len)
{
@@ -255,39 +89,6 @@ ssize_t writeall(int fd, void *buf, size_t len)
return count;
}
-// Die if there's an error other than EOF.
-size_t xread(int fd, void *buf, size_t len)
-{
- ssize_t ret = read(fd, buf, len);
- if (ret < 0) perror_exit("xread");
-
- return ret;
-}
-
-void xreadall(int fd, void *buf, size_t len)
-{
- if (len != readall(fd, buf, len)) perror_exit("xreadall");
-}
-
-// There's no xwriteall(), just xwrite(). When we read, there may or may not
-// be more data waiting. When we write, there is data and it had better go
-// somewhere.
-
-void xwrite(int fd, void *buf, size_t len)
-{
- if (len != writeall(fd, buf, len)) perror_exit("xwrite");
-}
-
-// Die if lseek fails, probably due to being called on a pipe.
-
-off_t xlseek(int fd, off_t offset, int whence)
-{
- offset = lseek(fd, offset, whence);
- if (offset<0) perror_exit("lseek");
-
- return offset;
-}
-
off_t lskip(int fd, off_t offset)
{
off_t and = lseek(fd, offset, SEEK_CUR);
@@ -309,19 +110,6 @@ off_t lskip(int fd, off_t offset)
}
}
-char *xgetcwd(void)
-{
- char *buf = getcwd(NULL, 0);
- if (!buf) perror_exit("xgetcwd");
-
- return buf;
-}
-
-void xstat(char *path, struct stat *st)
-{
- if(stat(path, st)) perror_exit("Can't stat %s", path);
-}
-
// Split a path into linked list of components, tracking head and tail of list.
// Filters out // entries with no contents.
struct string_list **splitpath(char *path, struct string_list **list)
@@ -347,171 +135,6 @@ struct string_list **splitpath(char *path, struct string_list **list)
return list;
}
-// Cannonicalize path, even to file with one or more missing components at end.
-// if exact, require last path component to exist
-char *xabspath(char *path, int exact)
-{
- struct string_list *todo, *done = 0;
- int try = 9999, dirfd = open("/", 0);;
- char buf[4096], *ret;
-
- // If this isn't an absolute path, start with cwd.
- if (*path != '/') {
- char *temp = xgetcwd();
-
- splitpath(path, splitpath(temp, &todo));
- free(temp);
- } else splitpath(path, &todo);
-
- // Iterate through path components
- while (todo) {
- struct string_list *new = llist_pop(&todo), **tail;
- ssize_t len;
-
- if (!try--) {
- errno = ELOOP;
- goto error;
- }
-
- // Removable path componenents.
- if (!strcmp(new->str, ".") || !strcmp(new->str, "..")) {
- int x = new->str[1];
-
- free(new);
- if (x) {
- if (done) free(llist_pop(&done));
- len = 0;
- } else continue;
-
- // Is this a symlink?
- } else len=readlinkat(dirfd, new->str, buf, 4096);
-
- if (len>4095) goto error;
- if (len<1) {
- int fd;
- char *s = "..";
-
- // For .. just move dirfd
- if (len) {
- // Not a symlink: add to linked list, move dirfd, fail if error
- if ((exact || todo) && errno != EINVAL) goto error;
- new->next = done;
- done = new;
- if (errno == EINVAL && !todo) break;
- s = new->str;
- }
- fd = openat(dirfd, s, 0);
- if (fd == -1 && (exact || todo || errno != ENOENT)) goto error;
- close(dirfd);
- dirfd = fd;
- continue;
- }
-
- // If this symlink is to an absolute path, discard existing resolved path
- buf[len] = 0;
- if (*buf == '/') {
- llist_traverse(done, free);
- done=0;
- close(dirfd);
- dirfd = open("/", 0);
- }
- free(new);
-
- // prepend components of new path. Note symlink to "/" will leave new NULL
- tail = splitpath(buf, &new);
-
- // symlink to "/" will return null and leave tail alone
- if (new) {
- *tail = todo;
- todo = new;
- }
- }
- close(dirfd);
-
- // At this point done has the path, in reverse order. Reverse list while
- // calculating buffer length.
-
- try = 2;
- while (done) {
- struct string_list *temp = llist_pop(&done);;
-
- if (todo) try++;
- try += strlen(temp->str);
- temp->next = todo;
- todo = temp;
- }
-
- // Assemble return buffer
-
- ret = xmalloc(try);
- *ret = '/';
- ret [try = 1] = 0;
- while (todo) {
- if (try>1) ret[try++] = '/';
- try = stpcpy(ret+try, todo->str) - ret;
- free(llist_pop(&todo));
- }
-
- return ret;
-
-error:
- close(dirfd);
- llist_traverse(todo, free);
- llist_traverse(done, free);
-
- return NULL;
-}
-
-// Resolve all symlinks, returning malloc() memory.
-char *xrealpath(char *path)
-{
- char *new = realpath(path, NULL);
- if (!new) perror_exit("realpath '%s'", path);
- return new;
-}
-
-void xchdir(char *path)
-{
- if (chdir(path)) error_exit("chdir '%s'", path);
-}
-
-// Ensure entire path exists.
-// If mode != -1 set permissions on newly created dirs.
-// Requires that path string be writable (for temporary null terminators).
-void xmkpath(char *path, int mode)
-{
- char *p, old;
- mode_t mask;
- int rc;
- struct stat st;
-
- for (p = path; ; p++) {
- if (!*p || *p == '/') {
- old = *p;
- *p = rc = 0;
- if (stat(path, &st) || !S_ISDIR(st.st_mode)) {
- if (mode != -1) {
- mask=umask(0);
- rc = mkdir(path, mode);
- umask(mask);
- } else rc = mkdir(path, 0777);
- }
- *p = old;
- if(rc) perror_exit("mkpath '%s'", path);
- }
- if (!*p) break;
- }
-}
-
-// setuid() can fail (for example, too many processes belonging to that user),
-// which opens a security hole if the process continues as the original user.
-
-void xsetuid(uid_t uid)
-{
- if (setuid(uid)) perror_exit("xsetuid");
-}
-
-
// Find all file in a colon-separated path with access type "type" (generally
// X_OK or R_OK). Returns a list of absolute paths to each file found, in
// order.
@@ -692,30 +315,6 @@ off_t fdlength(int fd)
return pos + 1;
}
-// This can return null (meaning file not found). It just won't return null
-// for memory allocation reasons.
-char *xreadlink(char *name)
-{
- int len, size = 0;
- char *buf = 0;
-
- // Grow by 64 byte chunks until it's big enough.
- for(;;) {
- size +=64;
- buf = xrealloc(buf, size);
- len = readlink(name, buf, size);
-
- if (len<0) {
- free(buf);
- return 0;
- }
- if (len<size) {
- buf[len]=0;
- return buf;
- }
- }
-}
-
// Read contents of file as a single freshly allocated nul-terminated string.
char *readfile(char *name)
{
@@ -732,13 +331,6 @@ char *readfile(char *name)
return buf;
}
-char *xreadfile(char *name)
-{
- char *buf = readfile(name);
- if (!buf) perror_exit("xreadfile %s", name);
- return buf;
-}
-
// Sleep for this many thousandths of a second
void msleep(long miliseconds)
{
@@ -749,17 +341,6 @@ void msleep(long miliseconds)
nanosleep(&ts, &ts);
}
-int xioctl(int fd, int request, void *data)
-{
- int rc;
-
- errno = 0;
- rc = ioctl(fd, request, data);
- if (rc == -1 && errno) perror_exit("ioctl %x", request);
-
- return rc;
-}
-
int64_t peek(void *ptr, int size)
{
if (size & 8) {
@@ -794,39 +375,6 @@ void poke(void *ptr, uint64_t val, int size)
}
}
-// Open a /var/run/NAME.pid file, dying if we can't write it or if it currently
-// exists and is this executable.
-void xpidfile(char *name)
-{
- char pidfile[256], spid[32];
- int i, fd;
- pid_t pid;
-
- sprintf(pidfile, "/var/run/%s.pid", name);
- // Try three times to open the sucker.
- for (i=0; i<3; i++) {
- fd = open(pidfile, O_CREAT|O_EXCL, 0644);
- if (fd != -1) break;
-
- // If it already existed, read it. Loop for race condition.
- fd = open(pidfile, O_RDONLY);
- if (fd == -1) continue;
-
- // Is the old program still there?
- spid[xread(fd, spid, sizeof(spid)-1)] = 0;
- close(fd);
- pid = atoi(spid);
- if (pid < 1 || kill(pid, 0) == ESRCH) unlink(pidfile);
-
- // An else with more sanity checking might be nice here.
- }
-
- if (i == 3) error_exit("xpidfile %s", name);
-
- xwrite(fd, spid, sprintf(spid, "%ld\n", (long)getpid()));
- close(fd);
-}
-
// Iterate through an array of files, opening each one and calling a function
// on that filehandle and name. The special filename "-" means stdin if
// flags is O_RDONLY, stdout otherwise. An empty argument list calls
@@ -890,21 +438,6 @@ char *get_line(int fd)
return buf;
}
-// Copy the rest of in to out and close both files.
-
-void xsendfile(int in, int out)
-{
- long len;
- char buf[4096];
-
- if (in<0) return;
- for (;;) {
- len = xread(in, buf, 4096);
- if (len<1) break;
- xwrite(out, buf, len);
- }
-}
-
int wfchmodat(int fd, char *name, mode_t mode)
{
int rc = fchmodat(fd, name, mode, 0);