1
0
mirror of https://github.com/fumiama/CMoe-Counter.git synced 2024-11-27 15:20:47 +01:00

fix overlay

This commit is contained in:
源文雨 2023-07-08 20:25:33 +08:00
parent 5ad5065a44
commit da014b2485
6 changed files with 174 additions and 58 deletions

4
.gitignore vendored
View File

@ -5,3 +5,7 @@ build
# misc # misc
.DS_Store .DS_Store
#for test.c
/test
/testlog.txt

View File

@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 2.6)
project(CMoe-Counter C) project(CMoe-Counter C)
SET(CMAKE_BUILD_TYPE "Release") SET(CMAKE_BUILD_TYPE "Release")
# include_directories("/usr/local/include") include_directories("/usr/local/include")
# link_directories("/usr/local/lib") link_directories("/usr/local/lib")
#c99 #c99
add_compile_options(-std=c99) add_compile_options(-std=c99)

98
cmoe.c
View File

@ -9,6 +9,7 @@
static uint32_t* items_len; static uint32_t* items_len;
static counter_t counter; static counter_t counter;
static FILE* fp;
static char* datfile = "dat.sp"; static char* datfile = "dat.sp";
static char* token = "fumiama"; static char* token = "fumiama";
@ -19,7 +20,7 @@ static char* token = "fumiama";
static int _headers(uint32_t content_len, const char* h, size_t hlen) { static int _headers(uint32_t content_len, const char* h, size_t hlen) {
char buf[64]; char buf[64];
size_t offset = ADD_HEADER_PARAM(buf, 0, CONTENT_LEN "\r\n", content_len); size_t offset = ADD_HEADER_PARAM(buf, 0, CONTENT_LEN "\r\n", content_len);
if(offset <= 0) return -1; if (offset <= 0) return -1;
content_len += offset+hlen; content_len += offset+hlen;
struct iovec iov[3] = {{&content_len, sizeof(uint32_t)}, {(void*)h, hlen}, {(void*)buf, offset}}; struct iovec iov[3] = {{&content_len, sizeof(uint32_t)}, {(void*)h, hlen}, {(void*)buf, offset}};
return writev(1, (const struct iovec *)&iov, 3) <= 0; return writev(1, (const struct iovec *)&iov, 3) <= 0;
@ -36,29 +37,29 @@ static inline void http_error(errcode_enum_t code, char* msg) {
// get_arg used malloc but has never freed // get_arg used malloc but has never freed
static char* get_arg(const char* query) { static char* get_arg(const char* query) {
int len = 0; int len = 0;
while(query[len] && query[len] != '&') len++; while (query[len] && query[len] != '&') len++;
if(len <= 0) return NULL; if (len <= 0) return NULL;
char* name = malloc(len+1); char* name = malloc(len+1);
memcpy(name, query, len); memcpy(name, query, len);
name[len] = 0; name[len] = 0;
return name; return name;
} }
static int del_user(FILE* fp, SIMPLE_PB* spb) { static int del_user(FILE* fp, simple_pb_t* spb) {
counter_t *d = (counter_t *)spb->target; counter_t *d = (counter_t *)spb->target;
uint32_t next = ftell(fp); uint32_t next = ftell(fp);
uint32_t this = next - spb->real_len; uint32_t this = next - spb->real_len;
fseek(fp, 0, SEEK_END); if (fseek(fp, 0, SEEK_END) < 0) return -2;
uint32_t end = ftell(fp); uint32_t end = ftell(fp);
if(next == end) return ftruncate(fileno(fp), end - spb->real_len); if (next == end) return ftruncate(fileno(fp), end - spb->real_len);
uint32_t cap = end - next; uint32_t cap = end - next;
char *data = malloc(cap); char *data = malloc(cap);
if(data) { if (data) {
fseek(fp, next, SEEK_SET); if (fseek(fp, next, SEEK_SET)) return -3;
if(fread(data, cap, 1, fp) == 1) { if (fread(data, cap, 1, fp) == 1) {
if(!ftruncate(fileno(fp), end - spb->real_len)){ if (!ftruncate(fileno(fp), end - spb->real_len)){
fseek(fp, this, SEEK_SET); if (fseek(fp, this, SEEK_SET)) return -4;
if(fwrite(data, cap, 1, fp) == 1) { if (fwrite(data, cap, 1, fp) == 1) {
free(data); free(data);
fflush(fp); fflush(fp);
return 0; return 0;
@ -73,34 +74,34 @@ static int del_user(FILE* fp, SIMPLE_PB* spb) {
static inline int add_user(char* name, uint32_t count, FILE* fp) { static inline int add_user(char* name, uint32_t count, FILE* fp) {
counter.count = count; counter.count = count;
strncpy(counter.name, name, COUNTER_NAME_LEN-1); strncpy(counter.name, name, COUNTER_NAME_LEN-1);
fseek(fp, 0, SEEK_END); if (fseek(fp, 0, SEEK_END) < 0) return -2;
return !set_pb(fp, items_len, sizeof(counter_t), &counter); return !set_pb(fp, items_len, sizeof(counter_t), &counter);
} }
static inline uint32_t get_content_len(int isbig, uint16_t* len_type, char* cntstr) { static inline uint32_t get_content_len(int isbig, uint16_t* len_type, char* cntstr) {
uint32_t len = sizeof(svg_small) // small & big has the same len uint32_t len = sizeof(svg_small) // small & big has the same len
+ sizeof(svg_tail) - 1; + sizeof(svg_tail) - 1;
for(int i = 0; cntstr[i]; i++) { for (int i = 0; cntstr[i]; i++) {
len += len_type[cntstr[i] - '0'] + (sizeof(img_slot_front) + sizeof(img_slot_rear) - 2); len += len_type[cntstr[i] - '0'] + (sizeof(img_slot_front) + sizeof(img_slot_rear) - 2);
if(i > 0) len++; if (i > 0) len++;
if(i > 2-isbig) len++; if (i > 2-isbig) len++;
} }
return len; return len;
} }
#define has_next(fp, ch) ((ch=getc(fp)),(feof(fp)?0:(ungetc(ch,fp),1))) #define has_next(fp, ch) ((ch=getc(fp)),(feof(fp)?0:(ungetc(ch,fp),1)))
#define set_type(name, t, l) if(!strcmp(theme, name)) {\ #define set_type(name, t, l) if (!strcmp(theme, name)) {\
theme_type = (char**)t;\ theme_type = (char**)t;\
len_type = (uint16_t*)l;\ len_type = (uint16_t*)l;\
} }
static void return_count(FILE* fp, char* name, char* theme) { static void return_count(FILE* fp, char* name, char* theme) {
int ch, exist = 0, user_exist = 0; int ch, exist = 0, user_exist = 0;
char buf[sizeof(SIMPLE_PB)+sizeof(counter_t)]; char buf[sizeof(simple_pb_t)+sizeof(counter_t)];
while(has_next(fp, ch)) { while (has_next(fp, ch)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf); simple_pb_t *spb = read_pb_into(fp, (simple_pb_t*)buf);
counter_t *d = (counter_t *)spb->target; counter_t *d = (counter_t *)spb->target;
if (strcmp(name, d->name)) continue; if (strcmp(name, d->name)) continue;
if(del_user(fp, spb)) { if (del_user(fp, spb)) {
http_error(HTTP500, "Unable to Delete Old Data."); http_error(HTTP500, "Unable to Delete Old Data.");
return; return;
} }
@ -111,14 +112,14 @@ static void return_count(FILE* fp, char* name, char* theme) {
char cntstrbuf[11]; char cntstrbuf[11];
sprintf(cntstrbuf, "%010u", d->count); sprintf(cntstrbuf, "%010u", d->count);
char* cntstr = cntstrbuf; char* cntstr = cntstrbuf;
for(int i = 0; i < 10; i++) if(cntstrbuf[i] != '0') { for (int i = 0; i < 10; i++) if (cntstrbuf[i] != '0') {
if(i > 2) cntstr = cntstrbuf+i-2; if (i > 2) cntstr = cntstrbuf+i-2;
break; break;
} }
int isbig = 0; int isbig = 0;
char** theme_type = (char**)mb; char** theme_type = (char**)mb;
uint16_t* len_type = (uint16_t*)mbl; uint16_t* len_type = (uint16_t*)mbl;
if(theme) { if (theme) {
set_type("mbh", mbh, mbhl) else set_type("mbh", mbh, mbhl) else
set_type("r34", r34, r34l) else set_type("r34", r34, r34l) else
set_type("gb", gb, gbl) else set_type("gb", gb, gbl) else
@ -127,7 +128,7 @@ static void return_count(FILE* fp, char* name, char* theme) {
} }
int w, h; int w, h;
char *head; char *head;
if(isbig) { if (isbig) {
w = W_BIG; w = W_BIG;
h = H_BIG; h = H_BIG;
head = (char*)svg_big; head = (char*)svg_big;
@ -137,12 +138,12 @@ static void return_count(FILE* fp, char* name, char* theme) {
h = H_SMALL; h = H_SMALL;
head = (char*)svg_small; head = (char*)svg_small;
} }
if(headers(get_content_len(isbig, len_type, cntstr), "image/svg+xml")) { if (headers(get_content_len(isbig, len_type, cntstr), "image/svg+xml")) {
write(1, "\0\0\0\0", 4); write(1, "\0\0\0\0", 4);
return; return;
} }
printf(head, w*(10+cntstrbuf-cntstr)); printf(head, w*(10+cntstrbuf-cntstr));
for(int i = 0; cntstr[i]; i++) { for (int i = 0; cntstr[i]; i++) {
printf(img_slot_front, w * i, w, h); printf(img_slot_front, w * i, w, h);
int n = cntstr[i] - '0'; int n = cntstr[i] - '0';
fwrite(theme_type[n], len_type[n], 1, stdout); fwrite(theme_type[n], len_type[n], 1, stdout);
@ -156,9 +157,9 @@ static void return_count(FILE* fp, char* name, char* theme) {
static int name_exist(FILE* fp, char* name) { static int name_exist(FILE* fp, char* name) {
int ch, exist = 0; int ch, exist = 0;
char buf[sizeof(SIMPLE_PB)+sizeof(counter_t)]; char buf[sizeof(simple_pb_t)+sizeof(counter_t)];
while(has_next(fp, ch)) { while (has_next(fp, ch)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf); simple_pb_t *spb = read_pb_into(fp, (simple_pb_t*)buf);
counter_t *d = (counter_t *)spb->target; counter_t *d = (counter_t *)spb->target;
if (!strcmp(name, d->name)) return 1; if (!strcmp(name, d->name)) return 1;
} }
@ -170,47 +171,46 @@ static int name_exist(FILE* fp, char* name) {
#define QS (argv[2]) #define QS (argv[2])
// Usage: cmoe method query_string // Usage: cmoe method query_string
int main(int argc, char **argv) { int main(int argc, char **argv) {
if(argc != 3) { if (argc != 3) {
http_error(HTTP500, "Argument Count Error."); http_error(HTTP500, "Argument Count Error.");
return -1; return -1;
} }
char* str = getenv("DATFILE"); char* str = getenv("DATFILE");
if(str != NULL) datfile = str; if (str != NULL) datfile = str;
str = getenv("TOKEN"); str = getenv("TOKEN");
if(str != NULL) token = str; if (str != NULL) token = str;
char* name = strstr(QS, "name="); char* name = strstr(QS, "name=");
items_len = align_struct(sizeof(counter_t), 2, &counter.name, &counter.count); items_len = align_struct(sizeof(counter_t), 2, &counter.name, &counter.count);
if(!items_len) { if (!items_len) {
http_error(HTTP500, "Align Struct Error."); http_error(HTTP500, "Align Struct Error.");
return 2; return 2;
} }
if(!name) { if (!name) {
http_error(HTTP400, "Name Argument Notfound."); http_error(HTTP400, "Name Argument Notfound.");
return 3; return 3;
} }
name = get_arg(name + 5); name = get_arg(name + 5);
if(!name) { if (!name) {
http_error(HTTP400, "Null Name Argument."); http_error(HTTP400, "Null Name Argument.");
return 4; return 4;
} }
char* theme = strstr(QS, "theme="); char* theme = strstr(QS, "theme=");
if(theme) { if (theme) {
theme = get_arg(theme + 6); theme = get_arg(theme + 6);
} }
char* reg = strstr(QS, "reg="); char* reg = strstr(QS, "reg=");
int fd; FILE* fp; int fd;
if (!reg) { if (!reg) {
if((fd=create_or_open(datfile)) < 0) { if ((fd=create_or_open(datfile)) < 0) {
http_error(HTTP500, "Open File Error."); http_error(HTTP500, "Open File Error.");
return -2; return -2;
} }
if(flock(fd, LOCK_EX)) { if (flock(fd, LOCK_EX)) {
http_error(HTTP500, "Lock File Error."); http_error(HTTP500, "Lock File Error.");
return -3; return -3;
} }
fp = fdopen(fd, "rb+"); fp = fdopen(fd, "rb+");
return_count(fp, name, theme); return_count(fp, name, theme);
fflush(fp); flock(fd, LOCK_UN); close(fd);
return 0; return 0;
} }
reg = get_arg(reg + 4); reg = get_arg(reg + 4);
@ -218,31 +218,33 @@ int main(int argc, char **argv) {
http_error(HTTP400, "Null Register Token."); http_error(HTTP400, "Null Register Token.");
return 5; return 5;
} }
if(strcmp(reg, token)) { if (strcmp(reg, token)) {
http_error(HTTP400, "Token Error."); http_error(HTTP400, "Token Error.");
return 6; return 6;
} }
if((fd=create_or_open(datfile)) < 0) { if ((fd=create_or_open(datfile)) < 0) {
http_error(HTTP500, "Open File Error."); http_error(HTTP500, "Open File Error.");
return -4; return -4;
} }
if(flock(fd, LOCK_EX)) { if (flock(fd, LOCK_EX)) {
http_error(HTTP500, "Lock File Error."); http_error(HTTP500, "Lock File Error.");
return -5; return -5;
} }
fp = fdopen(fd, "rb+"); fp = fdopen(fd, "rb+");
if(name_exist(fp, name)) { if (name_exist(fp, name)) {
fflush(fp); flock(fd, LOCK_UN); close(fd);
http_error(HTTP400, "Name Exist."); http_error(HTTP400, "Name Exist.");
return 7; return 7;
} }
fseek(fp, 0, SEEK_END); fseek(fp, 0, SEEK_END);
add_user(name, 0, fp); add_user(name, 0, fp);
fflush(fp); flock(fd, LOCK_UN); close(fd);
char* msg = "<P>Success.\r\n"; char* msg = "<P>Success.\r\n";
if(headers(strlen(msg), "text/html")) { if (headers(strlen(msg), "text/html")) {
write(1, "\0\0\0\0", 4); write(1, "\0\0\0\0", 4);
return 8; return 8;
} }
return write(1, msg, strlen(msg)) <= 0; return write(1, msg, strlen(msg)) <= 0;
} }
static void __attribute__((destructor)) defer_close_fp() {
if (fp) fclose(fp);
}

View File

@ -10,9 +10,9 @@ static counter_t counter;
static FILE* fp; static FILE* fp;
static char buf[sizeof(SIMPLE_PB)+sizeof(counter_t)]; static char buf[sizeof(simple_pb_t)+sizeof(counter_t)];
static int del_user(FILE* fp, SIMPLE_PB* spb) { static int del_user(FILE* fp, simple_pb_t* spb) {
counter_t *d = (counter_t *)spb->target; counter_t *d = (counter_t *)spb->target;
uint32_t next = ftell(fp); uint32_t next = ftell(fp);
uint32_t this = next - spb->real_len; uint32_t this = next - spb->real_len;
@ -99,7 +99,7 @@ int main(int argc, char** argv) {
return 5; return 5;
} }
while(has_next(fp, c)) { while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf); simple_pb_t *spb = read_pb_into(fp, (simple_pb_t*)buf);
counter_t *d = (counter_t *)spb->target; counter_t *d = (counter_t *)spb->target;
if (strcmp(counter.name, d->name)) continue; if (strcmp(counter.name, d->name)) continue;
if(del_user(fp, spb)) { if(del_user(fp, spb)) {
@ -127,7 +127,7 @@ int main(int argc, char** argv) {
return 7; return 7;
} }
while(has_next(fp, c)) { while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf); simple_pb_t *spb = read_pb_into(fp, (simple_pb_t*)buf);
counter_t *d = (counter_t *)spb->target; counter_t *d = (counter_t *)spb->target;
if (strstr(d->name, counter.name)) { if (strstr(d->name, counter.name)) {
if(del_user(fp, spb)) { if(del_user(fp, spb)) {
@ -151,7 +151,7 @@ int main(int argc, char** argv) {
return 5; return 5;
} }
while(has_next(fp, c)) { while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf); simple_pb_t *spb = read_pb_into(fp, (simple_pb_t*)buf);
counter_t *d = (counter_t *)spb->target; counter_t *d = (counter_t *)spb->target;
if (strcmp(counter.name, d->name)) continue; if (strcmp(counter.name, d->name)) continue;
printf("user '%s' = %u.\n", d->name, d->count); printf("user '%s' = %u.\n", d->name, d->count);
@ -170,7 +170,7 @@ int main(int argc, char** argv) {
return 7; return 7;
} }
while(has_next(fp, c)) { while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf); simple_pb_t *spb = read_pb_into(fp, (simple_pb_t*)buf);
counter_t *d = (counter_t *)spb->target; counter_t *d = (counter_t *)spb->target;
if (d->count < counter.count) { if (d->count < counter.count) {
printf("'%s' = %u\n", d->name, d->count); printf("'%s' = %u\n", d->name, d->count);
@ -195,7 +195,7 @@ int main(int argc, char** argv) {
return 7; return 7;
} }
while(has_next(fp, c)) { while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf); simple_pb_t *spb = read_pb_into(fp, (simple_pb_t*)buf);
counter_t *d = (counter_t *)spb->target; counter_t *d = (counter_t *)spb->target;
if (d->count < counter.count) { if (d->count < counter.count) {
if(del_user(fp, spb)) { if(del_user(fp, spb)) {
@ -222,7 +222,7 @@ int main(int argc, char** argv) {
return 7; return 7;
} }
while(has_next(fp, c)) { while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf); simple_pb_t *spb = read_pb_into(fp, (simple_pb_t*)buf);
counter_t *d = (counter_t *)spb->target; counter_t *d = (counter_t *)spb->target;
if (!counter.name[0] || strstr(d->name, counter.name)) { if (!counter.name[0] || strstr(d->name, counter.name)) {
printf("'%s' = %u\n", d->name, d->count); printf("'%s' = %u\n", d->name, d->count);

89
test.c Normal file
View File

@ -0,0 +1,89 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/file.h>
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
#define THREADCNT 1024
int pipefds[2*THREADCNT];
#define create_or_open(filename) (open(filename, O_CREAT|O_RDWR, 0600))
int main(int argc, char** argv) {
printf("run: ");
for (int i = 0; i < argc; i++) {
printf("%s ", argv[i]);
}
puts(".");
if (argc == 1) {
for (int i = 0; i < THREADCNT; i++) {
if (pipe(&pipefds[i*2]) < 0) {
perror("pipe");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
char buf[5];
sprintf(buf, "%04d", i);
if (!pid) {
printf("[%s] start@[%d,%d]=(%d,%d).\n", buf, i*2, i*2+1, pipefds[i*2], pipefds[i*2+1]);
dup2(pipefds[i*2+1], STDOUT_FILENO);
close(pipefds[i*2]);
//printf("[%s] sub close@%d=%d, execl.\n", buf, i*2, pipefds[i*2]);
execl("./test", "./test", buf, NULL);
perror("execl");
exit(EXIT_FAILURE); // a success execl will never return
} else {
close(pipefds[i*2+1]);
//printf("[%s] main close@%d=%d, read.\n", buf, i*2+1, pipefds[i*2+1]);
}
}
if (!fork()) {
char buf[128]; ssize_t n;
for (int i = 0; i < THREADCNT; i++) {
do {
n = read(pipefds[i*2], buf, sizeof(buf));
if (n < 0) {
perror("read");
exit(EXIT_FAILURE);
}
if (n > 0) {
buf[n] = 0;
printf("%zu> %s", n, buf);
}
} while (n > 0);
}
} else waitpid(-1, NULL, 0);
return 0;
}
usleep(rand()%1000);
int fd = create_or_open("testlog.txt");
if (fd < 0) {
perror("open");
exit(EXIT_FAILURE);
}
if(flock(fd, LOCK_EX)) {
perror("flock");
exit(EXIT_FAILURE);
}
FILE* fp = fdopen(fd, "rb+");
fseek(fp, 0, SEEK_END);
fputs(argv[1], fp);
putc('\n', fp);
srand(*(uint32_t*)argv[1]);
int rndslp = rand()%1000;
printf("[%s] get lock. sleep %d ms\n", argv[1], rndslp);
usleep(rndslp);
printf("[%s] release lock.\n", argv[1]);
fclose(fp);
//close(fd);
return 0;
}

21
test.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash
cd build
./cmoe GET "name=fumiama&reg=fumiama"
./cmoe GET "name=fumiam&reg=fumiama"
./cmoe GET "name=fumia&reg=fumiama"
./cmoe GET "name=fumi&reg=fumiama"
./cmoe GET "name=fum&reg=fumiama"
./cmoe GET "name=fu&reg=fumiama"
./cmoe GET "name=f&reg=fumiama"
for ((i=0; i<$1; i++))
do
./cmoe GET "name=fumiama&theme=r34" &
./cmoe GET "name=fumiam&theme=r34" &
./cmoe GET "name=fumia&theme=r34" &
./cmoe GET "name=fumi&theme=r34" &
./cmoe GET "name=fum&theme=r34" &
./cmoe GET "name=fu&theme=r34" &
./cmoe GET "name=f&theme=r34" &
done