├── .gitignore ├── README.md ├── doc-examples ├── dns │ ├── Makefile │ └── uv_getaddrinfo.c ├── filesystem │ ├── Makefile │ ├── testfile │ ├── uv_fs_chown.c │ ├── uv_fs_close.c │ ├── uv_fs_mkdir.c │ ├── uv_fs_open.c │ ├── uv_fs_read.c │ ├── uv_fs_readdir.c │ ├── uv_fs_rename.c │ ├── uv_fs_rmdir.c │ ├── uv_fs_stat.c │ ├── uv_fs_unlink.c │ └── uv_fs_write.c └── tcp │ ├── Makefile │ ├── uv_tcp_bind.c │ ├── uv_tcp_init.c │ └── uv_tcp_listen.c ├── fs_read ├── Makefile └── main.c ├── helloworld ├── Makefile └── main.c ├── idle-basic ├── Makefile └── main.c ├── internal ├── Makefile ├── queue.c └── queue.h ├── shell ├── Makefile ├── test2 ├── uv_shell.c └── uv_shell.h ├── streams ├── Makefile └── main.c ├── tcp-echo-server ├── Makefile └── tcp_echo_server.c ├── uvcat ├── Makefile └── uvcat.c └── uvtee ├── Makefile └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | *.out 10 | 11 | # Packages # 12 | ############ 13 | # it's better to unpack these files and commit the raw source 14 | # git has its own built in compression methods 15 | *.7z 16 | *.dmg 17 | *.gz 18 | *.iso 19 | *.jar 20 | *.rar 21 | *.tar 22 | *.zip 23 | 24 | # Logs and databases # 25 | ###################### 26 | *.log 27 | *.sql 28 | *.sqlite 29 | *.tmp 30 | *.temp 31 | 32 | # OS generated files # 33 | ###################### 34 | .DS_Store 35 | .DS_Store? 36 | ._* 37 | .Spotlight-V100 38 | .Trashes 39 | Icon? 40 | ehthumbs.db 41 | Thumbs.db 42 | 43 | # Nodejs packages # 44 | ################### 45 | node_modules 46 | 47 | # Cloud9 ide # 48 | ############## 49 | .c9revisions 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libuv-snippets 2 | 3 | some libuv code snippets written while learning c and libuv. 4 | 5 | If you are interested on internals of libuv. 6 | Checkout [libuv internals](http://github.com/bodokaiser/libuv-internals). 7 | 8 | ## Ressources 9 | 10 | * [uvbook](http://nikhilm.github.com/uvbook) 11 | * [libuv header](http://github.com/joyent/libuv/blob/master/include/uv.h) 12 | 13 | ## Installation 14 | 15 | I use a global copy of the uv library installed with homebrew: 16 | 17 | ``` 18 | brew install libuv 19 | 20 | ``` 21 | 22 | to compile the specific file just change to its dir and run ```make```. 23 | 24 | ## License 25 | 26 | Copyright © 2013 Bodo Kaiser 27 | 28 | Permission is hereby granted, free of charge, to any person obtaining 29 | a copy of this software and associated documentation files (the 30 | "Software"), to deal in the Software without restriction, including 31 | without limitation the rights to use, copy, modify, merge, publish, 32 | distribute, sublicense, and/or sell copies of the Software, and to 33 | permit persons to whom the Software is furnished to do so, subject to 34 | the following conditions: 35 | 36 | The above copyright notice and this permission notice shall be 37 | included in all copies or substantial portions of the Software. 38 | 39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 40 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 41 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 42 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 43 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 44 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 45 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 46 | -------------------------------------------------------------------------------- /doc-examples/dns/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS = -luv 2 | 3 | all: uv_getaddrinfo 4 | 5 | exec: 6 | ./uv_getaddrinfo 7 | 8 | clean: 9 | rm -Rf *.o 10 | 11 | uv_getaddrinfo: 12 | $(CC) -o uv_getaddrinfo.o uv_getaddrinfo.c $(LDFLAGS) 13 | -------------------------------------------------------------------------------- /doc-examples/dns/uv_getaddrinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | uv_loop_t* loop; 6 | 7 | uv_getaddrinfo_t* handle; 8 | 9 | void getaddrinfo_cb(uv_getaddrinfo_t* handle, int status, 10 | struct addrinfo* response); 11 | 12 | const char* name = "localhost"; 13 | 14 | int main() { 15 | loop = uv_default_loop(); 16 | 17 | int r = uv_getaddrinfo(loop, handle, getaddrinfo_cb, name, "80", NULL); 18 | 19 | if (r) { 20 | printf("Error at dns request: %s.\n", 21 | uv_strerror(uv_last_error(loop))); 22 | } 23 | 24 | return 0; 25 | } 26 | 27 | void getaddrinfo_cb(uv_getaddrinfo_t* handle, int status, 28 | struct addrinfo* response) { 29 | 30 | printf("%s \n", handle->data); 31 | 32 | free(handle); 33 | uv_freeaddrinfo(response); 34 | } 35 | -------------------------------------------------------------------------------- /doc-examples/filesystem/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS = -luv 2 | 3 | all: uv_fs_open uv_fs_read uv_fs_write uv_fs_close uv_fs_unlink \ 4 | uv_fs_mkdir uv_fs_rmdir uv_fs_readdir uv_fs_rename uv_fs_stat \ 5 | uv_fs_chown 6 | 7 | exec: 8 | ./uv_fs_open.o && ./uv_fs_read.o && ./uv_fs_write.o && ./uv_fs_close.o && \ 9 | ./uv_fs_unlink.o && ./uv_fs_mkdir.o && ./uv_fs_rmdir.o && \ 10 | ./uv_fs_readdir.o && ./uv_fs_rename.o && ./uv_fs_stat.o && \ 11 | ./uv_fs_chown.o 12 | 13 | clean: 14 | rm -Rf *.o *.tmp 15 | 16 | uv_fs_open: 17 | $(CC) -o uv_fs_open.o uv_fs_open.c $(LDFLAGS) 18 | 19 | uv_fs_read: 20 | $(CC) -o uv_fs_read.o uv_fs_read.c $(LDFLAGS) 21 | 22 | uv_fs_write: 23 | $(CC) -o uv_fs_write.o uv_fs_write.c $(LDFLAGS) 24 | 25 | uv_fs_close: 26 | $(CC) -o uv_fs_close.o uv_fs_close.c $(LDFLAGS) 27 | 28 | uv_fs_unlink: 29 | $(CC) -o uv_fs_unlink.o uv_fs_unlink.c $(LDFLAGS) 30 | 31 | uv_fs_mkdir: 32 | $(CC) -o uv_fs_mkdir.o uv_fs_mkdir.c $(LDFLAGS) 33 | 34 | uv_fs_rmdir: 35 | $(CC) -o uv_fs_rmdir.o uv_fs_rmdir.c $(LDFLAGS) 36 | 37 | uv_fs_readdir: 38 | $(CC) -o uv_fs_readdir.o uv_fs_readdir.c $(LDFLAGS) 39 | 40 | uv_fs_rename: 41 | $(CC) -o uv_fs_rename.o uv_fs_rename.c $(LDFLAGS) 42 | 43 | uv_fs_stat: 44 | $(CC) -o uv_fs_stat.o uv_fs_stat.c $(LDFLAGS) 45 | 46 | uv_fs_chown: 47 | $(CC) -o uv_fs_chown.o uv_fs_chown.c $(LDFLAGS) 48 | -------------------------------------------------------------------------------- /doc-examples/filesystem/testfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bodokaiser/libuv-snippets/c22bc6f30ec765cb91b9628cc505a12f765f031d/doc-examples/filesystem/testfile -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_chown.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t chown_req; 7 | 8 | void chown_cb(uv_fs_t* req); 9 | 10 | const char* path = "testfile"; 11 | 12 | int main() { 13 | loop = uv_default_loop(); 14 | 15 | uv_fs_chown(loop, &chown_req, path, 501, 12,chown_cb); 16 | 17 | uv_run(loop, UV_RUN_DEFAULT); 18 | 19 | return 0; 20 | } 21 | 22 | void chown_cb(uv_fs_t* req) { 23 | int result = req->result; 24 | 25 | if (result == -1) { 26 | fprintf(stderr, "Error at chaning owner of file: %s.\n", 27 | uv_strerror(uv_last_error(loop))); 28 | } 29 | 30 | uv_fs_req_cleanup(req); 31 | 32 | printf("Successfully changed owner of file.\n"); 33 | } 34 | -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_close.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t open_req; 7 | uv_fs_t close_req; 8 | 9 | void on_open(uv_fs_t* req); 10 | void on_close(uv_fs_t* req); 11 | 12 | const char* path = "Makefile"; 13 | 14 | int main() { 15 | loop = uv_default_loop(); 16 | 17 | int r = uv_fs_open(loop, &open_req, path, O_RDONLY, S_IRUSR, on_open); 18 | 19 | if (r) { 20 | fprintf(stderr, "Error on opening file: %s.\n", 21 | uv_strerror(uv_last_error(loop))); 22 | } 23 | 24 | uv_run(loop, UV_RUN_DEFAULT); 25 | 26 | return 0; 27 | } 28 | 29 | void on_open(uv_fs_t* req) { 30 | int result = req->result; 31 | 32 | if (result == -1) { 33 | fprintf(stderr, "Error on opening file: %s.\n", 34 | uv_strerror(uv_last_error(loop))); 35 | } 36 | 37 | uv_fs_req_cleanup(req); 38 | uv_fs_close(loop, &close_req, open_req.result, on_close); 39 | } 40 | 41 | void on_close(uv_fs_t* req) { 42 | int result = req->result; 43 | 44 | if (result == -1) { 45 | fprintf(stderr, "Error on closing file: %s.\n", 46 | uv_strerror(uv_last_error(loop))); 47 | } 48 | 49 | uv_fs_req_cleanup(req); 50 | 51 | printf("Successfully opened and closed a file.\n"); 52 | } 53 | -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_mkdir.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t mkdir_req; 7 | 8 | void mkdir_cb(uv_fs_t* req); 9 | 10 | const char* path = "dir.tmp"; 11 | 12 | int main() { 13 | loop = uv_default_loop(); 14 | 15 | int r = uv_fs_mkdir(loop, &mkdir_req, path, S_IRUSR | S_IWUSR, mkdir_cb); 16 | 17 | if (r) { 18 | fprintf(stderr, "Error at creating directory: %s.\n", 19 | uv_strerror(uv_last_error(loop))); 20 | } 21 | 22 | uv_run(loop, UV_RUN_DEFAULT); 23 | 24 | return 0; 25 | } 26 | 27 | void mkdir_cb(uv_fs_t* req) { 28 | int result = req->result; 29 | 30 | if (result == -1) { 31 | fprintf(stderr, "Error at creating directory: %s.\n", 32 | uv_strerror(uv_last_error(loop))); 33 | } 34 | 35 | printf("Successfully created directory.\n"); 36 | 37 | uv_fs_req_cleanup(req); 38 | } 39 | -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_open.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t open_req; 7 | 8 | void open_cb(uv_fs_t* req); 9 | 10 | const char* path = "Makefile"; 11 | 12 | int main() { 13 | loop = uv_default_loop(); 14 | 15 | int r = uv_fs_open(loop, &open_req, path, O_RDONLY, S_IRUSR, open_cb); 16 | 17 | if (r) { 18 | fprintf(stderr, "Error at opening file: %s\n", 19 | uv_strerror(uv_last_error(loop))); 20 | } 21 | 22 | uv_run(loop, UV_RUN_DEFAULT); 23 | 24 | return 0; 25 | } 26 | 27 | void open_cb(uv_fs_t* req) { 28 | int result = req->result; 29 | 30 | if (result == -1) { 31 | fprintf(stderr, "Error at opening file: %s\n", 32 | uv_strerror(uv_last_error(loop))); 33 | } 34 | 35 | uv_fs_req_cleanup(req); 36 | 37 | printf("Successfully opened file.\n"); 38 | } 39 | -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_read.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t open_req; 7 | uv_fs_t read_req; 8 | uv_fs_t close_req; 9 | 10 | void open_cb(uv_fs_t* req); 11 | void read_cb(uv_fs_t* req); 12 | void close_cb(uv_fs_t* req); 13 | 14 | char buf[1024]; 15 | const char* path = "Makefile"; 16 | 17 | int main() { 18 | loop = uv_default_loop(); 19 | 20 | int r = uv_fs_open(loop, &open_req, path, O_RDONLY, S_IRUSR, open_cb); 21 | 22 | if (r) { 23 | fprintf(stderr, "Error at opening file: %s.\n", 24 | uv_strerror(uv_last_error(loop))); 25 | } 26 | 27 | uv_run(loop, UV_RUN_DEFAULT); 28 | 29 | return 0; 30 | } 31 | 32 | void open_cb(uv_fs_t* req) { 33 | int result = req->result; 34 | 35 | if (result == -1) { 36 | fprintf(stderr, "Error at opening file: %s.\n", 37 | uv_strerror(uv_last_error(loop))); 38 | } 39 | 40 | uv_fs_req_cleanup(req); 41 | uv_fs_read(loop, &read_req, result, buf, sizeof(buf), -1, read_cb); 42 | } 43 | 44 | void read_cb(uv_fs_t* req) { 45 | int result = req->result; 46 | 47 | if (result == -1) { 48 | fprintf(stderr, "Error at reading file: %s.\n", 49 | uv_strerror(uv_last_error(loop))); 50 | } 51 | 52 | uv_fs_req_cleanup(req); 53 | uv_fs_close(loop, &close_req, open_req.result, close_cb); 54 | } 55 | 56 | void close_cb(uv_fs_t* req) { 57 | int result = req->result; 58 | 59 | if (result == -1) { 60 | fprintf(stderr, "Error at closing file: %s.\n", 61 | uv_strerror(uv_last_error(loop))); 62 | } 63 | 64 | uv_fs_req_cleanup(req); 65 | 66 | printf("Successfully read file.\n"); 67 | } 68 | -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_readdir.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t readdir_req; 7 | 8 | void readdir_cb(uv_fs_t* req); 9 | 10 | const char* path = "../filesystem"; 11 | 12 | int main() { 13 | loop = uv_default_loop(); 14 | 15 | int r = uv_fs_readdir(loop, &readdir_req, path, O_RDONLY, readdir_cb); 16 | 17 | if (r) { 18 | fprintf(stderr, "Error at reading directory: %s.\n", 19 | uv_strerror(uv_last_error(loop))); 20 | 21 | return -1; 22 | } 23 | 24 | uv_run(loop, UV_RUN_DEFAULT); 25 | 26 | return 0; 27 | } 28 | 29 | void readdir_cb(uv_fs_t* req) { 30 | int result = req->result; 31 | 32 | if (result == -1) { 33 | fprintf(stderr, "Error at reading directory: %s.\n", 34 | uv_strerror(uv_last_error(loop))); 35 | } 36 | 37 | uv_fs_req_cleanup(req); 38 | 39 | printf("Successfully read directory content.\n"); 40 | } 41 | -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_rename.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t open_req; 7 | uv_fs_t close_req; 8 | uv_fs_t rename_req; 9 | 10 | void open_cb(uv_fs_t* req); 11 | void close_cb(uv_fs_t* req); 12 | void rename_cb(uv_fs_t* req); 13 | 14 | const char* old_path = "one.tmp"; 15 | const char* new_path = "two.tmp"; 16 | 17 | int main() { 18 | loop = uv_default_loop(); 19 | 20 | int r = uv_fs_open(loop, &open_req, old_path, O_CREAT | O_RDONLY, 21 | S_IRUSR | S_IWUSR, open_cb); 22 | 23 | if (r) { 24 | fprintf(stderr, "Error at opening file: %s.\n", 25 | uv_strerror(uv_last_error(loop))); 26 | 27 | return -1; 28 | } 29 | 30 | uv_run(loop, UV_RUN_DEFAULT); 31 | 32 | return 0; 33 | } 34 | 35 | void open_cb(uv_fs_t* req) { 36 | int result = req->result; 37 | 38 | if (result == -1) { 39 | fprintf(stderr, "Error at opening file: %s.\n", 40 | uv_strerror(uv_last_error(loop))); 41 | } 42 | 43 | uv_fs_req_cleanup(req); 44 | uv_fs_close(loop, &close_req, open_req.result, close_cb); 45 | } 46 | 47 | void close_cb(uv_fs_t* req) { 48 | int result = req->result; 49 | 50 | if (result == -1) { 51 | fprintf(stderr, "Error at closing file: %s.\n", 52 | uv_strerror(uv_last_error(loop))); 53 | } 54 | 55 | uv_fs_req_cleanup(req); 56 | uv_fs_rename(loop, &rename_req, old_path, new_path, rename_cb); 57 | } 58 | 59 | void rename_cb(uv_fs_t* req) { 60 | int result = req->result; 61 | 62 | if (result == -1) { 63 | fprintf(stderr, "Error at renaming file: %s.\n", 64 | uv_strerror(uv_last_error(loop))); 65 | } 66 | 67 | uv_fs_req_cleanup(req); 68 | 69 | printf("Successfully renamed file.\n"); 70 | } 71 | -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_rmdir.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t mkdir_req; 7 | uv_fs_t rmdir_req; 8 | 9 | void mkdir_cb(uv_fs_t* req); 10 | void rmdir_cb(uv_fs_t* req); 11 | 12 | const char* path = "dir2.tmp"; 13 | 14 | int main() { 15 | loop = uv_default_loop(); 16 | 17 | int r = uv_fs_mkdir(loop, &mkdir_req, path, S_IRUSR | S_IWUSR, mkdir_cb); 18 | 19 | if (r) { 20 | fprintf(stderr, "Error at creating directory: %s.\n", 21 | uv_strerror(uv_last_error(loop))); 22 | } 23 | 24 | uv_run(loop, UV_RUN_DEFAULT); 25 | 26 | return 0; 27 | } 28 | 29 | void mkdir_cb(uv_fs_t* req) { 30 | int result = req->result; 31 | 32 | if (result == -1) { 33 | fprintf(stderr, "Error at creating directory: %s.\n", 34 | uv_strerror(uv_last_error(loop))); 35 | } 36 | 37 | uv_fs_req_cleanup(req); 38 | uv_fs_rmdir(loop, &rmdir_req, path, rmdir_cb); 39 | } 40 | 41 | void rmdir_cb(uv_fs_t* req) { 42 | int result = req->result; 43 | 44 | if (result == -1) { 45 | fprintf(stderr, "Error at removing directory: %s.\n", 46 | uv_strerror(uv_last_error(loop))); 47 | } 48 | 49 | uv_fs_req_cleanup(req); 50 | 51 | printf("Successfully removed directory.\n"); 52 | } 53 | -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_stat.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t stat_req; 7 | 8 | void stat_cb(uv_fs_t* req); 9 | 10 | const char* path = "./"; 11 | 12 | int main() { 13 | loop = uv_default_loop(); 14 | 15 | int r = uv_fs_stat(loop, &stat_req, path, stat_cb); 16 | 17 | if (r) { 18 | fprintf(stderr, "Error on reading stats: %s.\n", 19 | uv_strerror(uv_last_error(loop))); 20 | 21 | return -1; 22 | } 23 | 24 | uv_run(loop, UV_RUN_DEFAULT); 25 | 26 | return 0; 27 | } 28 | 29 | void stat_cb(uv_fs_t* req) { 30 | int result = req->result; 31 | 32 | if (result == -1) { 33 | fprintf(stderr, "Error on reading stats: %s.\n", 34 | uv_strerror(uv_last_error(loop))); 35 | } 36 | 37 | uv_fs_req_cleanup(req); 38 | 39 | printf("Successfully read stats.\n"); 40 | } 41 | -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_unlink.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t open_req; 7 | uv_fs_t write_req; 8 | uv_fs_t close_req; 9 | 10 | void open_cb(uv_fs_t* req); 11 | void close_cb(uv_fs_t* req); 12 | void unlink_cb(uv_fs_t* req); 13 | 14 | char buf[] = "blablabla\n"; 15 | const char* path = "txt.tmp"; 16 | 17 | int main() { 18 | loop = uv_default_loop(); 19 | 20 | int r = uv_fs_open(loop, &open_req, path, O_CREAT, S_IRUSR | S_IRUSR, 21 | open_cb); 22 | 23 | if (r) { 24 | fprintf(stderr, "Error opening file: %s.\n", 25 | uv_strerror(uv_last_error(loop))); 26 | } 27 | 28 | uv_run(loop, UV_RUN_DEFAULT); 29 | 30 | return 0; 31 | } 32 | 33 | void open_cb(uv_fs_t* req) { 34 | int result = req->result; 35 | 36 | if (result == -1) { 37 | fprintf(stderr, "Error at opening file: %s.\n", 38 | uv_strerror(uv_last_error(loop))); 39 | } 40 | 41 | uv_fs_req_cleanup(req); 42 | uv_fs_close(loop, &close_req, result, close_cb); 43 | } 44 | 45 | void close_cb(uv_fs_t* req) { 46 | int result = req->result; 47 | 48 | if (result == -1) { 49 | fprintf(stderr, "Error at closing file: %s.\n", 50 | uv_strerror(uv_last_error(loop))); 51 | } 52 | 53 | uv_fs_req_cleanup(req); 54 | uv_fs_unlink(loop, &close_req, path, unlink_cb); 55 | } 56 | 57 | void unlink_cb(uv_fs_t* req) { 58 | int result = req->result; 59 | 60 | if (result == -1) { 61 | fprintf(stderr, "Error at deleting file: %s.\n", 62 | uv_strerror(uv_last_error(loop))); 63 | } 64 | 65 | uv_fs_req_cleanup(req); 66 | 67 | printf("Successfully unlinked file.\n"); 68 | } 69 | -------------------------------------------------------------------------------- /doc-examples/filesystem/uv_fs_write.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | #include "stdio.h" 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t open_req; 7 | uv_fs_t write_req; 8 | uv_fs_t close_req; 9 | 10 | void open_cb(uv_fs_t* req); 11 | void write_cb(uv_fs_t* req); 12 | void close_cb(uv_fs_t* req); 13 | 14 | char buf[] = "blablabla\n"; 15 | const char* path = "write.tmp"; 16 | 17 | int main() { 18 | loop = uv_default_loop(); 19 | 20 | int r = uv_fs_open(loop, &open_req, path, O_WRONLY | O_CREAT, 21 | S_IRUSR | S_IWUSR, open_cb); 22 | 23 | if (r) { 24 | fprintf(stderr, "Error opening file: %s.\n", 25 | uv_strerror(uv_last_error(loop))); 26 | } 27 | 28 | uv_run(loop, UV_RUN_DEFAULT); 29 | 30 | return 0; 31 | } 32 | 33 | void open_cb(uv_fs_t* req) { 34 | int result = req->result; 35 | 36 | if (result == -1) { 37 | fprintf(stderr, "Error opening file: %s.\n", 38 | uv_strerror(uv_last_error(loop))); 39 | } 40 | 41 | uv_fs_req_cleanup(req); 42 | uv_fs_write(loop, &write_req, result, buf, sizeof(buf), -1, write_cb); 43 | } 44 | 45 | void write_cb(uv_fs_t* req) { 46 | int result = req->result; 47 | 48 | if (result == -1) { 49 | fprintf(stderr, "Error writting data to file: %s.\n", 50 | uv_strerror(uv_last_error(loop))); 51 | } 52 | 53 | uv_fs_req_cleanup(req); 54 | uv_fs_close(loop, &close_req, open_req.result, close_cb); 55 | } 56 | 57 | void close_cb(uv_fs_t* req) { 58 | int result = req->result; 59 | 60 | if (result == -1) { 61 | fprintf(stderr, "Error closing file: %s.\n", 62 | uv_strerror(uv_last_error(loop))); 63 | } 64 | 65 | uv_fs_req_cleanup(req); 66 | 67 | printf("Successfuly wrote blabla to file.\n"); 68 | } 69 | -------------------------------------------------------------------------------- /doc-examples/tcp/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS = -luv 2 | 3 | all: uv_tcp_init uv_tcp_bind 4 | 5 | exec: 6 | ./uv_tcp_init.o ./uv_tcp_bind.o 7 | 8 | clean: 9 | rm -Rf *.o 10 | 11 | uv_tcp_init: 12 | $(CC) -o uv_tcp_init.o uv_tcp_init.c $(LDFLAGS) 13 | 14 | uv_tcp_bind: 15 | $(CC) -o uv_tcp_bind.o uv_tcp_bind.c $(LDFLAGS) 16 | -------------------------------------------------------------------------------- /doc-examples/tcp/uv_tcp_bind.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | 3 | uv_loop_t* loop; 4 | 5 | uv_tcp_t tcp_req; 6 | 7 | struct sockaddr_in addr; 8 | 9 | int main() { 10 | loop = uv_default_loop(); 11 | 12 | addr = uv_ip4_addr("127.0.0.1", 3000); 13 | 14 | uv_tcp_init(loop, &tcp_req); 15 | 16 | uv_tcp_bind(&tcp_req, addr); 17 | 18 | return uv_run(loop, UV_RUN_DEFAULT); 19 | } 20 | -------------------------------------------------------------------------------- /doc-examples/tcp/uv_tcp_init.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | 3 | uv_loop_t* loop; 4 | 5 | uv_tcp_t tcp_req; 6 | 7 | int main() { 8 | loop = uv_default_loop(); 9 | 10 | uv_tcp_init(loop, &tcp_req); 11 | 12 | return uv_run(loop, UV_RUN_DEFAULT); 13 | } 14 | -------------------------------------------------------------------------------- /doc-examples/tcp/uv_tcp_listen.c: -------------------------------------------------------------------------------- 1 | #include "uv.h" 2 | 3 | uv_loop_t* loop; 4 | 5 | uv_tcp_t tcp_req; 6 | 7 | struct sockaddr_in addr; 8 | 9 | void listen_cb(uv_stream_t* socket, int status); 10 | 11 | int main() { 12 | loop = uv_default_loop(); 13 | 14 | addr = uv_ip4_addr("127.0.0.1", 3000); 15 | 16 | uv_tcp_init(loop, &tcp_req); 17 | 18 | uv_tcp_bind(&tcp_req, addr); 19 | 20 | int r = uv_tcp_listen((uv_stream_t*) &server, 128, listen_cb); 21 | 22 | if (r) { 23 | return fprintf(stderr, "Error on listening: %s.\n", 24 | uv_strerror(uv_last_error(loop))); 25 | } 26 | 27 | return uv_run(loop, UV_RUN_DEFAULT); 28 | } 29 | 30 | void listen_cb(uv_stream_t* socket, int status) { 31 | if (status == -1) { 32 | return fprintf(stderr, "Error on listening: %s.\n", 33 | uv_strerror(uv_last_error(loop))); 34 | } 35 | 36 | /* handle connecting client */ 37 | } 38 | -------------------------------------------------------------------------------- /fs_read/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS = -luv 2 | 3 | all: 4 | $(CC) -o main.o main.c $(LDFLAGS) 5 | -------------------------------------------------------------------------------- /fs_read/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | uv_loop_t* loop; 5 | 6 | uv_fs_t open_req; 7 | uv_fs_t read_req; 8 | 9 | char buffer[1024]; 10 | 11 | void on_open(uv_fs_t* req); 12 | void on_read(uv_fs_t* req); 13 | void on_write(uv_fs_t* req); 14 | 15 | int main(int argc, char **argv) { 16 | loop = uv_default_loop(); 17 | 18 | char* file = argv[1]; 19 | 20 | uv_fs_open(loop, &open_req, file, O_RDONLY, 0, on_open); 21 | 22 | uv_run(loop, UV_RUN_DEFAULT); 23 | 24 | return 0; 25 | } 26 | 27 | void on_open(uv_fs_t* req) { 28 | if (req->result != -1) 29 | // read or write on file 30 | else 31 | // handle error 32 | 33 | uv_fs_req_cleanup(req); 34 | } 35 | 36 | void on_read(uv_fs_t* req) { 37 | 38 | } 39 | 40 | void on_write(uv_fs_t* req) { 41 | 42 | } 43 | -------------------------------------------------------------------------------- /helloworld/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS = -luv 2 | 3 | all: 4 | $(CC) -o main.o main.c $(LDFLAGS) 5 | -------------------------------------------------------------------------------- /helloworld/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | /* initialize a pointer of struct type uv_loop_t */ 6 | uv_loop_t *loop; 7 | 8 | /* assign pointer to return pointer of uv_loop_new */ 9 | loop = uv_loop_new(); 10 | 11 | /* print out hello world */ 12 | printf("Hello World\n"); 13 | 14 | /* starts the event loop in UV_RUN_DEFAULT mode */ 15 | uv_run(loop, UV_RUN_DEFAULT); 16 | 17 | /* return zero if everything went well */ 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /idle-basic/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS = -luv 2 | 3 | all: 4 | $(CC) -o main.o main.c $(LDFLAGS) 5 | -------------------------------------------------------------------------------- /idle-basic/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* a 64bit integer counter */ 5 | int64_t counter = 0; 6 | 7 | /* is reexecuted until uv_idle_stop is called */ 8 | void wait_for_a_while(uv_idle_t* handle, int status) { 9 | counter++; 10 | 11 | if (counter >= 10e6) 12 | /* stops the idle handle */ 13 | uv_idle_stop(handle); 14 | } 15 | 16 | int main() { 17 | /* our reference to the default loop */ 18 | uv_loop_t *loop; 19 | 20 | /* a idler of uv_idle_t struct type */ 21 | uv_idle_t idler; 22 | 23 | /* let uv return the default loop */ 24 | loop = uv_default_loop(); 25 | 26 | /* initialize a idle handle with the default loop and the reference of our idle type */ 27 | uv_idle_init(loop, &idler); 28 | /* start executing the idle handler and call the wait_for_a_while callback */ 29 | uv_idle_start(&idler, wait_for_a_while); 30 | 31 | printf("Idling ...\n"); 32 | 33 | /* start runing the loop in default mode */ 34 | uv_run(loop, UV_RUN_DEFAULT); 35 | } 36 | -------------------------------------------------------------------------------- /internal/Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | $(CC) -o queue.o queue.c 3 | -------------------------------------------------------------------------------- /internal/queue.c: -------------------------------------------------------------------------------- 1 | #include "queue.h" 2 | #include 3 | 4 | /** 5 | * A pointer to a list node. 6 | */ 7 | static QUEUE* q; 8 | 9 | /** 10 | * Our circulary list. 11 | */ 12 | static QUEUE queue; 13 | 14 | /** 15 | * Our item struct we want to store in queue. 16 | */ 17 | struct user_s { 18 | int age; 19 | char* name; 20 | 21 | QUEUE node; 22 | }; 23 | 24 | int main() { 25 | /** 26 | * This will be our user pointer. 27 | * It will point to the user we received from the queue. 28 | */ 29 | struct user_s* user; 30 | 31 | /** 32 | * John is 44. 33 | */ 34 | struct user_s john; 35 | john.name = "john"; 36 | john.age = 44; 37 | 38 | 39 | /** 40 | * Henry is 32. 41 | */ 42 | struct user_s henry; 43 | henry.name = "henry"; 44 | henry.age = 32; 45 | 46 | /** 47 | * Willy is 99. 48 | */ 49 | struct user_s willy; 50 | willy.name = "willy"; 51 | willy.age = 99; 52 | 53 | /** 54 | * Initialize the queue of each user. 55 | */ 56 | QUEUE_INIT(&queue); 57 | QUEUE_INIT(&john.node); 58 | QUEUE_INIT(&henry.node); 59 | QUEUE_INIT(&willy.node); 60 | 61 | /** 62 | * Lets insert each user to the tail of the list. 63 | */ 64 | QUEUE_INSERT_TAIL(&queue, &john.node); 65 | QUEUE_INSERT_TAIL(&queue, &henry.node); 66 | QUEUE_INSERT_TAIL(&queue, &willy.node); 67 | 68 | /** 69 | * Retrieve a pointer to our first user john. 70 | */ 71 | q = QUEUE_HEAD(&queue); 72 | 73 | /** 74 | * Should retrieve the user behind the "q" pointer. 75 | */ 76 | user = QUEUE_DATA(q, struct user_s, node); 77 | 78 | /** 79 | * Should output the name of john. 80 | */ 81 | printf("Received first inserted user: %s who is %d.\n", 82 | user->name, user->age); 83 | 84 | /** 85 | * Now lets remove john from the queue. 86 | */ 87 | QUEUE_REMOVE(q); 88 | 89 | /** 90 | * Lets output the other two users through a for each loop. 91 | */ 92 | QUEUE_FOREACH(q, &queue) { 93 | user = QUEUE_DATA(q, struct user_s, node); 94 | 95 | printf("Received rest inserted users: %s who is %d.\n", 96 | user->name, user->age); 97 | } 98 | 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /internal/queue.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Ben Noordhuis 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice and this permission notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef QUEUE_H_ 17 | #define QUEUE_H_ 18 | 19 | typedef void *QUEUE[2]; 20 | 21 | /* Private macros. */ 22 | #define QUEUE_NEXT(q) ((*(q))[0]) 23 | #define QUEUE_PREV(q) ((*(q))[1]) 24 | #define QUEUE_PREV_NEXT(q) (QUEUE_NEXT((QUEUE *) QUEUE_PREV(q))) 25 | #define QUEUE_NEXT_PREV(q) (QUEUE_PREV((QUEUE *) QUEUE_NEXT(q))) 26 | 27 | /* Public macros. */ 28 | #define QUEUE_DATA(ptr, type, field) \ 29 | ((type *) ((char *) (ptr) - ((long) &((type *) 0)->field))) 30 | 31 | #define QUEUE_FOREACH(q, h) \ 32 | for ((q) = (*(h))[0]; (q) != (h); (q) = (*(q))[0]) 33 | 34 | #define QUEUE_EMPTY(q) \ 35 | (QUEUE_NEXT(q) == (q)) 36 | 37 | #define QUEUE_HEAD(q) \ 38 | (QUEUE_NEXT(q)) 39 | 40 | #define QUEUE_INIT(q) \ 41 | do { \ 42 | QUEUE_NEXT(q) = (q); \ 43 | QUEUE_PREV(q) = (q); \ 44 | } \ 45 | while (0) 46 | 47 | #define QUEUE_ADD(h, n) \ 48 | do { \ 49 | QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \ 50 | QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \ 51 | QUEUE_PREV(h) = QUEUE_PREV(n); \ 52 | QUEUE_PREV_NEXT(h) = (h); \ 53 | } \ 54 | while (0) 55 | 56 | #define QUEUE_SPLIT(h, q, n) \ 57 | do { \ 58 | QUEUE_PREV(n) = QUEUE_PREV(h); \ 59 | QUEUE_PREV_NEXT(n) = (n); \ 60 | QUEUE_NEXT(n) = (q); \ 61 | QUEUE_PREV(h) = QUEUE_PREV(q); \ 62 | QUEUE_PREV_NEXT(h) = (h); \ 63 | QUEUE_PREV(q) = (n); \ 64 | } \ 65 | while (0) 66 | 67 | #define QUEUE_INSERT_HEAD(h, q) \ 68 | do { \ 69 | QUEUE_NEXT(q) = QUEUE_NEXT(h); \ 70 | QUEUE_PREV(q) = (h); \ 71 | QUEUE_NEXT_PREV(q) = (q); \ 72 | QUEUE_NEXT(h) = (q); \ 73 | } \ 74 | while (0) 75 | 76 | #define QUEUE_INSERT_TAIL(h, q) \ 77 | do { \ 78 | QUEUE_NEXT(q) = (h); \ 79 | QUEUE_PREV(q) = QUEUE_PREV(h); \ 80 | QUEUE_PREV_NEXT(q) = (q); \ 81 | QUEUE_PREV(h) = (q); \ 82 | } \ 83 | while (0) 84 | 85 | #define QUEUE_REMOVE(q) \ 86 | do { \ 87 | QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \ 88 | QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \ 89 | } \ 90 | while (0) 91 | 92 | #endif /* QUEUE_H_ */ 93 | -------------------------------------------------------------------------------- /shell/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS = -luv 2 | 3 | all: 4 | $(CC) -o uv_shell.o uv_shell.c $(LDFLAGS) 5 | -------------------------------------------------------------------------------- /shell/test2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bodokaiser/libuv-snippets/c22bc6f30ec765cb91b9628cc505a12f765f031d/shell/test2 -------------------------------------------------------------------------------- /shell/uv_shell.c: -------------------------------------------------------------------------------- 1 | #include "uv_shell.h" 2 | 3 | uv_loop_t* loop; 4 | 5 | uv_fs_t request; 6 | 7 | int main(int argc, const char ** argv) { 8 | loop = uv_default_loop(); 9 | 10 | if (!strcmp(argv[1], "mv")) { 11 | uv_shell_mv(argv[2], argv[3]); 12 | } 13 | 14 | uv_run(loop, UV_RUN_DEFAULT); 15 | 16 | return 0; 17 | } 18 | 19 | void print_last_error() { 20 | fprintf(stderr, "Error occured: %s.\n", 21 | uv_strerror(uv_last_error(loop))); 22 | } 23 | 24 | void uv_shell_mv(const char * old_path, const char * new_path) { 25 | int r = uv_fs_rename(loop, &request, old_path, new_path, NULL); 26 | 27 | if (r) print_last_error(); 28 | 29 | uv_fs_req_cleanup(&request); 30 | }; 31 | -------------------------------------------------------------------------------- /shell/uv_shell.h: -------------------------------------------------------------------------------- 1 | #ifndef UV_SHELL_H 2 | #define UV_SHELL_H 3 | 4 | #include "uv.h" 5 | #include "stdio.h" 6 | 7 | void print_last_error(); 8 | 9 | void uv_shell_mv(const char * old_path, const char * new_path); 10 | 11 | void uv_shell_rm(const char * path); 12 | 13 | void uv_shell_mkdir(const char * path); 14 | 15 | void uv_shell_rmdir(const char * path); 16 | 17 | void uv_shell_chown(const char * path, int uid, int gid); 18 | 19 | void uv_shell_chmod(const char * path, int mode); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /streams/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS = -luv 2 | 3 | all: 4 | $(CC) -o main.o main.c $(LDFLAGS) 5 | -------------------------------------------------------------------------------- /streams/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | uv_loop_t* loop; 5 | 6 | int main() { 7 | loop = uv_default_loop(); 8 | 9 | uv_stream_t* stream = malloc(uv_stream_t); 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /tcp-echo-server/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS = -luv 2 | 3 | build: tcp_echo_server 4 | 5 | clean: 6 | rm -Rf *.o 7 | 8 | tcp_echo_server: 9 | $(CC) -o tcp_echo_server.o tcp_echo_server.c $(LDFLAGS) 10 | -------------------------------------------------------------------------------- /tcp-echo-server/tcp_echo_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * Our tcp server object. 7 | */ 8 | uv_tcp_t server; 9 | 10 | /** 11 | * Shared reference to our event loop. 12 | */ 13 | uv_loop_t * loop; 14 | 15 | /** 16 | * Function declarations. 17 | */ 18 | uv_buf_t alloc_buffer(uv_handle_t * handle, size_t size); 19 | void connection_cb(uv_stream_t * server, int status); 20 | void read_cb(uv_stream_t * stream, ssize_t nread, uv_buf_t buf); 21 | 22 | int main() { 23 | loop = uv_default_loop(); 24 | 25 | /* convert a humanreadable ip address to a c struct */ 26 | struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", 3000); 27 | 28 | /* initialize the server */ 29 | uv_tcp_init(loop, &server); 30 | /* bind the server to the address above */ 31 | uv_tcp_bind(&server, addr); 32 | 33 | /* let the server listen on the address for new connections */ 34 | int r = uv_listen((uv_stream_t *) &server, 128, connection_cb); 35 | 36 | if (r) { 37 | return fprintf(stderr, "Error on listening: %s.\n", 38 | uv_strerror(uv_last_error(loop))); 39 | } 40 | 41 | /* execute all tasks in queue */ 42 | return uv_run(loop, UV_RUN_DEFAULT); 43 | } 44 | 45 | /** 46 | * Callback which is executed on each new connection. 47 | */ 48 | void connection_cb(uv_stream_t * server, int status) { 49 | /* dynamically allocate a new client stream object on conn */ 50 | uv_tcp_t * client = malloc(sizeof(uv_tcp_t)); 51 | 52 | /* if status not zero there was an error */ 53 | if (status == -1) { 54 | fprintf(stderr, "Error on listening: %s.\n", 55 | uv_strerror(uv_last_error(loop))); 56 | } 57 | 58 | /* initialize the new client */ 59 | uv_tcp_init(loop, client); 60 | 61 | /* now let bind the client to the server to be used for incomings */ 62 | if (uv_accept(server, (uv_stream_t *) client) == 0) { 63 | /* start reading from stream */ 64 | int r = uv_read_start((uv_stream_t *) client, alloc_buffer, read_cb); 65 | 66 | if (r) { 67 | fprintf(stderr, "Error on reading client stream: %s.\n", 68 | uv_strerror(uv_last_error(loop))); 69 | } 70 | } else { 71 | /* close client stream on error */ 72 | uv_close((uv_handle_t *) client, NULL); 73 | } 74 | } 75 | 76 | /** 77 | * Callback which is executed on each readable state. 78 | */ 79 | void read_cb(uv_stream_t * stream, ssize_t nread, uv_buf_t buf) { 80 | /* dynamically allocate memory for a new write task */ 81 | uv_write_t * req = (uv_write_t *) malloc(sizeof(uv_write_t)); 82 | 83 | /* if read bytes counter -1 there is an error or EOF */ 84 | if (nread == -1) { 85 | if (uv_last_error(loop).code != UV_EOF) { 86 | fprintf(stderr, "Error on reading client stream: %s.\n", 87 | uv_strerror(uv_last_error(loop))); 88 | } 89 | 90 | uv_close((uv_handle_t *) stream, NULL); 91 | } 92 | 93 | /* write sync the incoming buffer to the socket */ 94 | int r = uv_write(req, stream, &buf, 1, NULL); 95 | 96 | if (r) { 97 | fprintf(stderr, "Error on writing client stream: %s.\n", 98 | uv_strerror(uv_last_error(loop))); 99 | } 100 | 101 | /* free the remaining memory */ 102 | free(buf.base); 103 | } 104 | 105 | /** 106 | * Allocates a buffer which we can use for reading. 107 | */ 108 | uv_buf_t alloc_buffer(uv_handle_t * handle, size_t size) { 109 | return uv_buf_init((char *) malloc(size), size); 110 | } 111 | -------------------------------------------------------------------------------- /uvcat/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS=-luv 2 | 3 | build: 4 | $(CC) -o uvcat.o uvcat.c $(LDFLAGS) 5 | 6 | clean: 7 | rm ./uvcat.o 8 | -------------------------------------------------------------------------------- /uvcat/uvcat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Reference to our event loop. 6 | */ 7 | uv_loop_t * loop; 8 | 9 | /** 10 | * Work requests for fs actions. 11 | */ 12 | uv_fs_t open_req; 13 | uv_fs_t read_req; 14 | uv_fs_t close_req; 15 | 16 | /** 17 | * Buffer we use to read. 18 | */ 19 | char buf[0xffff]; 20 | 21 | /** 22 | * Function heads. 23 | */ 24 | void open_cb(uv_fs_t * req); 25 | void read_cb(uv_fs_t * req); 26 | void close_cb(uv_fs_t * req); 27 | 28 | /** 29 | * Execution entrance point. 30 | * Gets passed arguments from console in argv array. 31 | */ 32 | int main(int argc, const char ** argv) { 33 | /* request our event loop */ 34 | loop = uv_default_loop(); 35 | 36 | /* return if user did not pass any filename */ 37 | if (!argv[1]) { 38 | printf("Please pass a filename as argument.\n"); 39 | 40 | return 1; 41 | } 42 | 43 | /* open file as user in read-only mode */ 44 | int r = uv_fs_open(loop, &open_req, argv[1], 45 | O_RDONLY, S_IRUSR, open_cb); 46 | 47 | /* handle error */ 48 | if (r) { 49 | fprintf(stderr, "Error on opening file: %s\n.", 50 | uv_strerror(uv_last_error(loop))); 51 | } 52 | 53 | /* start executing all queued tasks */ 54 | return uv_run(loop, UV_RUN_DEFAULT); 55 | } 56 | 57 | /** 58 | * Callback executed when file is opened. 59 | */ 60 | void open_cb(uv_fs_t * req) { 61 | int result = req->result; 62 | 63 | if (result == -1) { 64 | fprintf(stderr, "Error on opening file: %s\n.", 65 | uv_strerror(uv_last_error(loop))); 66 | } 67 | 68 | /* free memory of our request */ 69 | uv_fs_req_cleanup(req); 70 | 71 | /* read as much from the file as our buffer can handle */ 72 | int r = uv_fs_read(loop, &read_req, result, buf, 73 | sizeof(buf), -1, read_cb); 74 | 75 | if (r) { 76 | fprintf(stderr, "Error on reading file: %s\n.", 77 | uv_strerror(uv_last_error(loop))); 78 | } 79 | } 80 | 81 | /** 82 | * Callback executed when read file. 83 | */ 84 | void read_cb(uv_fs_t * req) { 85 | int result = req->result; 86 | 87 | if (result == -1) { 88 | fprintf(stderr, "Error on reading file: %s\n.", 89 | uv_strerror(uv_last_error(loop))); 90 | } 91 | 92 | uv_fs_req_cleanup(req); 93 | 94 | /* now close the file properly */ 95 | int r = uv_fs_close(loop, &close_req, open_req.result, close_cb); 96 | 97 | if (result == -1) { 98 | fprintf(stderr, "Error on closing file: %s\n.", 99 | uv_strerror(uv_last_error(loop))); 100 | } 101 | } 102 | 103 | /** 104 | * Callback executed when file was closed. 105 | */ 106 | void close_cb(uv_fs_t * req) { 107 | int result = req->result; 108 | 109 | if (result == -1) { 110 | fprintf(stderr, "Error on closing file: %s\n.", 111 | uv_strerror(uv_last_error(loop))); 112 | } 113 | 114 | uv_fs_req_cleanup(req); 115 | 116 | /* output read data to console */ 117 | printf("%s\n", buf); 118 | } 119 | -------------------------------------------------------------------------------- /uvtee/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS = -luv 2 | 3 | all: 4 | $(CC) -o main.o main.c $(LDFLAGS) 5 | -------------------------------------------------------------------------------- /uvtee/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* create a write_request type which contains a buffer and a write request */ 9 | typedef struct { 10 | uv_buf_t buffer; 11 | uv_write_t request; 12 | } write_req_t; 13 | 14 | /* define shared variables */ 15 | uv_loop_t *loop; /* ? why double use ? */ 16 | uv_pipe_t file_pipe; 17 | uv_pipe_t stdin_pipe; 18 | uv_pipe_t stdout_pipe; 19 | 20 | /* function declarations */ 21 | uv_buf_t alloc_buffer(uv_handle_t *handle, size_t size); 22 | void read_stdin(uv_stream_t *stream, ssize_t nread, uv_buf_t buffer); 23 | void write_data(uv_stream_t *stream, size_t size, uv_buf_t buffer, uv_write_cb callback); 24 | void on_file_write(uv_write_t *request, int status); 25 | void on_stdout_write(uv_write_t *request, int status); 26 | void free_write_request(uv_write_t *request); 27 | 28 | int main(int argc, char ** argv) { 29 | /* contains the uv file discriptor */ 30 | int file_discriptor; 31 | /* contians the file request */ 32 | uv_fs_t file_request; 33 | /* contains pointer to default loop */ 34 | uv_loop_t* loop = uv_default_loop(); 35 | 36 | /* where does stdin_pipe come from ? */ 37 | 38 | /* adds input pipe to loop */ 39 | uv_pipe_init(loop, &stdin_pipe, 0); 40 | /* opens input pipe */ 41 | uv_pipe_open(&stdin_pipe, 0); 42 | 43 | /* adds stdoutput pipe to loop */ 44 | uv_pipe_init(loop, &stdout_pipe, 0); 45 | /* opens stdoutput pipe */ 46 | uv_pipe_open(&stdout_pipe, 1); 47 | 48 | /* add open file task to loop with the shown parameters (is executed syncronously ?) */ 49 | file_discriptor = uv_fs_open(loop, &file_request, argv[1], O_CREAT | O_RDWR, 0644, NULL); 50 | 51 | /* add fileoutput pipe to loop */ 52 | uv_pipe_init(loop, &file_pipe, 0); 53 | /* open fileoutput pipe */ 54 | uv_pipe_open(&file_pipe, file_discriptor); 55 | 56 | /* start begining to read incoming data of stdin. */ 57 | /* save the incoming to a manuelly allocated buffer and call the read_stdin callback on each income */ 58 | uv_read_start((uv_stream_t*) &stdin_pipe, alloc_buffer, read_stdin); 59 | 60 | /* start the loop */ 61 | uv_run(loop, UV_RUN_DEFAULT); 62 | 63 | return 0; 64 | } 65 | 66 | /* returns a buffer instance for storing incoming stdin lines */ 67 | uv_buf_t alloc_buffer(uv_handle_t *handle, size_t size) { 68 | return uv_buf_init((char *) malloc(size), size); 69 | } 70 | 71 | /* is executed as callback on each incoming stdinput */ 72 | void read_stdin(uv_stream_t *stream, ssize_t nread, uv_buf_t buffer) { 73 | /* *stream pointer to current stream (stdin_pipe) ? */ 74 | /* nread is the size of data */ 75 | /* buffer stores the actuall data (instance from alloc_buffer?) */ 76 | 77 | /* if size is -1 close everything */ 78 | if (nread == -1) { 79 | if (uv_last_error(loop).code == UV_EOF) { 80 | uv_close((uv_handle_t*) &file_pipe, NULL); 81 | uv_close((uv_handle_t*) &stdin_pipe, NULL); 82 | uv_close((uv_handle_t*) &stdout_pipe, NULL); 83 | } 84 | } else { 85 | /* write stdin input to stdout_pipe and file_pipe with size, buffer and freeing callback */ 86 | if (nread > 0) { 87 | write_data((uv_stream_t*) &stdout_pipe, nread, buffer, on_stdout_write); 88 | write_data((uv_stream_t*) &file_pipe, nread, buffer, on_file_write); 89 | } 90 | } 91 | 92 | /* free the buffer */ 93 | if (buffer.base) 94 | free(buffer.base); 95 | 96 | } 97 | 98 | /* writes the data to some streams */ 99 | void write_data(uv_stream_t *stream, size_t size, uv_buf_t buffer, uv_write_cb callback) { 100 | /* create a write request struct */ 101 | write_req_t *request = (write_req_t*) malloc(sizeof(write_req_t)); 102 | /* initialize new buffer for write request */ 103 | request->buffer = uv_buf_init((char*) malloc(size), size); 104 | /* copy whole passed buffer to write request (why?) */ 105 | memcpy(request->buffer.base, buffer.base, size); 106 | /* use uv_write to write something to streams */ 107 | uv_write((uv_write_t*) request, (uv_stream_t*) stream, &request->buffer, 1, callback); 108 | } 109 | 110 | /* frees file write request */ 111 | void on_file_write(uv_write_t *request, int status) { 112 | free_write_request(request); 113 | } 114 | 115 | /* frees stdout write request */ 116 | void on_stdout_write(uv_write_t *request, int status) { 117 | free_write_request(request); 118 | } 119 | 120 | /* implementation of freeing algorithm */ 121 | void free_write_request(uv_write_t *request) { 122 | /* create a pointer to a pointer ?? WHY? */ 123 | write_req_t *write_request = (write_req_t*) request; 124 | /* free structs */ 125 | free(write_request->buffer.base); 126 | free(write_request); 127 | } 128 | --------------------------------------------------------------------------------