Last active
April 7, 2019 12:27
-
-
Save DosAmp/d2cc793ec6c5272fd47af0abace7a569 to your computer and use it in GitHub Desktop.
Simple shell-script counter without lockfile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <libgen.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/mman.h> | |
/* strlen("-9223372036854775808\n") == 21 */ | |
#define MMAP_LEN 21 | |
static const char default_counter[] = ".dotcount"; | |
int main(int argc, char *argv[]) | |
{ | |
int ret = 0; | |
int replaced = 0; | |
char *counterfile = (char *) default_counter; | |
if (argc > 1) { | |
counterfile = argv[1]; | |
} | |
int cfd = open(counterfile, O_RDONLY | O_CLOEXEC, 0); | |
if (cfd == -1) { | |
ret = EXIT_FAILURE; | |
goto end; | |
} | |
void *cmap = mmap(NULL, MMAP_LEN, PROT_READ, MAP_FILE, cfd, 0); | |
if (cmap == MAP_FAILED) { | |
ret = EXIT_FAILURE; | |
goto end; | |
} | |
char *stablecountend; | |
long stablecount = strtol((const char *) cmap, &stablecountend, 10); | |
if (*stablecountend == '\n') { | |
stablecountend++; | |
} | |
off_t stablecountlen = (off_t)(stablecountend-(char*)cmap); | |
munmap(cmap, MMAP_LEN); | |
cmap = NULL; | |
off_t filelen = lseek(cfd, 0, SEEK_END); | |
close(cfd); | |
cfd = -1; | |
long linecount = (long)(filelen-stablecountlen); | |
if (linecount < 0) { | |
linecount = 0; | |
} | |
char *parent = dirname(counterfile); | |
/* strlen("/.new.XXXXXX") = 12 */ | |
char *newtemplate = malloc(strlen(parent) + 13); | |
if (!newtemplate) { | |
ret = EXIT_FAILURE; | |
goto end; | |
} | |
strcpy(newtemplate, parent); | |
strcat(newtemplate, "/.new.XXXXXX"); | |
int nfd = mkostemp(newtemplate, O_CLOEXEC); | |
if (nfd == -1) { | |
ret = EXIT_FAILURE; | |
goto end; | |
} | |
FILE *nfil = fdopen(nfd, "w"); | |
if (fprintf(nfil, "%ld\n", (stablecount + linecount)) > 0) { | |
fclose(nfil); | |
nfd = -1; | |
replaced = rename(newtemplate, counterfile) == 0; | |
} else { | |
/* nothing written, nothing to flush */ | |
ret = EXIT_FAILURE; | |
} | |
end: | |
if (nfd > -1) { | |
close(nfd); | |
if (!replaced) { | |
unlink(newtemplate); | |
} | |
} | |
if (cmap != MAP_FAILED && cmap) { | |
munmap(cmap, MMAP_LEN); | |
} | |
if (cfd > -1) { | |
close(cfd); | |
} | |
if (newtemplate) { | |
free(newtemplate); | |
} | |
return ret; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/ksh | |
# initialize with echo 0 > .dotcount | |
DOTCOUNT=.dotcount | |
MINDIGITS=6 | |
stablecount="$(head -n 1 "$DOTCOUNT" 2>/dev/null)" | |
if [ -z "$stablecount" ]; then | |
# no stable count, count as if there was one | |
stablecount=1 | |
fi | |
# appending/creating is a race-free operation | |
echo >> "$DOTCOUNT" | |
# linecount contains stablecount + number of all newlines since then | |
linecount=$(wc -l < "$DOTCOUNT") | |
# therefore subtract one | |
count=$((${stablecount}+${linecount}-1)) | |
echo "Content-Type: text/html" | |
echo | |
echo '<head><style>html,body{margin: 0}pre{text-align:right}</style></head>' | |
printf "<body><pre>%0${MINDIGITS}d</pre></body>\n" $count |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment