Re: [hackers] [sbase] [PATCH 00/10] IO improvements and some bug fixes
On Sun, 4 Dec 2016 21:55:02 -0800 Michael Forney wrote: Dear Michael, > I finally got around to addressing the issues with fread I raised at > the end of http://lists.suckless.org/dev/1504/26580.html. > > This patch series eliminates several uses of fread/fwrite where plain > read/write are more appropriate. To help with the common case of > writing an entire buffer to a file descriptor, I added a writeall > function (which works similar to plan9's standard write function and > the Write/write_all functions in go/rust). All users of concat were > better suited to work on plain file descriptors except for tail, so I > switched concat to a read/writeall loop, and tail to use a > fgetc/fputc loop. fgetc/fputc really can slow down your program, which I noticed when I wrote farbfeld-filters. Working on a buffer-basis rather than a char-by-char-basis really speeds up things a lot (for me it was around 50%-70%). Can you provide some performance-information e.g. for cat(1)? Does it get any faster with the writeall()-loop? What other benefits do we see here? Can you elaborate in this thread again why we should do raw I/O? In a naïve sense, the operating system can "shedule" reads and writes more efficiently with the buffered I/O. > The result should be more efficient (no copy between read/write > buffers, and data is processed as it comes in), and is roughly the > same complexity as before. In most cases, we now pull in less of > stdio, so statically linked binaries get smaller. Additionally, > cat/tee on a pipe/terminal is now usable. That makes sense. > Along the way, I found and fixed several bugs, mostly dealing with > error checking. > I've been running with these patches for a couple days now and > haven't noticed any regressions. That is great! I'm glad you test your patches before submitting, which I have been guilty of neglecting for so many times. Cheers Laslo -- Laslo Hunhold
[hackers] [sbase] [PATCH 03/10] libutil: Add writeall utility function
writeall makes successive write calls to write an entire buffer to the output file descriptor. It returns the number of bytes written, or -1 on the first error. --- Makefile | 3 ++- libutil/writeall.c | 21 + util.h | 3 +++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 libutil/writeall.c diff --git a/Makefile b/Makefile index 25bab70..a337ead 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,8 @@ LIBUTILSRC =\ libutil/strlcpy.c\ libutil/strsep.c\ libutil/strtonum.c\ - libutil/unescape.c + libutil/unescape.c\ + libutil/writeall.c LIB = $(LIBUTF) $(LIBUTIL) diff --git a/libutil/writeall.c b/libutil/writeall.c new file mode 100644 index 000..4725ced --- /dev/null +++ b/libutil/writeall.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include + +#include "../util.h" + +ssize_t +writeall(int fd, const void *buf, size_t len) +{ + const char *p = buf; + ssize_t n; + + while (len) { + n = write(fd, p, len); + if (n <= 0) + return n; + p += n; + len -= n; + } + + return p - (const char *)buf; +} diff --git a/util.h b/util.h index b5860dc..eaad3ce 100644 --- a/util.h +++ b/util.h @@ -62,6 +62,9 @@ char *strsep(char **, const char *); int enregcomp(int, regex_t *, const char *, int); int eregcomp(regex_t *, const char *, int); +/* io */ +ssize_t writeall(int, const void *, size_t); + /* misc */ void enmasse(int, char **, int (*)(const char *, const char *, int)); void fnck(const char *, const char *, int (*)(const char *, const char *, int), int); -- 2.11.0
[hackers] [sbase] [PATCH 08/10] cp: Only call chmod with -p or -a
Previously, when the destination file was created with fopen, we needed to use fchmod to set its permissions. Now that we pass in the mode to creat, we already get the desired behavior of creating the file with the same mode as the source file modified by the user's file creation mask. This fixes the issue where a directory or special file created with mkdir/mknod does not end up with the appropriate mode with -p or -a (since it may have been narrowed by the umask). This also allows us to clear the SUID and SGID bits from the mode if the chown fails, as specified by POSIX. --- libutil/cp.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libutil/cp.c b/libutil/cp.c index 8cd0a7d..339c892 100644 --- a/libutil/cp.c +++ b/libutil/cp.c @@ -134,15 +134,11 @@ cp(const char *s1, const char *s2, int depth) return 0; } - /* preserve permissions by default */ - fchmod(f2, st.st_mode); - close(f1); close(f2); } if (cp_aflag || cp_pflag) { - /* timestamp and owner */ if (!S_ISLNK(st.st_mode)) { times[0] = st.st_atim; times[1] = st.st_mtim; @@ -151,7 +147,11 @@ cp(const char *s1, const char *s2, int depth) if (chown(s2, st.st_uid, st.st_gid) < 0) { weprintf("chown %s:", s2); cp_status = 1; - return 0; + st.st_mode &= ~(S_ISUID | S_ISGID); + } + if (chmod(s2, st.st_mode) < 0) { + weprintf("chmod %s:", s2); + cp_status = 1; } } else { if (lchown(s2, st.st_uid, st.st_gid) < 0) { -- 2.11.0
[hackers] [sbase] [PATCH 00/10] IO improvements and some bug fixes
I finally got around to addressing the issues with fread I raised at the end of http://lists.suckless.org/dev/1504/26580.html. This patch series eliminates several uses of fread/fwrite where plain read/write are more appropriate. To help with the common case of writing an entire buffer to a file descriptor, I added a writeall function (which works similar to plan9's standard write function and the Write/write_all functions in go/rust). All users of concat were better suited to work on plain file descriptors except for tail, so I switched concat to a read/writeall loop, and tail to use a fgetc/fputc loop. The result should be more efficient (no copy between read/write buffers, and data is processed as it comes in), and is roughly the same complexity as before. In most cases, we now pull in less of stdio, so statically linked binaries get smaller. Additionally, cat/tee on a pipe/terminal is now usable. Along the way, I found and fixed several bugs, mostly dealing with error checking. I've been running with these patches for a couple days now and haven't noticed any regressions. Michael Forney (10): crypt: Add some missing error checks for cryptsum od: Fix buffer overflow if -N flag is larger than BUFSIZ libutil: Add writeall utility function Don't use buffered IO (fread) when not appropriate tail: Use getc and putc instead of concat xinstall: Check result of fchmod concat: Use plain read/write instead of buffered stdio cp: Only call chmod with -p or -a tail: Use fstat in case file is removed cp: Check result of utimensat Makefile | 3 ++- cat.c | 34 ++ cksum.c| 31 +-- crypt.h| 2 +- libutil/concat.c | 24 ++-- libutil/cp.c | 52 ++-- libutil/crypt.c| 47 ++- libutil/writeall.c | 21 + od.c | 47 --- sponge.c | 31 +-- tail.c | 38 -- tee.c | 39 +++ text.h | 1 - util.h | 4 xinstall.c | 26 +- 15 files changed, 214 insertions(+), 186 deletions(-) create mode 100644 libutil/writeall.c -- 2.11.0
[hackers] [sbase] [PATCH 09/10] tail: Use fstat in case file is removed
--- tail.c | 16 +++- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/tail.c b/tail.c index ad97308..000be62 100644 --- a/tail.c +++ b/tail.c @@ -133,7 +133,7 @@ main(int argc, char *argv[]) } if (many) printf("%s==> %s <==\n", newline ? "\n" : "", *argv); - if (stat(*argv, &st1) < 0) + if (fstat(fileno(fp), &st1) < 0) eprintf("stat %s:", *argv); if (!(S_ISFIFO(st1.st_mode) || S_ISREG(st1.st_mode))) fflag = 0; @@ -153,15 +153,13 @@ main(int argc, char *argv[]) if (ferror(fp)) eprintf("fgetc %s:", *argv); clearerr(fp); - /* ignore error in case file was removed, we continue -* tracking the existing open file descriptor */ - if (!stat(*argv, &st2)) { - if (st2.st_size < st1.st_size) { - fprintf(stderr, "%s: file truncated\n", *argv); - rewind(fp); - } - st1 = st2; + if (fstat(fileno(fp), &st2) < 0) + eprintf("fstat:"); + if (st2.st_size < st1.st_size) { + fprintf(stderr, "%s: file truncated\n", *argv); + rewind(fp); } + st1 = st2; sleep(1); } } -- 2.11.0
[hackers] [sbase] [PATCH 06/10] xinstall: Check result of fchmod
--- xinstall.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xinstall.c b/xinstall.c index bf921fb..5a0e390 100644 --- a/xinstall.c +++ b/xinstall.c @@ -119,7 +119,8 @@ install(const char *s1, const char *s2, int depth) } concat(f1, s1, f2, s2); - fchmod(fileno(f2), mode); + if (fchmod(fileno(f2), mode) < 0) + eprintf("fchmod %s:", s2); if (fclose(f2) == EOF) eprintf("fclose %s:", s2); -- 2.11.0
[hackers] [sbase] [PATCH 04/10] Don't use buffered IO (fread) when not appropriate
fread reads the entire requested size (BUFSIZ), which causes tools to block if only small amounts of data are available at a time. At best, this causes unnecessary copies and inefficiency, at worst, tools like tee and cat are almost unusable in some cases since they only display large chunks of data at a time. --- cksum.c | 31 +-- crypt.h | 2 +- libutil/crypt.c | 37 +++-- od.c| 42 ++ tee.c | 39 +++ 5 files changed, 82 insertions(+), 69 deletions(-) diff --git a/cksum.c b/cksum.c index 570ca81..b53ec17 100644 --- a/cksum.c +++ b/cksum.c @@ -1,7 +1,9 @@ /* See LICENSE file for copyright and license details. */ +#include #include #include #include +#include #include "util.h" @@ -61,19 +63,20 @@ static const unsigned long crctab[] = { 0x, }; static void -cksum(FILE *fp, const char *s) +cksum(int fd, const char *s) { - size_t len = 0, i, n; + ssize_t n; + size_t len = 0, i; uint32_t ck = 0; unsigned char buf[BUFSIZ]; - while ((n = fread(buf, 1, sizeof(buf), fp))) { + while ((n = read(fd, buf, sizeof(buf))) > 0) { for (i = 0; i < n; i++) ck = (ck << 8) ^ crctab[(ck >> 24) ^ buf[i]]; len += n; } - if (ferror(fp)) { - weprintf("fread %s:", s ? s : ""); + if (n < 0) { + weprintf("read %s:", s ? s : ""); ret = 1; return; } @@ -92,29 +95,29 @@ cksum(FILE *fp, const char *s) int main(int argc, char *argv[]) { - FILE *fp; + int fd; argv0 = argv[0], argc--, argv++; if (!argc) { - cksum(stdin, NULL); + cksum(0, NULL); } else { for (; *argv; argc--, argv++) { if (!strcmp(*argv, "-")) { *argv = ""; - fp = stdin; - } else if (!(fp = fopen(*argv, "r"))) { - weprintf("fopen %s:", *argv); + fd = 0; + } else if ((fd = open(*argv, O_RDONLY)) < 0) { + weprintf("open %s:", *argv); ret = 1; continue; } - cksum(fp, *argv); - if (fp != stdin && fshut(fp, *argv)) - ret = 1; + cksum(fd, *argv); + if (fd != 0) + close(fd); } } - ret |= fshut(stdin, "") | fshut(stdout, ""); + ret |= fshut(stdout, ""); return ret; } diff --git a/crypt.h b/crypt.h index e0cc08d..2fd2932 100644 --- a/crypt.h +++ b/crypt.h @@ -8,5 +8,5 @@ struct crypt_ops { int cryptcheck(int, char **, struct crypt_ops *, uint8_t *, size_t); int cryptmain(int, char **, struct crypt_ops *, uint8_t *, size_t); -int cryptsum(struct crypt_ops *, FILE *, const char *, uint8_t *); +int cryptsum(struct crypt_ops *, int, const char *, uint8_t *); void mdprint(const uint8_t *, const char *, size_t); diff --git a/libutil/crypt.c b/libutil/crypt.c index 6991c39..e285614 100644 --- a/libutil/crypt.c +++ b/libutil/crypt.c @@ -1,8 +1,10 @@ /* See LICENSE file for copyright and license details. */ +#include #include #include #include #include +#include #include "../crypt.h" #include "../text.h" @@ -41,7 +43,7 @@ static void mdchecklist(FILE *listfp, struct crypt_ops *ops, uint8_t *md, size_t sz, int *formatsucks, int *noread, int *nonmatch) { - FILE *fp; + int fd; size_t bufsiz = 0; int r; char *line = NULL, *file, *p; @@ -59,12 +61,12 @@ mdchecklist(FILE *listfp, struct crypt_ops *ops, uint8_t *md, size_t sz, file += 2; for (p = file; *p && *p != '\n' && *p != '\r'; p++); /* strip newline */ *p = '\0'; - if (!(fp = fopen(file, "r"))) { - weprintf("fopen %s:", file); + if ((fd = open(file, O_RDONLY)) < 0) { + weprintf("open %s:", file); (*noread)++; continue; } - if (cryptsum(ops, fp, file, md)) { + if (cryptsum(ops, fd, file, md)) { (*noread)++; continue; } @@ -77,7 +79,7 @@ mdchecklist(FILE *listfp, struct crypt_ops *ops, uint8_t *md, size_t sz, } else { (*formatsucks)++; } - fclose(fp); + close(fd); } free(line); } @@ -124,11 +126,11 @@ cryptcheck(int argc, char
[hackers] [sbase] [PATCH 02/10] od: Fix buffer overflow if -N flag is larger than BUFSIZ
Previously, if max was specified, od will call read with that size, potentially overflowing buf with data read from the file. --- od.c | 11 +-- 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/od.c b/od.c index 9b83501..b5884e7 100644 --- a/od.c +++ b/od.c @@ -132,20 +132,19 @@ od(FILE *fp, char *fname, int last) size_t i; unsigned char buf[BUFSIZ]; static off_t addr; - size_t buflen; + size_t n; while (skip - addr > 0) { - buflen = fread(buf, 1, MIN(skip - addr, BUFSIZ), fp); - addr += buflen; + n = fread(buf, 1, MIN(skip - addr, sizeof(buf)), fp); + addr += n; if (feof(fp) || ferror(fp)) return; } if (!line) line = emalloc(linelen); - while ((buflen = fread(buf, 1, max >= 0 ? - max - (addr - skip) : BUFSIZ, fp))) { - for (i = 0; i < buflen; i++, addr++) { + while ((n = fread(buf, 1, MIN((size_t)max - (addr - skip), sizeof(buf)), fp))) { + for (i = 0; i < n; i++, addr++) { line[lineoff++] = buf[i]; if (lineoff == linelen) { printline(line, lineoff, addr - lineoff + 1); -- 2.11.0
[hackers] [sbase] [PATCH 10/10] cp: Check result of utimensat
POSIX says that if duplicating the modification/access times fails, then an error should be written to stderr. --- libutil/cp.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libutil/cp.c b/libutil/cp.c index 339c892..15e4ce5 100644 --- a/libutil/cp.c +++ b/libutil/cp.c @@ -142,8 +142,10 @@ cp(const char *s1, const char *s2, int depth) if (!S_ISLNK(st.st_mode)) { times[0] = st.st_atim; times[1] = st.st_mtim; - utimensat(AT_FDCWD, s2, times, 0); - + if (utimensat(AT_FDCWD, s2, times, 0) < 0) { + weprintf("utimensat %s:", s2); + cp_status = 1; + } if (chown(s2, st.st_uid, st.st_gid) < 0) { weprintf("chown %s:", s2); cp_status = 1; -- 2.11.0
[hackers] [sbase] [PATCH 01/10] crypt: Add some missing error checks for cryptsum
Previously, if a file failed to read in a checksum list, it would be reported as not matched rather than a read failure. Also, if reading from stdin failed, previously a bogus checksum would be printed anyway. --- libutil/crypt.c | 16 ++-- 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/libutil/crypt.c b/libutil/crypt.c index 3f849ba..6991c39 100644 --- a/libutil/crypt.c +++ b/libutil/crypt.c @@ -64,7 +64,10 @@ mdchecklist(FILE *listfp, struct crypt_ops *ops, uint8_t *md, size_t sz, (*noread)++; continue; } - cryptsum(ops, fp, file, md); + if (cryptsum(ops, fp, file, md)) { + (*noread)++; + continue; + } r = mdcheckline(line, md, sz); if (r == 1) { printf("%s: OK\n", file); @@ -125,8 +128,10 @@ cryptmain(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz) int ret = 0; if (argc == 0) { - cryptsum(ops, stdin, "", md); - mdprint(md, "", sz); + if (cryptsum(ops, stdin, "", md)) + ret = 1; + else + mdprint(md, "", sz); } else { for (; *argv; argc--, argv++) { if ((*argv)[0] == '-' && !(*argv)[1]) { @@ -137,11 +142,10 @@ cryptmain(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz) ret = 1; continue; } - if (cryptsum(ops, fp, *argv, md)) { + if (cryptsum(ops, fp, *argv, md)) ret = 1; - } else { + else mdprint(md, *argv, sz); - } if (fp != stdin && fshut(fp, *argv)) ret = 1; } -- 2.11.0
[hackers] [sbase] [PATCH 05/10] tail: Use getc and putc instead of concat
The FILE streams are buffered, so the end result is essentially the same, except now lines are printed as they are read since we don't wait until the entire buffer is filled. This also fixes an issue where only part of the lines during the follow were printed if they contained NUL bytes. --- tail.c | 22 +- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tail.c b/tail.c index 711707f..ad97308 100644 --- a/tail.c +++ b/tail.c @@ -20,6 +20,7 @@ dropinit(FILE *fp, const char *str, size_t n) char *buf = NULL; size_t size = 0, i = 1; ssize_t len; + int c; if (mode == 'n') { while (i < n && (len = getline(&buf, &size, fp)) > 0) @@ -30,7 +31,10 @@ dropinit(FILE *fp, const char *str, size_t n) i++; } free(buf); - concat(fp, str, stdout, ""); + while ((c = fgetc(fp)) != EOF) { + if (fputc(c, stdout) == EOF) + break; + } } static void @@ -88,9 +92,9 @@ main(int argc, char *argv[]) { struct stat st1, st2; FILE *fp; - size_t tmpsize, n = 10; - int fflag = 0, ret = 0, newline = 0, many = 0; - char *numstr, *tmp; + size_t n = 10; + int fflag = 0, ret = 0, newline = 0, many = 0, c; + char *numstr; void (*tail)(FILE *, const char *, size_t) = taketail; ARGBEGIN { @@ -141,13 +145,13 @@ main(int argc, char *argv[]) ret = 1; continue; } - for (tmp = NULL, tmpsize = 0;;) { - while (getline(&tmp, &tmpsize, fp) > 0) { - fputs(tmp, stdout); - fflush(stdout); + for (;;) { + while ((c = fgetc(fp)) != EOF) { + if (fputc(c, stdout) == EOF) + eprintf("fputc :"); } if (ferror(fp)) - eprintf("readline %s:", *argv); + eprintf("fgetc %s:", *argv); clearerr(fp); /* ignore error in case file was removed, we continue * tracking the existing open file descriptor */ -- 2.11.0
[hackers] [sbase] [PATCH 07/10] concat: Use plain read/write instead of buffered stdio
If we are just copying data from one file to another, we don't need to fill a complete buffer, just read a chunk at a time, and write it to the output. --- cat.c| 34 ++ libutil/concat.c | 24 ++-- libutil/cp.c | 42 -- sponge.c | 31 +-- text.h | 1 - util.h | 1 + xinstall.c | 25 - 7 files changed, 70 insertions(+), 88 deletions(-) diff --git a/cat.c b/cat.c index e3741aa..55585dd 100644 --- a/cat.c +++ b/cat.c @@ -1,22 +1,11 @@ /* See LICENSE file for copyright and license details. */ -#include +#include #include #include -#include "text.h" #include "util.h" static void -uconcat(FILE *fp1, const char *s1, FILE *fp2, const char *s2) -{ - int c; - - setbuf(fp2, NULL); - while ((c = getc(fp1)) != EOF) - putc(c, fp2); -} - -static void usage(void) { eprintf("usage: %s [-u] [file ...]\n", argv0); @@ -25,37 +14,34 @@ usage(void) int main(int argc, char *argv[]) { - FILE *fp; - int ret = 0; - void (*cat)(FILE *, const char *, FILE *, const char *) = &concat; + int fd, ret = 0; ARGBEGIN { case 'u': - cat = &uconcat; break; default: usage(); } ARGEND if (!argc) { - cat(stdin, "", stdout, ""); + if (concat(0, "", 1, "") < 0) + ret = 1; } else { for (; *argv; argc--, argv++) { if (!strcmp(*argv, "-")) { *argv = ""; - fp = stdin; - } else if (!(fp = fopen(*argv, "r"))) { - weprintf("fopen %s:", *argv); + fd = 0; + } else if ((fd = open(*argv, O_RDONLY)) < 0) { + weprintf("open %s:", *argv); ret = 1; continue; } - cat(fp, *argv, stdout, ""); - if (fp != stdin && fshut(fp, *argv)) + if (concat(fd, *argv, 1, "") < 0) ret = 1; + if (fd != 0) + close(fd); } } - ret |= fshut(stdin, "") | fshut(stdout, ""); - return ret; } diff --git a/libutil/concat.c b/libutil/concat.c index fad9471..3f617e2 100644 --- a/libutil/concat.c +++ b/libutil/concat.c @@ -1,19 +1,23 @@ /* See LICENSE file for copyright and license details. */ -#include +#include -#include "../text.h" #include "../util.h" -void -concat(FILE *fp1, const char *s1, FILE *fp2, const char *s2) +int +concat(int f1, const char *s1, int f2, const char *s2) { char buf[BUFSIZ]; - size_t n; + ssize_t n; - while ((n = fread(buf, 1, sizeof(buf), fp1))) { - fwrite(buf, 1, n, fp2); - - if (feof(fp1) || ferror(fp1) || ferror(fp2)) - break; + while ((n = read(f1, buf, sizeof(buf))) > 0) { + if (writeall(f2, buf, n) < 0) { + weprintf("write %s:", s2); + return -1; + } + } + if (n < 0) { + weprintf("read %s:", s1); + return -1; } + return 0; } diff --git a/libutil/cp.c b/libutil/cp.c index c398962..8cd0a7d 100644 --- a/libutil/cp.c +++ b/libutil/cp.c @@ -12,7 +12,6 @@ #include #include "../fs.h" -#include "../text.h" #include "../util.h" int cp_aflag = 0; @@ -27,7 +26,7 @@ int cp(const char *s1, const char *s2, int depth) { DIR *dp; - FILE *f1, *f2; + int f1, f2; struct dirent *d; struct stat st; struct timespec times[2]; @@ -112,43 +111,34 @@ cp(const char *s1, const char *s2, int depth) return 0; } } else { - if (!(f1 = fopen(s1, "r"))) { - weprintf("fopen %s:", s1); + if ((f1 = open(s1, O_RDONLY)) < 0) { + weprintf("open %s:", s1); cp_status = 1; return 0; } - if (!(f2 = fopen(s2, "w"))) { - if (cp_fflag) { - if (unlink(s2) < 0 && errno != ENOENT) { - weprintf("unlink %s:", s2); - cp_status = 1; - return 0; - } else if (!(f2 = fopen(s2, "w"))) { - weprintf("fopen %s:", s2); - cp_status = 1; -
[hackers] [scc] [driver] fix temporary object generation for old POSIX || Quentin Rameau
commit 700201165e35131fd7c6e64e8e97f591a9724500 Author: Quentin Rameau AuthorDate: Sun Dec 4 10:36:21 2016 +0100 Commit: Quentin Rameau CommitDate: Sun Dec 4 12:30:55 2016 +0100 [driver] fix temporary object generation for old POSIX Pre-susv4 mkstemp don't impose a filename format and don't provide EINVAL error on which we were counting. diff --git a/driver/posix/scc.c b/driver/posix/scc.c index 74f5299..7f3e64e 100644 --- a/driver/posix/scc.c +++ b/driver/posix/scc.c @@ -163,10 +163,12 @@ outfname(char *path, char *type) n = snprintf(new, newsz, "%.*s%c%s", (int)pathln, path, sep, type); if (n < 0 || n >= newsz) die("scc: wrong output filename"); - if ((tmpfd = mkstemp(new)) < 0 && errno != EINVAL) - die("scc: could not create output file '%s': %s", - new, strerror(errno)); - close(tmpfd); + if (sep == '/') { + if ((tmpfd = mkstemp(new)) < 0) + die("scc: could not create output file '%s': %s", + new, strerror(errno)); + close(tmpfd); + } return new; }
[hackers] [scc] Makefile: remove unnecessary mkdir bin/ || Quentin Rameau
commit 9c999e2862eb82d8a19b7ba8b2bd42a0256f860e Author: Quentin Rameau AuthorDate: Fri Dec 2 11:41:54 2016 +0100 Commit: Quentin Rameau CommitDate: Sun Dec 4 12:30:59 2016 +0100 Makefile: remove unnecessary mkdir bin/ diff --git a/Makefile b/Makefile index d6a2caa..98e5f0b 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,6 @@ driver/$(DRIVER)/scc: bin ln -f driver/$(DRIVER)/scc bin/scc $(ARCHS): bin - mkdir -p bin for i in cc1 cc2; \ do \ (cd $$i; \
[hackers] [scc] Makefiles: build a binary for each arch target || Quentin Rameau
commit 2f972eea17a78f21c5ffbce5be12b42ca91cb80c Author: Quentin Rameau AuthorDate: Sun Dec 4 10:34:37 2016 +0100 Commit: Quentin Rameau CommitDate: Sun Dec 4 12:30:59 2016 +0100 Makefiles: build a binary for each arch target This fixes a build issue when common code would be modified while having a pre-built arch .o file, the arch-specific binary wouldn't be rebuilt. diff --git a/Makefile b/Makefile index 98e5f0b..588d808 100644 --- a/Makefile +++ b/Makefile @@ -20,10 +20,10 @@ $(ARCHS): bin for i in cc1 cc2; \ do \ (cd $$i; \ - ARCH=$@ $(MAKE) -e $$i || exit); \ + ARCH=$@ $(MAKE) -e $$i-$@ || exit); \ done - ln -f cc1/cc1 bin/cc1-$@ - ln -f cc2/cc2 bin/cc2-$@ + ln -f cc1/cc1-$@ bin/ + ln -f cc2/cc2-$@ bin/ bin: mkdir -p bin diff --git a/cc1/Makefile b/cc1/Makefile index 25df906..8b36fb1 100644 --- a/cc1/Makefile +++ b/cc1/Makefile @@ -6,7 +6,7 @@ include ../config.mk OBJS = types.o decl.o lex.o error.o symbol.o main.o expr.o \ code.o stmt.o cpp.o fold.o init.o arch/$(ARCH)/arch.o -all: cc1 +all: cc1-$(ARCH) cpp.o: stallman.msg $(OBJS): cc1.h ../inc/cc.h ../inc/sizes.h @@ -17,15 +17,15 @@ $(OBJS): cc1.h ../inc/cc.h ../inc/sizes.h ../lib/libcc.a: cd ../lib && $(MAKE) -e -cc1: $(OBJS) ../lib/libcc.a +cc1-$(ARCH): $(OBJS) ../lib/libcc.a $(CC) $(SCC_LDFLAGS) $(OBJS) ../lib/libcc.a -o $@ -cpp: cc1 - ln -f cc1 cpp +cpp: cc1-$(ARCH) + ln -f $< cpp test: cd tests && ./chktest.sh *.c clean: rm -f $(OBJS) - rm -f cc1 cpp + rm -f cc1-* cpp diff --git a/cc2/Makefile b/cc2/Makefile index ee0f35d..244b137 100644 --- a/cc2/Makefile +++ b/cc2/Makefile @@ -7,7 +7,7 @@ OBJS = main.o parser.o peep.o symbol.o node.o code.o optm.o\ arch/$(ARCH)/code.o arch/$(ARCH)/cgen.o \ arch/$(ARCH)/types.o arch/$(ARCH)/optm.o -all: cc2 +all: cc2-$(ARCH) main.o: error.h $(OBJS): cc2.h ../inc/sizes.h ../inc/cc.h @@ -24,9 +24,9 @@ error.h: cc2.h ../inc/sizes.h: cp ../inc/sizes_$(STD).h $@ -cc2: $(OBJS) ../lib/libcc.a +cc2-$(ARCH): $(OBJS) ../lib/libcc.a $(CC) $(SCC_LDFLAGS) $(OBJS) ../lib/libcc.a -o $@ clean: rm -f $(OBJS) - rm -f cc2 error.h + rm -f cc2-* error.h