diff options
author | Denis Vlasenko | 2008-06-14 04:28:41 +0000 |
---|---|---|
committer | Denis Vlasenko | 2008-06-14 04:28:41 +0000 |
commit | a1767a1f5d744804958b2ef0516cbd5d33292c0c (patch) | |
tree | 9f8d284587e8270cf6be2b1f7f5033f1f21c884d /coreutils/dos2unix.c | |
parent | 21765fa063830923d13426ec6989c16da9210e49 (diff) | |
download | busybox-a1767a1f5d744804958b2ef0516cbd5d33292c0c.zip busybox-a1767a1f5d744804958b2ef0516cbd5d33292c0c.tar.gz |
dos2unix: do not destroy symlinks and mode of the file being converted.
Diffstat (limited to 'coreutils/dos2unix.c')
-rw-r--r-- | coreutils/dos2unix.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c index 2db7e11..311dc13 100644 --- a/coreutils/dos2unix.c +++ b/coreutils/dos2unix.c @@ -24,24 +24,27 @@ static void convert(char *fn, int conv_type) { FILE *in, *out; int i; - char *name_buf = name_buf; /* for compiler */ + char *temp_fn = temp_fn; /* for compiler */ + char *resolved_fn = resolved_fn; in = stdin; out = stdout; if (fn != NULL) { - in = xfopen(fn, "r"); - /* - The file is then created with mode read/write and - permissions 0666 for glibc 2.0.6 and earlier or - 0600 for glibc 2.0.7 and later. - */ - name_buf = xasprintf("%sXXXXXX", fn); - i = mkstemp(name_buf); + struct stat st; + + resolved_fn = xmalloc_follow_symlinks(fn); + if (resolved_fn == NULL) + bb_simple_perror_msg_and_die(fn); + in = xfopen(resolved_fn, "r"); + fstat(fileno(in), &st); + + temp_fn = xasprintf("%sXXXXXX", resolved_fn); + i = mkstemp(temp_fn); if (i == -1 - || fchmod(i, 0600) == -1 + || fchmod(i, st.st_mode) == -1 || !(out = fdopen(i, "w+")) ) { - bb_perror_nomsg_and_die(); + bb_simple_perror_msg_and_die(temp_fn); } } @@ -56,12 +59,12 @@ static void convert(char *fn, int conv_type) if (fn != NULL) { if (fclose(in) < 0 || fclose(out) < 0) { - unlink(name_buf); + unlink(temp_fn); bb_perror_nomsg_and_die(); } -// TODO: destroys symlinks. See how passwd handles this - xrename(name_buf, fn); - free(name_buf); + xrename(temp_fn, resolved_fn); + free(temp_fn); + free(resolved_fn); } } |