Skip to content

Commit

Permalink
Support partial saves
Browse files Browse the repository at this point in the history
  • Loading branch information
martanne committed Oct 25, 2014
1 parent d19c796 commit af18596
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 12 deletions.
35 changes: 24 additions & 11 deletions text.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,17 +594,23 @@ size_t text_redo(Text *txt) {
return pos;
}

bool text_save(Text *txt, const char *filename) {
Filerange r = (Filerange){ .start = 0, .end = text_size(txt) };
return text_range_save(txt, &r, filename);
}

/* save current content to given filename. the data is first saved to `filename~`
* and then atomically moved to its final (possibly alredy existing) destination
* using rename(2).
*/
bool text_save(Text *txt, const char *filename) {
bool text_range_save(Text *txt, Filerange *range, const char *filename) {
int fd = -1;
size_t len = strlen(filename) + 10;
char *tmpname = malloc(len);
size_t bufsize = strlen(filename) + 10;
size_t size = range->end - range->start;
char *tmpname = malloc(bufsize);
if (!tmpname)
return false;
snprintf(tmpname, len, "%s~", filename);
snprintf(tmpname, bufsize, "%s~", filename);
// TODO preserve user/group
struct stat meta;
if (stat(filename, &meta) == -1) {
Expand All @@ -616,21 +622,28 @@ bool text_save(Text *txt, const char *filename) {
/* O_RDWR is needed because otherwise we can't map with MAP_SHARED */
if ((fd = open(tmpname, O_CREAT|O_RDWR|O_TRUNC, meta.st_mode)) == -1)
goto err;
if (ftruncate(fd, txt->size) == -1)
if (ftruncate(fd, size) == -1)
goto err;
if (txt->size > 0) {
void *buf = mmap(NULL, txt->size, PROT_WRITE, MAP_SHARED, fd, 0);
if (size > 0) {
void *buf = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED)
goto err;

char *cur = buf;
text_iterate(txt, it, 0) {
size_t len = it.end - it.start;
memcpy(cur, it.start, len);
size_t rem = size;

for (Iterator it = text_iterator_get(txt, range->start);
rem > 0 && text_iterator_valid(&it);
text_iterator_next(&it)) {
size_t len = it.end - it.text;
if (len > rem)
len = rem;
memcpy(cur, it.text, len);
cur += len;
rem -= len;
}

if (munmap(buf, txt->size) == -1)
if (munmap(buf, size) == -1)
goto err;
}
if (close(fd) == -1)
Expand Down
1 change: 1 addition & 0 deletions text.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ bool text_modified(Text*);
/* test whether the underlying file uses UNIX style \n or Windows style \r\n newlines */
bool text_newlines_crnl(Text*);
bool text_save(Text*, const char *file);
bool text_range_save(Text*, Filerange*, const char *file);
ssize_t text_write(Text*, int fd);
void text_free(Text*);

Expand Down
2 changes: 1 addition & 1 deletion vis.c
Original file line number Diff line number Diff line change
Expand Up @@ -1421,7 +1421,7 @@ static bool cmd_write(Filerange *range, const char *argv[]) {
return false;
}
for (const char **file = &argv[1]; *file; file++) {
if (!text_save(text, *file)) {
if (!text_range_save(text, range, *file)) {
editor_info_show(vis, "Can't write `%s'", *file);
return false;
}
Expand Down

0 comments on commit af18596

Please sign in to comment.