aboutsummaryrefslogtreecommitdiff
path: root/www/content/posts/c-func-ext.md
diff options
context:
space:
mode:
Diffstat (limited to 'www/content/posts/c-func-ext.md')
-rw-r--r--www/content/posts/c-func-ext.md80
1 files changed, 71 insertions, 9 deletions
diff --git a/www/content/posts/c-func-ext.md b/www/content/posts/c-func-ext.md
index f5ab8fb..f0fce10 100644
--- a/www/content/posts/c-func-ext.md
+++ b/www/content/posts/c-func-ext.md
@@ -8,16 +8,78 @@ tags:
- posix
---
-Recently, I've been working on porting libraries to GNU/Hurd. The maintainers of GNU/Hurd
-have a strong belief that [`*_MAX` macros on POSIX system interfaces](https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/nframe.html)
-are very evil things. This is indeed true as a lot of (old) libraries relying on those macros
-to determine the buffer size. In modern programming world, it is definitely a bad
-idea to use fixed values for buffer sizes without considering possible overflow, unless
-you are certain that size is sufficient.
-
-When you get rid of some old things, you will always meet compatibility problems. In these
-case, old source codes using these macros just do not compile now. So here are some
+Recently, I’ve been working on porting some libraries to GNU/Hurd. Many (old)
+libraries use [`*_MAX` constants on POSIX system
+interfaces](https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/nframe.html)
+to calculate buffer sizes. However, the GNU/Hurd maintainers urge against the
+blind use of them and refuse to define them in system headers. When old APIs are
+gone, compatibility problems come. To make my life easier, I'll put some
+reusable code snippets here to help *fix `*_MAX` bugs*.
<!--more-->
+```c
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static inline char *xreadlink(const char *restrict path) {
+ char *buffer;
+ size_t allocated = 128;
+ ssize_t len;
+
+ while (1) {
+ buffer = (char *)malloc(allocated);
+ if (!buffer) {
+ return NULL;
+ }
+ len = readlink(path, buffer, allocated);
+ if (len < (ssize_t)allocated) {
+ return buffer;
+ }
+ free(buffer);
+ if (len >= (ssize_t)allocated) {
+ allocated *= 2;
+ continue;
+ }
+ return NULL;
+ }
+}
+
+static inline char *xgethostname() {
+ long max_host_name;
+ char *buffer;
+
+ max_host_name = sysconf(_SC_HOST_NAME_MAX);
+ buffer = malloc(max_host_name + 1);
+
+ if (gethostname(buffer, max_host_name + 1)) {
+ free(buffer);
+ return NULL;
+ }
+
+ buffer[max_host_name] = '\0';
+ return buffer;
+}
+
+static inline char *xgetcwd() {
+ char *buffer;
+ size_t allocated = 128;
+ while (1) {
+ buffer = (char *)malloc(allocated);
+ if (!buffer) {
+ return NULL;
+ }
+ getcwd(buffer, allocated);
+ if (buffer)
+ return buffer;
+ free(buffer);
+ if (errno == ERANGE) {
+ allocated *= 2;
+ continue;
+ }
+ return NULL;
+ }
+}
+```