Skip to content

Instantly share code, notes, and snippets.

@teknoraver
Last active July 11, 2024 16:26
Show Gist options
  • Save teknoraver/81142422b9baa7d75e73275feef249db to your computer and use it in GitHub Desktop.
Save teknoraver/81142422b9baa7d75e73275feef249db to your computer and use it in GitHub Desktop.
C cleanups example
#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