mirror of
https://github.com/peter-tanner/CITS-3007-labs.git
synced 2024-11-30 09:00:19 +08:00
88 lines
3.2 KiB
C
88 lines
3.2 KiB
C
// gcc make_pathname.c -pedantic -Wall -Wextra -Wconversion -fsanitize=undefined,address -g -O0
|
|
|
|
// You can assume the following headers have already been included: stdio.h,
|
|
// stdlib.h, limits.h, ctype.h, stdbool.h, stdint.h, and string.h.
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include <ctype.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#define SLASH_LEN 1
|
|
#define DOT_LEN 1
|
|
#define NULL_LEN 1
|
|
#define SUM_LEN (SLASH_LEN + DOT_LEN + NULL_LEN)
|
|
|
|
void fill_buffer(
|
|
const char *dir, size_t dirlen, const char *fname, size_t filelen,
|
|
const char *ext, size_t extlen, char *path)
|
|
{
|
|
memcpy(path, dir, dirlen);
|
|
path[dirlen] = '/';
|
|
memcpy(path + dirlen + SLASH_LEN, fname, filelen);
|
|
path[dirlen + SLASH_LEN + filelen] = '.';
|
|
memcpy(path + dirlen + SLASH_LEN + filelen + DOT_LEN, ext, extlen);
|
|
path[dirlen + SLASH_LEN + filelen + DOT_LEN + extlen] = '\0';
|
|
}
|
|
|
|
/** Return true when the sum of dirlen, filelen, extlen and 3
|
|
* would exceed the maximum possible value of a size_t; otherwise,
|
|
* return false.
|
|
*/
|
|
bool would_wrap_around(size_t dirlen, size_t filelen, size_t extlen)
|
|
{
|
|
return (SUM_LEN + dirlen + filelen < filelen //
|
|
|| SUM_LEN + dirlen + filelen < dirlen //
|
|
|| SUM_LEN + filelen + extlen < extlen //
|
|
|| SUM_LEN + filelen + extlen < filelen //
|
|
|| SUM_LEN + dirlen + extlen < dirlen //
|
|
|| SUM_LEN + dirlen + extlen < extlen //
|
|
|| SUM_LEN + dirlen + extlen + filelen < dirlen //
|
|
|| SUM_LEN + dirlen + extlen + filelen < filelen //
|
|
|| SUM_LEN + dirlen + extlen + filelen < extlen //
|
|
);
|
|
}
|
|
|
|
// Concatenates dir, fname and ext, with a forward slash ('/') between dir and
|
|
// fname and a full stop ('.') between fname and ext.
|
|
//
|
|
// The return value is normally a pointer to dynamically allocated memory
|
|
// containing this concatenated string, which should be freed by the caller
|
|
// after use.
|
|
//
|
|
// If, however, the system cannot allocate sufficient memory to hold the
|
|
// resulting string, then a NULL pointer is returned.
|
|
//
|
|
// Each of dir, fname and ext must be valid null-terminated strings;
|
|
// furthermore, the fname and ext parameters must not contain any forward-slash
|
|
// or full stop characters. If any of these conditions do not hold, the result
|
|
// of calling the function is undefined.
|
|
char *make_pathname(const char *dir, const char *fname, const char *ext)
|
|
{
|
|
size_t dirlen = strlen(dir);
|
|
size_t filelen = strlen(fname);
|
|
size_t extlen = strlen(ext);
|
|
if (would_wrap_around(dirlen, filelen, extlen))
|
|
return NULL;
|
|
char *path = malloc(dirlen + SLASH_LEN + filelen + DOT_LEN + extlen + NULL_LEN);
|
|
if (path == NULL)
|
|
return NULL; // malloc() failed. Do not continue.
|
|
fill_buffer(dir, dirlen, fname, filelen, ext, extlen, path);
|
|
return path;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
char *c = make_pathname("ddddddddddddd", "ff", "xx");
|
|
printf("%s", c);
|
|
free(c);
|
|
|
|
// TEST WRAP CHECK
|
|
// size_t dirlen = 18446744073709551595UL;
|
|
// size_t filelen = 9;
|
|
// size_t extlen = 16;
|
|
// bool res = would_wrap_around(dirlen, filelen, extlen);
|
|
// printf("%d\n", res);
|
|
} |