176 lines
5.8 KiB
C
176 lines
5.8 KiB
C
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "config.h"
|
|
|
|
// Current working directory
|
|
char current_directory[MAX_PATH] = {0};
|
|
|
|
// Initialize the current directory
|
|
void InitializeDirectory() {
|
|
GetCurrentDirectoryA(MAX_PATH, current_directory);
|
|
}
|
|
|
|
// Normalize path with proper backslashes
|
|
void NormalizePath(char* path) {
|
|
size_t path_len = strlen(path);
|
|
|
|
// Replace forward slashes with backslashes
|
|
for (size_t i = 0; i < path_len; i++) {
|
|
if (path[i] == '/') {
|
|
path[i] = '\\';
|
|
}
|
|
}
|
|
|
|
// Remove trailing backslash if present (except for root paths like "C:\")
|
|
if (path_len > 3 && path[path_len - 1] == '\\') {
|
|
path[path_len - 1] = '\0';
|
|
}
|
|
}
|
|
|
|
// Check if directory exists
|
|
int DirectoryExists(const char* path) {
|
|
DWORD attributes = GetFileAttributesA(path);
|
|
return (attributes != INVALID_FILE_ATTRIBUTES &&
|
|
(attributes & FILE_ATTRIBUTE_DIRECTORY));
|
|
}
|
|
|
|
// Change directory function
|
|
int ChangeDirectory(const char* path) {
|
|
char target_path[MAX_PATH] = {0};
|
|
|
|
// Handle "../" - needs special handling to remove trailing "/.."
|
|
if (strcmp(path, "..") == 0 || strcmp(path, "../") == 0) {
|
|
// Copy current path to work with
|
|
strncpy(target_path, current_directory, MAX_PATH - 1);
|
|
|
|
// Find the last backslash
|
|
char* last_backslash = strrchr(target_path, '\\');
|
|
|
|
// Don't go up from drive root (e.g., C:\)
|
|
if (last_backslash > target_path + 2) {
|
|
*last_backslash = '\0'; // Remove last directory component
|
|
} else {
|
|
// Keep drive letter root (e.g., "C:\")
|
|
*(last_backslash + 1) = '\0';
|
|
}
|
|
}
|
|
// Handle absolute path
|
|
else if (strlen(path) >= 2 && path[1] == ':') {
|
|
strncpy(target_path, path, MAX_PATH - 1);
|
|
NormalizePath(target_path);
|
|
}
|
|
// Handle current directory
|
|
else if (strcmp(path, ".") == 0 || strlen(path) == 0) {
|
|
return 1; // No change needed
|
|
}
|
|
// Handle relative path
|
|
else {
|
|
size_t current_len = strlen(current_directory);
|
|
if (current_directory[current_len - 1] == '\\') {
|
|
snprintf(target_path, MAX_PATH, "%s%s", current_directory, path);
|
|
} else {
|
|
snprintf(target_path, MAX_PATH, "%s\\%s", current_directory, path);
|
|
}
|
|
NormalizePath(target_path);
|
|
}
|
|
|
|
// Check if directory exists and is accessible
|
|
if (DirectoryExists(target_path)) {
|
|
strncpy(current_directory, target_path, MAX_PATH - 1);
|
|
return SetCurrentDirectoryA(target_path);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// List directory contents - without buffer size parameter
|
|
void ListDirectory(char result[]) {
|
|
char search_path[MAX_PATH];
|
|
WIN32_FIND_DATAA find_data;
|
|
char buffer[STANDARD_BUFF];
|
|
|
|
// Initialize result buffer as empty
|
|
result[0] = '\0';
|
|
size_t used_size = 0;
|
|
|
|
snprintf(search_path, sizeof(search_path), "%s\\*", current_directory);
|
|
HANDLE h_find = FindFirstFileA(search_path, &find_data);
|
|
|
|
if (h_find != INVALID_HANDLE_VALUE) {
|
|
// Add directory header
|
|
int header_len = snprintf(buffer, sizeof(buffer), "Directory listing for %s:\n", current_directory);
|
|
|
|
// Check if we have enough space in the result buffer
|
|
if (header_len < STANDARD_BUFF - used_size) {
|
|
strcat(result, buffer);
|
|
used_size += header_len;
|
|
} else {
|
|
strncpy(result, "Buffer too small", STANDARD_BUFF - 1);
|
|
result[STANDARD_BUFF - 1] = '\0';
|
|
FindClose(h_find);
|
|
return;
|
|
}
|
|
|
|
do {
|
|
int is_directory = (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
|
int line_len;
|
|
|
|
if (is_directory) {
|
|
line_len = snprintf(buffer, sizeof(buffer), "[DIR] %s\n", find_data.cFileName);
|
|
} else {
|
|
// Format with file size
|
|
ULONGLONG file_size = ((ULONGLONG)find_data.nFileSizeHigh << 32) + find_data.nFileSizeLow;
|
|
line_len = snprintf(buffer, sizeof(buffer), "%s (%llu bytes)\n", find_data.cFileName, file_size);
|
|
}
|
|
|
|
// Check if we have enough space for this line
|
|
if (used_size + line_len < STANDARD_BUFF) {
|
|
strcat(result, buffer);
|
|
used_size += line_len;
|
|
} else {
|
|
// Indicate truncation and break the loop
|
|
strcat(result, "\n[Directory listing truncated due to buffer size limitation]");
|
|
break;
|
|
}
|
|
|
|
} while (FindNextFileA(h_find, &find_data));
|
|
|
|
FindClose(h_find);
|
|
} else {
|
|
snprintf(result, STANDARD_BUFF, "Error accessing directory %s\n", current_directory);
|
|
}
|
|
}
|
|
|
|
// Get current directory - without buffer size parameter
|
|
void GetCurrentWorkingDir(char result[]) {
|
|
strncpy(result, current_directory, STANDARD_BUFF - 1);
|
|
result[STANDARD_BUFF - 1] = '\0';
|
|
}
|
|
|
|
// Main handler for directory commands - without buffer size parameter
|
|
void HandleDirectoryCommand(char result[], char* command, char* args) {
|
|
// Initialize directory if not done yet
|
|
if (strlen(current_directory) == 0) {
|
|
InitializeDirectory();
|
|
}
|
|
|
|
if (strcmp(command, "cd") == 0) {
|
|
if (ChangeDirectory(args)) {
|
|
snprintf(result, STANDARD_BUFF, "Changed directory to: %s", current_directory);
|
|
} else {
|
|
snprintf(result, STANDARD_BUFF, "Error: Could not change to directory: %s", args);
|
|
}
|
|
}
|
|
else if (strcmp(command, "pwd") == 0) {
|
|
GetCurrentWorkingDir(result);
|
|
}
|
|
else if (strcmp(command, "ls") == 0 || strcmp(command, "dir") == 0) {
|
|
ListDirectory(result);
|
|
}
|
|
else {
|
|
snprintf(result, STANDARD_BUFF, "Unknown directory command: %s", command);
|
|
}
|
|
} |