Last active
July 11, 2024 16:26
-
-
Save teknoraver/81142422b9baa7d75e73275feef249db to your computer and use it in GitHub Desktop.
C cleanups example
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 <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
#define BUFFER_SIZE 4096 | |
int copy(const char *src_path, const char *dst_path) | |
{ | |
int src, dst; | |
char *buffer; | |
int n; | |
buffer = malloc(BUFFER_SIZE); | |
if (!buffer) | |
return 1; | |
src = open(src_path, O_RDONLY); | |
if (src < 0) { | |
free(buffer); | |
return 2; | |
} | |
dst = open(dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
if (dst < 0) { | |
close(src); | |
free(buffer); | |
return 3; | |
} | |
while ((n = read(src, buffer, BUFFER_SIZE)) > 0) { | |
if (write(dst, buffer, n) != n) { | |
close(dst); | |
close(src); | |
free(buffer); | |
return 4; | |
} | |
} | |
if (n < 0) { | |
close(dst); | |
close(src); | |
free(buffer); | |
return 5; | |
} | |
close(dst); | |
close(src); | |
free(buffer); | |
return 0; | |
} | |
int copy_goto(const char *src_path, const char *dst_path) | |
{ | |
int src, dst; | |
char *buffer; | |
int ret = 0, n; | |
buffer = malloc(BUFFER_SIZE); | |
if (!buffer) { | |
ret = 1; | |
goto out; | |
} | |
src = open(src_path, O_RDONLY); | |
if (src < 0) { | |
ret = 2; | |
goto out_free; | |
} | |
dst = open(dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
if (dst < 0) { | |
ret = 3; | |
goto out_src; | |
} | |
while ((n = read(src, buffer, BUFFER_SIZE)) > 0) { | |
if (write(dst, buffer, n) != n) { | |
ret = 4; | |
goto out_dst; | |
} | |
} | |
if (n < 0) { | |
ret = 5; | |
goto out_dst; | |
} | |
out_dst: | |
close(dst); | |
out_src: | |
close(src); | |
out_free: | |
free(buffer); | |
out: | |
return ret; | |
} | |
#define _cleanup_(x) __attribute__((__cleanup__(x))) | |
#define _cleanup_close_ _cleanup_(closep) | |
#define _cleanup_free_ _cleanup_(freep) | |
static inline void closep(int *fd) | |
{ | |
if (*fd >= 0) | |
close(*fd); | |
} | |
static inline void freep(void *p) | |
{ | |
free(*(void **)p); | |
} | |
int copy_cleanups(const char *src_path, const char *dst_path) | |
{ | |
_cleanup_close_ int src = -EBADF, dst = -EBADF; | |
_cleanup_free_ char *buffer = NULL; | |
int n; | |
buffer = malloc(BUFFER_SIZE); | |
if (!buffer) | |
return 1; | |
src = open(src_path, O_RDONLY); | |
if (src < 0) | |
return 2; | |
dst = open(dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
if (dst < 0) | |
return 3; | |
while ((n = read(src, buffer, BUFFER_SIZE)) > 0) { | |
if (write(dst, buffer, n) != n) | |
return 4; | |
} | |
if (n < 0) | |
return 5; | |
return 0; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
if (argc != 3) { | |
fprintf(stderr, "Usage: %s <source> <destination>\n", argv[0]); | |
return 1; | |
} | |
copy(argv[1], argv[2]); | |
copy_goto(argv[1], argv[2]); | |
copy_cleanups(argv[1], argv[2]); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment