From: Michael D. Lowis Date: Tue, 27 Mar 2018 00:39:19 +0000 (-0400) Subject: switched from mmap saving and loading to read/write X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=2efcb7e10d8261968f93e7fd7a4b8299b5e90175;p=projs%2Ftide.git switched from mmap saving and loading to read/write --- diff --git a/inc/edit.h b/inc/edit.h index 37c2854..38eb6ed 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -6,6 +6,7 @@ typedef struct { size_t len; /* length of the buffer */ } FMap; +size_t pagealign(size_t sz); FMap mmap_readonly(char* path); FMap mmap_readwrite(char* path, size_t sz); void mmap_close(FMap file); diff --git a/lib/buf.c b/lib/buf.c index 367943e..b536139 100644 --- a/lib/buf.c +++ b/lib/buf.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include size_t buf_setln(Buf* buf, size_t line); size_t buf_getcol(Buf* buf, size_t pos); @@ -49,11 +51,23 @@ size_t buf_load(Buf* buf, char* path) { char* addr = strrchr(buf->path, ':'); if (addr) *addr = '\0', addr++; - /* load the file and determine the character set */ - FMap file = mmap_readonly(buf->path); - buf_resize(buf, next_size(file.len)); - for (size_t i = 0; i < file.len;) - buf_insert(buf, false, buf_end(buf), file.buf[i++]); + /* load the contents from the file */ + int fd, nread; + struct stat sb = {0}; + if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0)) { + /* allocate the buffer in advance */ + free(buf->bufstart); + buf->bufsize = pagealign(sb.st_size); + buf->bufstart = malloc(buf->bufsize); + buf->bufend = buf->bufstart + buf->bufsize; + buf->gapstart = buf->bufstart; + buf->gapend = buf->bufend; + /* Read the file into the buffer */ + while (sb.st_size && (nread = read(fd, buf->gapstart, sb.st_size)) > 0) + buf->gapstart += nread, sb.st_size -= nread; + if (nread < 0) buf->errfn("Failed to read file"); + } + if (fd > 0) close(fd); /* jump to address if we got one */ if (addr) @@ -75,25 +89,28 @@ void buf_reload(Buf* buf) { void buf_save(Buf* buf) { if (0 == buf_end(buf)) return; - /* text files should always end in a new line. If we detected a binary file or at least a non-utf8 file, skip this part. */ if (!buf_iseol(buf, buf_end(buf)-1)) buf_insert(buf, false, buf_end(buf), '\n'); - size_t wrlen = 0; - if (buf->path) { - FMap file = mmap_readwrite(buf->path, buf_end(buf) * UTF_MAX); - if (file.buf) { - for (size_t i = 0, end = buf_end(buf); i < end; i++) - file.buf[wrlen++] = buf_get(buf, i); - mmap_close(file); - truncate(buf->path, wrlen); + char* wptr; + long fd, nwrite, towrite; + if (buf->path && (fd = open(buf->path, O_WRONLY|O_CREAT, 0644)) >= 0) { + /* write the chunk before the gap */ + wptr = buf->bufstart, towrite = (buf->gapstart - buf->bufstart); + while (towrite && ((nwrite = write(fd, wptr, towrite)) > 0)) + wptr += nwrite, towrite -= nwrite; + /* write the chunk after the gap */ + wptr = buf->gapend, towrite = (buf->bufend - buf->gapend); + while (towrite && ((nwrite = write(fd, wptr, towrite)) > 0)) + wptr += nwrite, towrite -= nwrite; + close(fd); + /* report success or failure */ + if (nwrite >= 0) buf->modified = false; - buf->modtime = modtime(buf->path); - } else { - buf->errfn("Failed to open file for writing"); - } + else + buf->errfn("Failed to write file"); } else { buf->errfn("Need a filename: SaveAs "); } diff --git a/lib/utils.c b/lib/utils.c index 30e7f3e..f5eb902 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -10,51 +10,13 @@ #include #include -static size_t pagealign(size_t sz) { - size_t pgsize = sysconf(_SC_PAGE_SIZE); - size_t alignmask = pgsize - 1; +size_t pagealign(size_t sz) { + size_t pgsize = sysconf(_SC_PAGE_SIZE), alignmask = pgsize - 1; if (sz & alignmask) sz += pgsize - (sz & alignmask); return sz; } -FMap mmap_readonly(char* path) { - FMap file = { .buf = NULL, .len = 0 }; - int fd; - struct stat sb; - if (((fd = open(path, O_RDONLY, 0)) < 0) || - (fstat(fd, &sb) < 0) || - (sb.st_size == 0)) { - return file; - } - file.buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - file.len = sb.st_size; - if (file.buf == MAP_FAILED) - die("memory mapping of file failed"); - close(fd); - return file; -} - -FMap mmap_readwrite(char* path, size_t sz) { - FMap file = { .buf = NULL, .len = 0 }; - int fd = open(path, O_CREAT|O_RDWR, 0644); - if (fd >= 0) { - ftruncate(fd, sz); - void* buf = mmap(NULL, pagealign(sz), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (buf != MAP_FAILED) { - file.buf = buf; - file.len = sz; - } - close(fd); - } - return file; -} - -void mmap_close(FMap file) { - if (file.buf) - munmap(file.buf, file.len); -} - uint64_t getmillis(void) { struct timespec time; clock_gettime(CLOCK_MONOTONIC, &time); @@ -82,19 +44,6 @@ char* stringdup(const char* s) { return ns; } -char* fdgets(int fd) { - char buf[256]; - size_t len = 0, nread = 0; - char* str = NULL; - while ((nread = read(fd, buf, 256)) > 0) { - str = realloc(str, len + nread + 1); - memcpy(str+len, buf, nread); - len += nread; - } - if (str) str[len] = '\0'; - return str; -} - uint64_t modtime(char* path) { struct stat status; if (stat(path, &status) < 0)