File information
Gain knowledge of file system operations, such as navigating directories, creating and deleting files and directories, and modifying file permissions. Implement the necessary functionalities to handle these operations within your shell.
The stat (man 2 stat) system call gets the status of a file. On success, zero is returned. On error, -1 is returned.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/**
* main - stat example
*
* Return: Always 0.
*/
int main(int ac, char **av)
{
unsigned int i;
struct stat st;
if (ac < 2)
{
printf("Usage: %s path_to_file ...\n", av[0]);
return (1);
}
i = 1;
while (av[i])
{
printf("%s:", av[i]);
if (stat(av[i], &st) == 0)
{
printf(" FOUND\n");
}
else
{
printf(" NOT FOUND\n");
}
i++;
}
return (0);
}
Write a program that looks for files in the current PATH
.
Usage:
_which filename ...
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_PATH_LENGTH 1024 // Function to check if a file exists in a directory int fileExists(const char *filename, const char *directory) { char path[MAX_PATH_LENGTH]; snprintf(path, sizeof(path), "%s/%s", directory, filename); FILE *file = fopen(path, "r"); if (file != NULL) { fclose(file); return 1; // File exists } return 0; // File does not exist } int main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: %s filename ...\n", argv[0]); return 1; } char *path_env = getenv("PATH"); if (path_env == NULL) { printf("Unable to access PATH environment variable.\n"); return 1; } char *path = strtok(path_env, ":"); int found = 0; // Iterate through each directory in PATH while (path != NULL) { int i; for (i = 1; i < argc; i++) { if (fileExists(argv[i], path)) { printf("%s\n", path); found = 1; } } path = strtok(NULL, ":"); } if (!found) { printf("Files not found in the current PATH.\n"); } return 0; }
In this program:
The
fileExists
function checks if a file with the provided filename exists in the specified directory. It constructs the full file path by concatenating the directory and filename, and then attempts to open the file for reading. If the file can be opened, it means the file exists.In the
main
function, the program expects at least one command-line argument (in addition to the program name). If the argument count is less than 2, it displays the usage message and returns.The program uses the
getenv
function to retrieve the value of the PATH environment variable. It checks if the value is NULL and displays an error message if it is unable to access the PATH variable.The program tokenizes the PATH value using
strtok
with ":" as the delimiter to extract each directory path.For each directory in the PATH, the program checks if each provided filename exists in that directory using the
fileExists
function. If a file is found, the directory path is printed.Finally, if no files are found in the current PATH, a message is displayed to indicate that the files were not found.
You can compile and run the program, providing the filenames you want to search for in the current PATH as command-line arguments. For example:
$ ./program_name file1 file2
The program will search for the provided files in the directories specified by the PATH environment variable and print the directories where the files are found.
Environment
We have seen earlier that the shell uses an environment list, where environment variables are “stored”. The list is an array of strings, with the following format: var=value
, where var
is the name of the variable and value
its value. As a reminder, you can list the environment with the command printenv.
Actually, every process comes with an environment. When a new process is created, it inherits a copy of its parent’s environment. To access the entire environment within a process, you have several options:
via the
main
functionvia the global variable
environ
Print environment using environ
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
int main() {
char **env = environ;
while (*env != NULL) {
printf("%s\n", *env);
env++;
}
return 0;
}
Compare env and environ addresses
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
int main(int argc, char *argv[], char *env[]) {
printf("Address of env: %p\n", env);
printf("Address of environ: %p\n", environ);
return 0;
}
Implement _getenv function
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char **environ;
char *_getenv(const char *name) {
char **env = environ;
size_t name_len = strlen(name);
while (*env != NULL) {
if (strncmp(*env, name, name_len) == 0 && (*env)[name_len] == '=') {
return *env + name_len + 1;
}
env++;
}
return NULL;
}
int main() {
char *value = _getenv("PATH");
if (value != NULL) {
printf("Value of PATH: %s\n", value);
} else {
printf("PATH environment variable not found.\n");
}
return 0;
}
Print each directory in the PATH environment variable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char **environ;
void printPathDirectories() {
char *path = getenv("PATH");
if (path != NULL) {
char *dir = strtok(path, ":");
while (dir != NULL) {
printf("%s\n", dir);
dir = strtok(NULL, ":");
}
} else {
printf("PATH environment variable not found.\n");
}
}
int main() {
printPathDirectories();
return 0;
}
Build a linked list of directories in the PATH environment variable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char **environ;
typedef struct Node {
char *directory;
struct Node *next;
} Node;
Node *buildPathList() {
char *path = getenv("PATH");
if (path == NULL) {
printf("PATH environment variable not found.\n");
return NULL;
}
Node *head = NULL;
Node *prev = NULL;
char *dir = strtok(path, ":");
while (dir != NULL) {
Node *node = malloc(sizeof(Node));
if (node == NULL) {
printf("Memory allocation failed.\n");
break;
}
node->directory = strdup(dir);
node->next = NULL;
if (prev == NULL) {
head = node;
} else {
prev->next = node;
}
prev = node;
dir = strtok(NULL, ":");
}
return head;
}
void freePathList(Node *head) {
Node *curr = head;
while (curr != NULL) {
Node *next = curr->next;
free(curr->directory);
free(curr);
curr = next;
}
}
int main() {
Node *pathList = buildPathList();
if (pathList != NULL) {
Node *curr = pathList;
while (curr != NULL) {
printf("%s\n", curr->directory);
curr = curr->next;
}
freePathList(pathList);
}
return 0;
}
Implement _setenv function
cCopy code#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char **environ;
int _setenv(const char *name, const char *value, int overwrite) {
if (name == NULL || value == NULL) {
return -1; // Invalid arguments
}
size_t name_len = strlen(name);
size_t value_len = strlen(value);
char **env = environ;
while (*env != NULL) {
if (strncmp(*env, name, name_len) == 0 && (*env)[name_len] == '=') {
if (overwrite) {
// Overwrite existing value
size_t entry_len = name_len + value_len + 2;
char *entry = malloc(entry_len);
if (entry == NULL) {
return -1; // Memory allocation failed
}
snprintf(entry, entry_len, "%s=%s", name, value);
*env = entry;
return 0;
} else {
// Value exists, but overwrite is not allowed
return 0;
}
}
env++;
}
// Value does not exist, create a new entry
size_t entry_len = name_len + value_len + 2;
char *entry = malloc(entry_len);
if (entry == NULL) {
return -1; // Memory allocation failed
}
snprintf(entry, entry_len, "%s=%s", name, value);
// Count the number of existing environment variables
int env_count = 0;
env = environ;
while (*env != NULL) {
env_count++;
env++;
}
// Allocate memory for the new environment variable
char **new_env = realloc(environ, (env_count + 2) * sizeof(char *));
if (new_env == NULL) {
free(entry);
return -1; // Memory allocation failed
}
environ = new_env;
environ[env_count] = entry;
environ[env_count + 1] = NULL;
return 0;
}
int main() {
char *name = "MY_VAR";
char *value = "my_value";
_setenv(name, value, 1); // Overwrite is allowed
char *result = getenv(name);
if (result != NULL) {
printf("%s=%s\n", name, result);
} else {
printf("Environment variable not found.\n");
}
return 0;
}
Implement _unsetenv function
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char **environ;
int _unsetenv(const char *name) {
if (name == NULL) {
return -1; // Invalid argument
}
size_t name_len = strlen(name);
char **env = environ;
while (*env != NULL) {
if (strncmp(*env, name, name_len) == 0 && (*env)[name_len] == '=') {
// Shift the remaining environment variables to fill the gap
char **next = env + 1;
while (*next != NULL) {
*env = *next;
env = next;
next++;
}
*env = NULL; // Set the last entry to NULL
return 0;
}
env++;
}
return 0; // Variable not found, nothing to unset
}
int main() {
char *name = "MY_VAR";
_unsetenv(name);
char *result = getenv(name);
if (result != NULL) {
printf("%s=%s\n", name, result);
} else {
printf("Environment variable not found.\n");
}
return 0;
}