Skip to content

Commit

Permalink
You can now call readlink(2) from Fexl, for example:
Browse files Browse the repository at this point in the history
	readlink "/proc/self/exe" \path
	print "You are currently running ";print path;nl;

I also changed the build script slightly so that its dependency analysis (via
grep) does not insist that #include lines always end precisely in a double-
quote.  For example, you can now add spaces or comments on the end of #include
lines, and the grep ignores them.  I had just made it too strict before, by
including '$' at the end of the pattern to match end-of-line immediately after
the quote.
  • Loading branch information
Patrick Chkoreff committed Sep 25, 2012
1 parent c06362e commit 943d69e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
2 changes: 1 addition & 1 deletion build
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ do

update=`newer_than $file_c $file_o`
if [ $update -eq 0 ]; then
grep -e "^#include \".*\"$" $file_c |
grep -e "^#include \".*\"" $file_c |
sed "s/^#include \"\(.*\)\"/\1/" |
(
while read file; do
Expand Down
66 changes: 66 additions & 0 deletions src/file.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include <stdio.h>
#include <unistd.h> /* readlink */
#include "buf.h"
#include "value.h"
#include "basic.h"
#include "file.h"
#include "long.h"
#include "memory.h"
#include "string.h"

void type_file(value f) { type_error(); }
Expand Down Expand Up @@ -167,3 +170,66 @@ void reduce_file_string(value f)
value const_stdin(void) { return Qfile_const(stdin); }
value const_stdout(void) { return Qfile_const(stdout); }
value const_stderr(void) { return Qfile_const(stderr); }

/*
Safely call readlink, returning a NUL-terminated result in a dynamically
allocated buffer.
Note that the size of the buffer is always a power of two. It doesn't have to
be that way, but it feels right.
*/
void safe_readlink(const char *path,
char **result, long *result_len, long *result_size)
{
long size = 256;
while (1)
{
char *link = new_memory(size);
ssize_t len = readlink(path, link, size - 1);
if (len == -1)
{
free_memory(link, size);
*result = 0;
*result_len = 0;
*result_size = 0;
return;
}
else if (len == size - 1)
{
/* Assume the worst: the result might be truncated. */
free_memory(link, size);
size = 2 * size;
}
else
{
link[len] = 0;
*result = link;
*result_len = len;
*result_size = size;
return;
}
}
}

/* readlink path next = (next link), where link is the result of calling
readlink(2) on the path. */
static void reduce2_readlink(value f)
{
value x = arg(type_string,f->L->R);
char *path = string_data(x);

char *buf;
long len;
long size;
safe_readlink(path, &buf, &len, &size);

value result = Qcopy_chars(buf,len);
if (buf) free_memory(buf, size);

replace_apply(f,f->R,result);
}

void reduce_readlink(value f)
{
f->T = reduce2_readlink;
}
2 changes: 2 additions & 0 deletions src/file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
extern void safe_readlink(const char *path,
char **result, long *result_len, long *result_size);

0 comments on commit 943d69e

Please sign in to comment.