This repository has been archived on 2026-07-28. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cmc/3sem/templates.c
T
2025-04-13 21:48:15 +03:00

172 lines
5.9 KiB
C
Executable File

/**
* @file templates.c
* @brief This file contains various template functions and includes necessary headers for file operations, memory
* management, mathematical computations, and system calls.
*
* The following libraries are included:
* - stdio.h: Provides functionalities for file operations such as fopen, fclose, fprintf, fscanf, printf, and scanf.
* - stdlib.h: Provides functionalities for memory management, conversions, and other utility functions such as exit,
* malloc, free, atoi, strtol, strtoul, atof, strtod, abs, labs, llabs, div, ldiv, and lldiv.
* - fcntl.h: Provides file control options such as O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND,
* O_NONBLOCK, O_SYNC, O_DSYNC, O_RSYNC, O_FSYNC, O_ASYNC, O_CLOEXEC, O_DIRECTORY, O_NOFOLLOW, O_NOCTTY, O_TMPFILE,
* O_DIRECT, O_LARGEFILE, O_NOATIME, O_PATH, and O_NDELAY.
* - unistd.h: Provides access to the POSIX operating system API.
* - sys/file.h: Provides file control options.
* - sys/types.h: Defines data types used in system calls such as mode_t, off_t, pid_t, uid_t, gid_t, dev_t, ino_t,
* nlink_t, blksize_t, blkcnt_t, fsblkcnt_t, and fsfilcnt_t.
* - sys/stat.h: Defines the structure of the data returned by the functions fstat(), lstat(), and stat().
* - limits.h: Defines the sizes of basic types.
* - errno.h: Defines macros for reporting and retrieving error conditions through error codes.
* - stdint.h: Provides a set of typedefs that specify exact-width integer types.
* - math.h: Provides mathematical functions.
* - dirent.h: Defines the format of directory entries.
* - string.h: Provides string handling functions.
*
* The following functions are implemented:
* - void safe_read(int fd, void *buf, size_t count): Reads data from a file descriptor safely, handling interruptions
* and errors.
* - void safe_write(int fd, void *buf, size_t count): Writes data to a file descriptor safely, handling interruptions
* and errors.
* - void str_to_ll(char *str, long long *num): Converts a string to a long long integer, handling errors.
* - void endian_swap(void *src, void *dst, size_t size): Swaps the endianness of a block of memory.
*
* The main function:
* - int main(int argc, char *argv[]): Template main function that checks the number of arguments, opens input and
* output files, and closes them.
*/
#include <stdio.h> // Standard I/O functions
#include <stdlib.h> // Standard library functions: memory allocation, process control, conversions, etc.
#include <fcntl.h> // File control options
#include <unistd.h> // POSIX API: read, write, close, etc.
#include <sys/file.h> // File control options
#include <sys/types.h> // Data types used in system calls
#include <sys/stat.h> // Data returned by the functions fstat(), lstat(), and stat()
#include <limits.h> // Sizes of basic types
#include <errno.h> // Error reporting macros
#include <stdint.h> // Exact-width integer types
#include <math.h> // Mathematical functions
#include <dirent.h> // Directory entry format
#include <string.h> // String handling functions
#include <sys/stat.h> // Data returned by the functions fstat(), lstat(), and stat()
// Function declarations
int safe_read(int fd, void *buf, size_t count); // Reads data from a file descriptor safely
int safe_write(int fd, void *buf, size_t count); // Writes data to a file descriptor safely
void str_to_ll(char *str, long long *num); // Converts a string to a long long integer
void endian_swap(void *src, void *dst, size_t size); // Swaps the endianness of a block of memory
int
safe_read(int fd, void *buf, size_t count)
{
errno = 0;
size_t bytes_read = 0;
while (bytes_read < count) {
ssize_t res = read(fd, buf + bytes_read, count - bytes_read);
if (res < 0) {
if (errno == EINTR) {
errno = 0;
continue;
}
fprintf(stderr, "Error reading from file descriptor %d\n", fd);
close(fd);
exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок
}
if (res == 0) {
break;
}
bytes_read += res;
}
return bytes_read;
}
int
safe_write(int fd, void *buf, size_t count)
{
errno = 0;
size_t bytes_written = 0;
while (bytes_written < count) {
ssize_t res = write(fd, buf + bytes_written, count - bytes_written);
if (res < 0) {
if (errno == EINTR) {
errno = 0;
continue;
}
fprintf(stderr, "Error writing to file descriptor %d\n", fd);
close(fd);
exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок
}
bytes_written += res;
}
return bytes_written;
}
void
str_to_ll(char *str, long long *num)
{
errno = 0;
char *endptr;
*num = strtoll(str, &endptr, 10);
if (*endptr || errno || endptr == str) {
fprintf(stderr, "Invalid number: %s\n", str);
exit(1); // TODO: по-хорошему заменить на внешний обработчик ошибок
}
return;
}
void
endian_swap(void *src, void *dst, size_t size)
{
for (size_t i = 0; i < size; i++) {
((char *) dst)[i] = ((char *) src)[size - i - 1];
}
return;
}
// template main function
enum
{
ARGS_NUM = 4,
};
int
main(int argc, char *argv[])
{
if (argc != ARGS_NUM) {
fprintf(stderr, "Wrong number of arguments\n");
return 1;
}
int fdin = open(argv[1], O_RDONLY);
if (fdin == -1) {
fprintf(stderr, "Error opening file %s\n", argv[1]);
return 1;
}
int fdout = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fdout == -1) {
fprintf(stderr, "Error opening file %s\n", argv[2]);
close(fdin);
return 1;
}
close(fdin);
close(fdout);
return 0;
}