This commit is contained in:
Simon From Jakobsen 2024-07-16 10:52:13 +00:00
commit eae18257d7
5 changed files with 171 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
target/
build/

16
CMakeLists.txt Normal file
View File

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.29)
project(path-shortener VERSION 0.0.0 LANGUAGES C)
add_executable(shortpath main.c)
install(TARGETS shortpath)
set(CPACK_PACKAGE_NAME path-shortener)
set(CPACK_PACKAGE_VENDOR simon)
set(CPACK_PACKAGE_DESCRIPTION "CWD path but short")
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
set(CPACK_VERBATIM_VARIABLES TRUE)
include(CPack)

10
build_debug.sh Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
set -xe
cmake . -B target/debug -DCMAKE_BUILD_TYPE=Debug
cmake --build target/debug

16
build_release.sh Normal file
View File

@ -0,0 +1,16 @@
#!/bin/bash
set -xe
cmake . -B target/release -DCMAKE_BUILD_TYPE=Release
cmake --build target/release
cd target/release
cpack -G "TGZ"
cd ../..

126
main.c Normal file
View File

@ -0,0 +1,126 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#define MAX_PATH_SIZE 512
#define SEGMENT_LENGTH 2
#define LAST_SEGMENT_MAX_LENGTH 16
#define MAX_SEGMENTS_AMOUNT 64
typedef struct {
size_t seperator;
size_t length;
} Segment;
/// @returns Amount of segments
size_t get_path_segments(
Segment* dest,
size_t dest_size,
const char* path,
size_t path_length)
{
size_t dest_i = 0;
size_t i = 0;
while (i < path_length) {
size_t seperator = i;
i += 1;
while (path[i] != '\0' && path[i] != '/') {
i += 1;
}
size_t length = i - seperator - 1;
dest[dest_i] = (Segment) { seperator, length };
dest_i += 1;
}
return dest_i;
}
bool in_home_directory(
const char* path,
const Segment* segments,
size_t segments_length,
const char* username)
{
if (segments_length < 2)
return false;
if (strncmp(&path[segments[0].seperator + 1], "home", segments[0].length) != 0) {
return false;
}
if (strncmp(&path[segments[1].seperator + 1], username, strlen(username)) != 0) {
return false;
}
return true;
}
int main(void)
{
char cwd_path[MAX_PATH_SIZE] = "";
if (getcwd(cwd_path, sizeof(cwd_path)) == NULL) {
fprintf(stderr, "error: failed to get current working directory: %s\n", strerror(errno));
exit(1);
}
const size_t cwd_path_length = strlen(cwd_path);
const char* username = getlogin();
Segment segments[MAX_SEGMENTS_AMOUNT] = { 0 };
size_t segments_length = get_path_segments(
segments,
sizeof(segments) / sizeof(segments[0]),
cwd_path,
cwd_path_length);
bool in_home_dir = in_home_directory(cwd_path, segments, segments_length, username);
char short_path[MAX_PATH_SIZE] = "";
size_t segments_i = 0;
size_t dest_i = 0;
if (in_home_dir) {
short_path[dest_i] = '~';
dest_i += 1;
segments_i += 2;
}
for (; segments_i < segments_length - 1; segments_i += 1) {
short_path[dest_i] = '/';
dest_i += 1;
Segment* segment = &segments[segments_i];
for (size_t i = 0; i < segment->length && i < SEGMENT_LENGTH; i += 1) {
short_path[dest_i] = cwd_path[segment->seperator + 1 + i];
dest_i += 1;
}
}
if (!(segments_length == 2 && in_home_dir)) {
short_path[dest_i] = '/';
dest_i += 1;
Segment* last = &segments[segments_i];
if (last->length >= LAST_SEGMENT_MAX_LENGTH) {
for (size_t i = 0; i < 5; i += 1) {
short_path[dest_i] = cwd_path[last->seperator + 1 + i];
dest_i += 1;
}
for (size_t i = 0; i < 3; i += 1) {
short_path[dest_i] = '.';
dest_i += 1;
}
for (size_t i = 0; i < 8; i += 1) {
short_path[dest_i] = cwd_path[last->seperator + 1 + last->length - 8 + i];
dest_i += 1;
}
} else {
for (size_t i = 0; i < last->length; i += 1) {
short_path[dest_i] = cwd_path[last->seperator + 1 + i];
dest_i += 1;
}
}
}
short_path[dest_i] = '\0';
fputs(short_path, stdout);
}