├── 0x00-c_dynamic_libraries ├── 1-create_dynamic_lib.sh ├── 100-operations.so ├── 101-make_me_win.sh ├── README.md ├── holberton.h ├── libholberton.so └── src │ ├── 0-main.c │ ├── _abs.c │ ├── _atoi.c │ ├── _isalpha.c │ ├── _isdigit.c │ ├── _islower.c │ ├── _isupper.c │ ├── _memcpy.c │ ├── _memset.c │ ├── _putchar.c │ ├── _puts.c │ ├── _strcat.c │ ├── _strchr.c │ ├── _strcmp.c │ ├── _strcpy.c │ ├── _strlen.c │ ├── _strncat.c │ ├── _strncpy.c │ ├── _strpbrk.c │ ├── _strspn.c │ ├── _strstr.c │ └── create_files.sh ├── 0x01-ls ├── README.md ├── direntry.c ├── direntry.h ├── direntry_utils.c ├── dirwalk.c ├── hls.h ├── list.c ├── list.h ├── list_utils.c ├── main.c ├── options.c ├── options.h ├── print_error.c ├── print_files.c ├── sort_direntry.c ├── sort_list.c ├── strings.c ├── strings.h ├── strings_2.c ├── strings_3.c ├── test │ ├── ..hidden3 │ ├── .hidden1 │ ├── .hidden2 │ ├── ABC │ ├── File2 │ ├── abc │ ├── file │ ├── file3 │ └── myfile ├── utils.c └── widths.c ├── 0x02-getline ├── 1-main.c ├── 3_line.py ├── 5-main.c ├── 6-main.c ├── README.md ├── _getline.c ├── _getline.h └── main.c ├── 0x03-proc_filesystem ├── README.md └── read_write_heap.py ├── 0x05-signals ├── 0-handle_signal.c ├── 1-current_handler_signal.c ├── 1-set_print_hello.c ├── 10-pid_exist.c ├── 100-all_in_one.c ├── 101-sigset_init.c ├── 102-signals_block.c ├── 103-signals_unblock.c ├── 104-handle_pending.c ├── 2-handle_sigaction.c ├── 3-current_handler_sigaction.c ├── 3-set_print_hello.c ├── 4-trace_signal_sender.c ├── 5-signal_describe.c ├── 6-suspend.c ├── 7-signal_send.c ├── 8-signal_send.sh ├── 9-handle_signal.sh ├── README.md ├── handle_pending.sh └── signals.h ├── 0x06-readelf ├── Makefile ├── README.md ├── inc │ └── readelf.h ├── src │ ├── 0-hreadelf.c │ ├── 1-hreadelf.c │ ├── 100-hreadelf.c │ ├── 2-hreadelf.c │ ├── elf_utils.c │ ├── elf_utils2.c │ ├── elf_utils3.c │ ├── elf_utils4.c │ ├── process_elf_header.c │ ├── process_elf_program_header.c │ ├── process_elf_section_header.c │ ├── process_elf_symbol_tables.c │ └── validate_elf.c └── tests │ ├── checker.bash │ └── elf_files │ ├── jpeg.mod │ ├── libperl.so.5.18 │ ├── netbsd32 │ ├── python.obj │ ├── sftp-server │ ├── solaris32 │ ├── sortix32 │ ├── sparcbigendian32 │ ├── ubuntu64 │ └── vgpreload_memcheck-x86-linux.so ├── 0x07-nm_objdump ├── Makefile ├── README.md ├── inc │ └── readelf.h ├── src │ ├── elf_utils.c │ ├── elf_utils1.c │ ├── elf_utils2.c │ ├── helper.c │ ├── nm.c │ ├── objdump.c │ ├── print_buffer.c │ ├── process_elf_header.c │ ├── process_elf_section_header.c │ ├── process_elf_symbol_tables.c │ └── validate_elf.c └── tests │ ├── 0-checker.bash │ ├── 1-checker.bash │ └── elf_files │ ├── jpeg.mod │ ├── libperl.so.5.18 │ ├── netbsd32 │ ├── python.obj │ ├── sftp-server │ ├── solaris32 │ ├── sortix32 │ ├── sparcbigendian32 │ ├── ubuntu64 │ └── vgpreload_memcheck-x86-linux.so ├── 0x08-malloc ├── 0-main.c ├── 1-main.c ├── EYNTK │ ├── 1-main.c │ ├── 2-main.c │ ├── 2-main_malloc.c │ ├── 2-naive_malloc.c │ ├── 3-main.c │ ├── 3-naive_malloc_header.c │ ├── 4-main.c │ ├── 4-main_beyond.c │ ├── 4-naive_malloc_page.c │ ├── 5-main.c │ ├── 5-naive_malloc_extend.c │ ├── 6-main.c │ ├── 6-naive_malloc_align.c │ ├── 7-main.c │ └── 7-naive_malloc.c ├── README.md ├── malloc.c ├── malloc.h └── naive_malloc.c ├── 0x09-libasm ├── 0-strlen.asm ├── 1-strcmp.asm ├── 100-putc.asm ├── 1000-puti.asm ├── 1001-puti_base.asm ├── 101-puts.asm ├── 102-strcasecmp.asm ├── 103-strncasecmp.asm ├── 104-strspn.asm ├── 105-strcspn.asm ├── 106-strpbrk.asm ├── 2-strncmp.asm ├── 3-strchr.asm ├── 4-strstr.asm ├── 5-memcpy.asm ├── README.md ├── libasm.h └── main │ ├── 0-main.c │ ├── 1-main.c │ ├── 100-main.c │ ├── 1000-main.c │ ├── 1001-main.c │ ├── 101-main.c │ ├── 102-main.c │ ├── 103-main.c │ ├── 104-main.c │ ├── 105-main.c │ ├── 106-main.c │ ├── 2-main.c │ ├── 3-main.c │ ├── 4-main.c │ ├── 5-main.c │ └── libasm.h ├── 0x0A_CPython ├── 0-python_lists_bigO ├── 1-python.c ├── 100-python.c ├── 2-python.c ├── 3-python.c ├── 4-python.c ├── 5-python.c ├── README.md └── tests │ ├── 1-test_lists.py │ ├── 100-tests.py │ ├── 2-tests.py │ ├── 3-tests.py │ ├── 4-tests.py │ └── 5-tests.py ├── 0x0b-strace ├── EYNTK │ ├── ex_0.c │ ├── ex_1.c │ └── ex_2.c ├── Makefile ├── README.md ├── inc │ ├── strace.h │ └── syscalls.h └── src │ ├── handle_syscall_macros.c │ ├── strace_0.c │ ├── strace_1.c │ ├── strace_2.c │ ├── strace_3.c │ ├── strace_4.c │ ├── strace_5.c │ ├── strace_6.c │ └── utils.c └── README.md /0x00-c_dynamic_libraries/1-create_dynamic_lib.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | gcc -shared -Wall -Werror -pedantic -Wextra -fPIC -o liball.so ./*.c 3 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/100-operations.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x00-c_dynamic_libraries/100-operations.so -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/101-make_me_win.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | wget -q -O /tmp/gigamillion.so https://github.com/SravanthiSinha/ShellScripts/raw/master/win_Giga_Millions/gigamillions.so 3 | export LD_PRELOAD=/tmp/gigamillions.so 4 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/holberton.h: -------------------------------------------------------------------------------- 1 | #ifndef _HOLBERTON_H_ 2 | #define _HOLBERTON_H_ 3 | 4 | #define EOF -1 5 | 6 | int _putchar(char c); 7 | int _islower(int c); 8 | int _isalpha(int c); 9 | int _abs(int n); 10 | int _isupper(int c); 11 | int _isdigit(int c); 12 | int _strlen(char *s); 13 | void _puts(char *s); 14 | char *_strcpy(char *dest, char *src); 15 | int _atoi(char *s); 16 | char *_strcat(char *dest, char *src); 17 | char *_strncat(char *dest, char *src, int n); 18 | char *_strncpy(char *dest, char *src, int n); 19 | int _strcmp(char *s1, char *s2); 20 | char *_memset(char *s, char b, unsigned int n); 21 | char *_memcpy(char *dest, char *src, unsigned int n); 22 | char *_strchr(char *s, char c); 23 | unsigned int _strspn(char *s, char *accept); 24 | char *_strpbrk(char *s, char *accept); 25 | char *_strstr(char *haystack, char *needle); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/libholberton.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x00-c_dynamic_libraries/libholberton.so -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/0-main.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | #include 3 | #include 4 | /** 5 | * main - check the code for Holberton School students. 6 | * 7 | * Return: Always EXIT_SUCCESS. 8 | */ 9 | int main(void) 10 | { 11 | printf("%d\n", _strlen("Holberton")); 12 | return (EXIT_SUCCESS); 13 | } 14 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_abs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _abs - function computes the absolute value of the integer argument c 3 | * @c: This is the character to be checked 4 | * 5 | * Return: Absolute value of the integer argument, of the appropriate 6 | * integer type for the function. 7 | */ 8 | int _abs(int c) 9 | { 10 | if (c >= 0) 11 | return (c); 12 | return (-1 * c); 13 | } 14 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_atoi.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * _atoi - The function converts the initial portion of the string 5 | * pointed to by @s to int. 6 | * @s: string too be converted to 7 | * 8 | * Return: Converted Value 9 | */ 10 | int _atoi(char *s) 11 | { 12 | int res; 13 | int sign; 14 | int i; 15 | 16 | res = 0; 17 | sign = 1; 18 | i = 0; 19 | if (s[0] == '-') 20 | { 21 | sign = -1; 22 | i++; 23 | } 24 | for (; s[i] != '\0'; ++i) 25 | { 26 | if (_isdigit(s[i]) == 0) 27 | return (0); 28 | res = res * 10 + s[i] - '0'; 29 | } 30 | return (sign * res); 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_isalpha.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _isalpha - checks whether the passed character is a alphabet 3 | * @c: This is the character to be checked 4 | * 5 | * Return: This function returns a non-zero value(true) if c is a 6 | * alphabetic letter else, zero (false). 7 | */ 8 | int _isalpha(int c) 9 | { 10 | if (c <= 122 && c >= 65) 11 | return (1); 12 | return (0); 13 | } 14 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_isdigit.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _isdigit - checks whether the passed character is a digit (0 through 9) 3 | * @c: This is the character to be checked 4 | * 5 | * Return: This function returns a non-zero value(true) if c is a digit else, 6 | * zero (false). 7 | */ 8 | int _isdigit(int c) 9 | { 10 | if (c <= 57 && c >= 48) 11 | return (1); 12 | return (0); 13 | } 14 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_islower.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _islower - checks whether the passed character is a lowercase letter. 3 | * @c: This is the character to be checked 4 | * 5 | * Return: This function returns a non-zero value(true) if c is a 6 | * lowercase alphabetic letter else, zero (false). 7 | */ 8 | int _islower(int c) 9 | { 10 | if (c <= 122 && c >= 97) 11 | return (1); 12 | return (0); 13 | } 14 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_isupper.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _isupper - checks whether the passed character is an upper case alphabet 3 | * @c: This is the character to be checked 4 | * 5 | * Return: This function returns a non-zero value(true) if c is a 6 | * upper case alphabetic letter else, zero (false). 7 | */ 8 | int _isupper(int c) 9 | { 10 | if (c <= 90 && c >= 65) 11 | return (1); 12 | return (0); 13 | } 14 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_memcpy.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _memcpy - A function that copies n bytes from memory area src 3 | * to memory area dest. 4 | * @dest: destationation to be copied to 5 | * @src: src to be copied from 6 | * @n: no of bytes to be copied 7 | * 8 | * Return: a pointer to dest 9 | */ 10 | char *_memcpy(char *dest, char *src, unsigned int n) 11 | { 12 | char *dp; 13 | const char *sp; 14 | 15 | dp = dest; 16 | sp = src; 17 | while (n--) 18 | *dp++ = *sp++; 19 | return (dest); 20 | } 21 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_memset.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _memset - The _memset function fills the first n bytes of the memory area 3 | * pointed to by s with the bytes b 4 | * @s: bytes to be filled in 5 | * @b: bytes to be filled 6 | * @n: no of bytes 7 | * 8 | * Return: A pointer to the memory area s 9 | */ 10 | 11 | char *_memset(char *s, char b, unsigned int n) 12 | { 13 | char *p; 14 | 15 | p = s; 16 | while (n--) 17 | *p++ = b; 18 | return (s); 19 | } 20 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_putchar.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * _putchar - writes the character c to stdout 5 | * @c: The character to print 6 | * 7 | * Return: On success 1. 8 | * On error, -1 is returned, and errno is set appropriately. 9 | */ 10 | int _putchar(char c) 11 | { 12 | return (write(1, &c, 1)); 13 | } 14 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_puts.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | 3 | /** 4 | * _puts - writes the string s to stdout 5 | * @s: The string to print 6 | * 7 | * Return: void 8 | */ 9 | void _puts(char *s) 10 | { 11 | while (*s) 12 | _putchar(*s++); 13 | _putchar('\n'); 14 | } 15 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_strcat.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | /** 3 | * _strcat - concatinates the given 2 strings 4 | * @dest: string to be concatinated to 5 | * @src: string to be concatinated with 6 | * Description: concatinates the given 2 strings 7 | * Return: concatinated string 8 | */ 9 | char *_strcat(char *dest, char *src) 10 | { 11 | int dest_len; 12 | int i; 13 | 14 | dest_len = _strlen(dest); 15 | for (i = 0 ; src[i] != '\0' ; i++) 16 | dest[dest_len + i] = src[i]; 17 | dest[dest_len + i] = '\0'; 18 | 19 | return (dest); 20 | } 21 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_strchr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _strchr - Returns a pointer to the 1st occurrence of the 3 | * character c in the string s 4 | * @s: string to be searched in 5 | * @c: character to be looked for 6 | * 7 | * Return: Pointer to the matched character or NULL if character is not found. 8 | */ 9 | char *_strchr(char *s, char c) 10 | { 11 | while (*s != c) 12 | if (!*s++) 13 | return (0); 14 | return ((char *)s); 15 | } 16 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_strcmp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _strcmp - Compare characters of two strings 3 | * @s1: C string to be compared. 4 | * @s2: C string to be compared. 5 | * 6 | * Return: An integral value indicating the relationship 7 | * between the strings 8 | */ 9 | 10 | int _strcmp(char *s1, char *s2) 11 | { 12 | while (*s1 && (*s1 == *s2)) 13 | s1++, s2++; 14 | return (*(unsigned char *)s1 - *(unsigned char *)s2); 15 | } 16 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_strcpy.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _strcpy - The _strcpy() function copies the string pointed to by src, 3 | * including the terminating null byte ('\0') to the buffer pointed to by dest. 4 | * @dest: string to be copied into 5 | * @src: string to be copied 6 | * 7 | * Return: a pointer to the destination string dest. 8 | */ 9 | char *_strcpy(char *dest, const char *src) 10 | { 11 | int i; 12 | 13 | i = 0; 14 | for (i = 0; src[i] != '\0'; i++) 15 | dest[i] = src[i]; 16 | dest[i] = '\0'; 17 | return (dest); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_strlen.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _strlen - calculate the length of a string 3 | * @s: This is the string whose length has to be calculated. 4 | * 5 | * Return: Number of bytes in the string s. 6 | */ 7 | int _strlen(char *s) 8 | { 9 | int i; 10 | 11 | i = 0; 12 | while (s[i]) 13 | i++; 14 | return (i); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_strncat.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | /** 3 | * _strncat - concatinates the given 2 strings 4 | * @dest: string to be concatinated to 5 | * @src: string to be concatinated with 6 | * @n: number of bytes to be concatinated 7 | * Description: concatinates the given 2 strings 8 | * Return: return a pointer to the resulting string dest. 9 | */ 10 | char *_strncat(char *dest, char *src, int n) 11 | { 12 | int dest_len; 13 | int i; 14 | 15 | dest_len = _strlen(dest); 16 | for (i = 0 ; i < n && src[i] != '\0' ; i++) 17 | dest[dest_len + i] = src[i]; 18 | dest[dest_len + i] = '\0'; 19 | 20 | return (dest); 21 | } 22 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_strncpy.c: -------------------------------------------------------------------------------- 1 | /** 2 | * _strncpy - The _strncpy() function copies the string pointed to by src, 3 | * at most n bytes of src are copied. 4 | * to the buffer pointed to by dest. 5 | * @dest: string to be copied into 6 | * @src: string to be copied 7 | * @n: number of bytes to be copied 8 | * 9 | * Return: a pointer to the destination string dest. 10 | */ 11 | char *_strncpy(char *dest, const char *src, int n) 12 | { 13 | int i; 14 | 15 | i = 0; 16 | for (i = 0; i < n && src[i] != '\0'; i++) 17 | dest[i] = src[i]; 18 | for ( ; i < n; i++) 19 | dest[i] = '\0'; 20 | return (dest); 21 | } 22 | 23 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_strpbrk.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | /** 3 | * _strpbrk - The function locates the first occurrence in the string s of any 4 | * of the bytes in the string accept. 5 | * @s:string s 6 | * @accept: bytes to be looked for in @s 7 | * 8 | * Return: a pointer to the byte in s that matches one 9 | * of the bytes in accept, or NULL if no such byte is found. 10 | */ 11 | char *_strpbrk(char *s, char *accept) 12 | { 13 | while (*s) 14 | if (_strchr(accept, *s++)) 15 | return ((char *) --s); 16 | return (0); 17 | } 18 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_strspn.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | /** 3 | * _strspn - function calculates the length (in bytes) of the initial segment 4 | * of s which consists entirely of bytes in accept 5 | * @s:string s 6 | * @accept: bytes to be looked for in @s 7 | * 8 | * Return: Number of bytes in the initial segment of s which consist 9 | * only of bytes from accept 10 | */ 11 | unsigned int _strspn(char *s, char *accept) 12 | { 13 | unsigned int ret; 14 | 15 | ret = 0; 16 | while (*s && _strchr(accept, *s++)) 17 | ret++; 18 | return (ret); 19 | } 20 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/_strstr.c: -------------------------------------------------------------------------------- 1 | #include "holberton.h" 2 | /** 3 | * _memcmp - compares the first n characters of the object pointed to by s1 4 | * to the first n characters of the object pointed to by s2. 5 | * @s1: string @s1 6 | * @s2: string @s2 7 | * @n: no of characters to be compated 8 | * 9 | * Return: Integer greater than, equal to, or less than zero, accordingly as 10 | * the object pointed to by s1 is greater than, equal to, or less than the 11 | * object pointed to by s2. 12 | */ 13 | int _memcmp(const void *s1, const void *s2, unsigned int n) 14 | { 15 | const unsigned char *p1 = s1, *p2 = s2; 16 | 17 | while (n--) 18 | { 19 | if (*p1 != *p2) 20 | return (*p1 - *p2); 21 | p1++, p2++; 22 | } 23 | return (0); 24 | } 25 | 26 | /** 27 | * _strstr - Finds the 1st occurrence of the substring needle in 28 | * the string haystack. 29 | * @haystack: string to be searched in 30 | * @needle: string to be looked for in @haystack 31 | * 32 | * Return: A pointer to the beginning of the substring, or NULL 33 | * if the substring is not found. 34 | */ 35 | char *_strstr(char *haystack, char *needle) 36 | { 37 | int n; 38 | 39 | n = _strlen(needle); 40 | while (*haystack) 41 | if (!_memcmp(haystack++, needle, n)) 42 | return (haystack - 1); 43 | return (0); 44 | } 45 | -------------------------------------------------------------------------------- /0x00-c_dynamic_libraries/src/create_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | while IFS='' read -r line || [[ -n "$line" ]]; do 3 | echo "$line" > $(echo "$line" | cut -d "(" -f1 |rev| cut -d " " -f1|rev| cut -d "*" -f2 |awk '{print $1".c"}') 4 | done < "$1" 5 | -------------------------------------------------------------------------------- /0x01-ls/direntry.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | 4 | /** 5 | * direntry_add - Adds the value to the direntry of Direntry 6 | * @direntry: The Direntry where the values are added. 7 | * @content: The value to be added. 8 | * @is_dir: if a file path is a directory = 1 else 0 9 | * @size : file_size 10 | * Return: on success: HLS_SUCCESS - 0 , on Failure: HLS_MAJOR_ERROR -2. 11 | */ 12 | int direntry_add(Direntry **direntry, char *content, int is_dir, long size) 13 | { 14 | Direntry *head = NULL; 15 | Direntry *node = NULL; 16 | 17 | head = *direntry; 18 | if (head == NULL) 19 | { 20 | head = malloc(sizeof(Direntry)); 21 | if (head == NULL) 22 | return (1); 23 | head->str = _strdup(content); 24 | head->is_dir = is_dir; 25 | head->size = size; 26 | head->next = NULL; 27 | *direntry = head; 28 | return (HLS_SUCCESS); 29 | } 30 | else 31 | { 32 | node = malloc(sizeof(Direntry)); 33 | if (node == NULL) 34 | return (1); 35 | node->str = _strdup(content); 36 | head->is_dir = is_dir; 37 | head->size = size; 38 | node->next = *direntry; 39 | *direntry = node; 40 | return (HLS_SUCCESS); 41 | } 42 | return (HLS_MAJOR_ERROR); 43 | } 44 | 45 | /** 46 | * direntry_size - Prints the Direntry. 47 | * @direntry: The Direntry whose size has to be measured. 48 | * 49 | * Return: size of the direntry of Direntry. 50 | */ 51 | int direntry_size(Direntry *direntry) 52 | { 53 | Direntry *node = NULL; 54 | int size; 55 | 56 | size = 0; 57 | node = direntry; 58 | while (node != NULL) 59 | { 60 | size++; 61 | node = node->next; 62 | } 63 | 64 | return (size); 65 | } 66 | 67 | /** 68 | * print_direntry - Prints the Direntry 69 | * @direntry: The Direntry to be printed 70 | * 71 | * Return: void 72 | */ 73 | void print_direntry(Direntry *direntry) 74 | { 75 | Direntry *node = NULL; 76 | 77 | node = direntry; 78 | while (node != NULL) 79 | { 80 | printf("%s\n", node->str); 81 | node = node->next; 82 | } 83 | } 84 | 85 | /** 86 | * free_direntry - Frees the Direntry 87 | * @head: The Direntry to be freed 88 | * 89 | * Return: void 90 | */ 91 | void free_direntry(Direntry *head) 92 | { 93 | Direntry *node = NULL; 94 | Direntry *temp = NULL; 95 | 96 | node = head; 97 | while (node != NULL) 98 | { 99 | temp = node; 100 | node = node->next; 101 | free(temp->str); 102 | free(temp); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /0x01-ls/direntry.h: -------------------------------------------------------------------------------- 1 | #ifndef _Direntry_H_ 2 | #define _Direntry_H_ 3 | 4 | /** 5 | * struct Direntry - List to be used to store the paths of the file. 6 | * @str : The value to be stored. 7 | * @is_dir : If a file path is directory 8 | * @next : A pointer to the next node of the List 9 | * @size : file size 10 | */ 11 | typedef struct Direntry 12 | { 13 | char *str; 14 | int is_dir; 15 | long size; 16 | struct Direntry *next; 17 | } Direntry; 18 | 19 | int direntry_size(Direntry *direntry); 20 | void print_direntry(Direntry *direntry); 21 | void free_direntry(Direntry *head); 22 | void removeDuplicates(Direntry *head); 23 | int direntry_add(Direntry **direntry, char *content, int is_dir, long size); 24 | void deleteDirent(Direntry **head_ref, char *key); 25 | Direntry *get_direntres(char *str, Direntry *en); 26 | Direntry *get_files(Direntry *en, List *dirnames); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /0x01-ls/direntry_utils.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * get_direntres - gets the list of the Direntres with specified value 5 | * @str: The value of the Direntry to be searched. 6 | * @en: The Direntry where the value are to be looked in. 7 | * 8 | * Return: on success: List of of the Direntres, on Failure: NULL 9 | */ 10 | Direntry *get_direntres(char *str, Direntry *en) 11 | { 12 | Direntry *result = NULL, *temp = NULL; 13 | int index = 0; 14 | 15 | while (en != NULL) 16 | { 17 | if (_strncmp(en->str, str, _strlen(str)) == 0) 18 | { 19 | if (_strchr(str, '/') == NULL) 20 | index = _strlen(str); 21 | else 22 | index = _strlen(str) + 1; 23 | if (_strchr(en->str + index, '/') == NULL) 24 | { 25 | if (temp == NULL) 26 | { 27 | result = malloc(sizeof(Direntry)); 28 | temp = result; 29 | } 30 | else 31 | { 32 | temp->next = malloc(sizeof(Direntry)); 33 | temp = temp->next; 34 | } 35 | temp->str = _strdup(en->str); 36 | temp->next = NULL; 37 | } 38 | } 39 | en = en->next; 40 | } 41 | return (result); 42 | } 43 | 44 | 45 | /** 46 | * get_files - gets the list of the Direntres which are files in params 47 | * @diren: The Direntry where the value are to be looked in. 48 | * @params: THe list of params 49 | * Return: on success: List of of the Direntres, on Failure: NULL 50 | */ 51 | Direntry *get_files(Direntry *diren, List *params) 52 | { 53 | Direntry *result = NULL, *temp = NULL, *en = NULL; 54 | int i = 0; 55 | 56 | for (i = 0 ; get_node(params, i); i++) 57 | { 58 | en = diren; 59 | while (en != NULL) 60 | { 61 | if (_strcmp(en->str, get_node(params, i)) == 0 && !is_directory(en->str)) 62 | { 63 | if (temp == NULL) 64 | { 65 | result = malloc(sizeof(Direntry)); 66 | temp = result; 67 | } 68 | else 69 | { 70 | temp->next = malloc(sizeof(Direntry)); 71 | temp = temp->next; 72 | } 73 | temp->str = _strdup(en->str); 74 | temp->next = NULL; 75 | break; 76 | } 77 | en = en->next; 78 | } 79 | } 80 | return (result); 81 | } 82 | /** 83 | * deleteDirent - Deletes the Direntry with a specified value 84 | * @head_ref: The List where the value are to be deleted. 85 | * @key: The value of the node to be deleted. 86 | * 87 | * Return: void 88 | */ 89 | void deleteDirent(Direntry **head_ref, char *key) 90 | { 91 | Direntry *temp = *head_ref, *prev; 92 | 93 | if (temp != NULL && _strcmp(temp->str, key) == 0) 94 | { 95 | *head_ref = temp->next; 96 | free(temp->str); 97 | free(temp); 98 | return; 99 | } 100 | while (temp != NULL && _strcmp(temp->str, key) != 0) 101 | { 102 | prev = temp; 103 | temp = temp->next; 104 | } 105 | 106 | if (temp == NULL) 107 | return; 108 | prev->next = temp->next; 109 | free(temp->str); 110 | free(temp); 111 | } 112 | 113 | /** 114 | * removeDuplicates - removes duplicate the Direntry with a specified value 115 | * @head: The List where the value are to be deleted. 116 | * 117 | * Return: void 118 | */ 119 | void removeDuplicates(Direntry *head) 120 | { 121 | Direntry *temp; 122 | 123 | while (head != NULL) 124 | { 125 | if (head->next != NULL) 126 | { 127 | while (head->next != NULL && _strcmp(head->next->str, head->str) == 0) 128 | { 129 | temp = head->next; 130 | head->next = temp->next; 131 | free(temp->str); 132 | free(temp); 133 | } 134 | } 135 | head = head->next; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /0x01-ls/dirwalk.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | 4 | /** 5 | * scan_files -scales the dirnames for validity of filepaths and builds 6 | * a direntry accordingly 7 | * @dirnames: input file optons 8 | * @direntry: The List to be built with the file_path 9 | * 10 | * Return: on success: HLS_SUCCESS - 0 , on Failure: HLS_MAJOR_ERROR, 11 | * HS_INVALID_FILE_DIR 12 | */ 13 | int scan_files(List **dirnames, Direntry **direntry) 14 | { 15 | int exit_value = HLS_SUCCESS; 16 | int error_occured = 0; 17 | char *param; 18 | List *node, *next; 19 | 20 | node = *dirnames; 21 | while (node != NULL) 22 | { 23 | param = _strdup(node->str); 24 | next = node->next; 25 | if (file_exist(param)) 26 | { 27 | exit_value = dirwalk(param, direntry); 28 | if (exit_value == HLS_MAJOR_ERROR) 29 | break; 30 | else if (exit_value == HLS_PERMISSION_DENIED) 31 | { 32 | print_error(HLS_PERMISSION_DENIED, param); 33 | deleteParam(dirnames, param); 34 | error_occured = 1; 35 | } 36 | } 37 | else 38 | { 39 | print_error(HLS_INVALID_FILE_DIR, param); 40 | deleteParam(dirnames, param); 41 | error_occured = 1; 42 | } 43 | node = next; 44 | free(param); 45 | } 46 | free_list(node); 47 | return (exit_value != HLS_SUCCESS || error_occured ? HLS_MAJOR_ERROR 48 | : HLS_SUCCESS); 49 | } 50 | 51 | /** 52 | * dirwalk - Adds to list consisiting of the files with in the 53 | * files in a particluar directory and files 54 | * @dirname: input file opton 55 | * @en: The List to be built with the file_path 56 | * 57 | * Return: on success: HLS_SUCCESS - 0 , on Failure: HLS_MAJOR_ERROR 58 | */ 59 | int dirwalk(char *dirname, Direntry **en) 60 | { 61 | DIR *dir = NULL; 62 | struct dirent *read = NULL; 63 | int exit_value = HLS_SUCCESS; 64 | char path[MAX_PATH_SIZE]; 65 | 66 | path[0] = '\0'; 67 | if (!is_directory(dirname)) 68 | exit_value = direntry_add(en, dirname, 0, file_size(dirname)); 69 | else 70 | { 71 | dir = opendir(dirname); 72 | if (!dir) 73 | return (HLS_PERMISSION_DENIED); 74 | while ((read = readdir(dir)) != NULL && exit_value == HLS_SUCCESS) 75 | { 76 | _strcat(path, dirname); 77 | if (path[_strlen(path) - 1] != '/') 78 | _strcat(path, "/"); 79 | _strcat(path, read->d_name); 80 | exit_value = direntry_add(en, path, is_directory(path), file_size(path)); 81 | path[0] = '\0'; 82 | } 83 | closedir(dir); 84 | } 85 | return (exit_value); 86 | } 87 | -------------------------------------------------------------------------------- /0x01-ls/hls.h: -------------------------------------------------------------------------------- 1 | #ifndef _HEADER_H_ 2 | #define _HEADER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "strings.h" 13 | #include "list.h" 14 | #include "direntry.h" 15 | #include "options.h" 16 | 17 | #define HLS_SUCCESS 0 18 | #define HLS_MINOR_ERROR 1 19 | #define HLS_MAJOR_ERROR 2 20 | 21 | #define HLS_INVALID_FILE_DIR 3 22 | #define HLS_INVALID_OPTION 4 23 | #define HLS_PERMISSION_DENIED 5 24 | #define MAX_PATH_SIZE 400 25 | #define MAX_OPTION_SIZE 100 26 | 27 | #define INT_DIGITS 19 /* enough for 64 bit integer */ 28 | 29 | int scan_files(List **dirnames, Direntry **direntry); 30 | int dirwalk(char *dirname, Direntry **direntry); 31 | 32 | void print_file_list(Options *op, List **dirnames, Direntry **dirent, int); 33 | 34 | void print_error(int error_code, char *name); 35 | 36 | int file_exist(char *filename); 37 | int is_directory(const char *path); 38 | 39 | int dirent_file_cmp(Direntry *node1, Direntry *node2, int reverse); 40 | int dirent_cmp_size(Direntry *node1, Direntry *node2, int reverse); 41 | int dirent_cmp(Direntry *, Direntry *, int reverse); 42 | void sort_direntres(Direntry **, int (*c)(Direntry *, Direntry *, int), int r); 43 | 44 | int node_cmp_size(List *node1, List *node2, int reverse); 45 | int node_cmp(List *node1, List *node2, int reverse); 46 | void sort_list(List **a, int (*cmp)(List *a, List *b, int r), int reverse); 47 | 48 | int validate_options(char **argv, char *options); 49 | 50 | int *widths(Direntry *en); 51 | long file_size(const char *filepath); 52 | char *basename(const char *filename); 53 | int *widths(Direntry *en); 54 | #endif 55 | -------------------------------------------------------------------------------- /0x01-ls/list.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * list_size - Prints the List. 5 | * @list: The List whose size has to be measured. 6 | * 7 | * Return: size of the list of List. 8 | */ 9 | int list_size(List *list) 10 | { 11 | List *node = NULL; 12 | int size; 13 | 14 | size = 0; 15 | node = list; 16 | while (node != NULL) 17 | { 18 | size++; 19 | node = node->next; 20 | } 21 | 22 | return (size); 23 | } 24 | 25 | /** 26 | * list_add - Adds the value to the direntry of Direntry 27 | * @list: The List where the values are added. 28 | * @content: The value to be added. 29 | * 30 | * Return: on success: HLS_SUCCESS - 0 , on Failure: HLS_MAJOR_ERROR -2. 31 | */ 32 | int list_add(List **list, char *content) 33 | { 34 | List *head = NULL; 35 | List *node = NULL; 36 | 37 | head = *list; 38 | node = malloc(sizeof(List)); 39 | if (node == NULL) 40 | return (1); 41 | node->str = _strdup(content); 42 | node->next = head; 43 | *list = node; 44 | return (0); 45 | } 46 | 47 | /** 48 | * array_to_list - Converts an string array to a linked list 49 | * @a: string array. 50 | * 51 | * Return: A linked list with values from array string. 52 | */ 53 | List *array_to_list(char **a) 54 | { 55 | List *list = NULL; 56 | int i = 0; 57 | 58 | for (i = 0; a[i]; i++) 59 | { 60 | if ((a[i][0] == '-' && _strlen(a[i]) == 1) || (a[i][0] != '-')) 61 | list_add(&list, a[i]); 62 | } 63 | return (list); 64 | } 65 | 66 | /** 67 | * free_list - Frees the List 68 | * @head: The List to be freed 69 | * 70 | * Return: void 71 | */ 72 | void free_list(List *head) 73 | { 74 | List *node = NULL; 75 | List *temp = NULL; 76 | 77 | node = head; 78 | while (node != NULL) 79 | { 80 | temp = node; 81 | node = node->next; 82 | free(temp->str); 83 | free(temp); 84 | } 85 | } 86 | 87 | 88 | /** 89 | * print_list - Prints the List 90 | * @list: The List to be printed 91 | * 92 | * Return: void 93 | */ 94 | void print_list(List *list) 95 | { 96 | List *node = NULL; 97 | 98 | node = list; 99 | while (node != NULL) 100 | { 101 | printf("%s\n", node->str); 102 | node = node->next; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /0x01-ls/list.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIST_H_ 2 | #define _LIST_H_ 3 | 4 | /** 5 | * struct List - List to be used to store the file options from input 6 | * @str : The value to be stored. 7 | * @next : A pointer to the next node of the List 8 | */ 9 | typedef struct List 10 | { 11 | char *str; 12 | struct List *next; 13 | } List; 14 | 15 | List *array_to_list(char **a); 16 | int list_size(List *list); 17 | void free_list(List *head); 18 | void deleteParam(List **head_ref, char *key); 19 | char *get_node(List *head, int index); 20 | void print_list(List *list); 21 | int list_add(List **list, char *content); 22 | int delete_nodeint_at_index(List **head, unsigned int index); 23 | #endif 24 | -------------------------------------------------------------------------------- /0x01-ls/list_utils.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * delete_nodeint_at_index - Deletes the node at index specified 5 | * @head: The List where the value are to be deleted. 6 | * @index: The position of the node to be deleted. 7 | * 8 | * Return: on success: 1, on Failure: 0 - list empty, -1 if position not found 9 | */ 10 | int delete_nodeint_at_index(List **head, unsigned int index) 11 | { 12 | List *curr = NULL; 13 | List *temp = NULL; 14 | unsigned int i = 0; 15 | 16 | if (*head == NULL) 17 | return (0); 18 | curr = *head; 19 | if (index == 1) 20 | { 21 | *head = (*head)->next; 22 | free(curr->str); 23 | free(curr); 24 | return (1); 25 | } 26 | else 27 | { 28 | while ((curr != NULL) && (i < index)) 29 | { 30 | i++; 31 | temp = curr; 32 | curr = curr->next; 33 | } 34 | if (curr == NULL) 35 | return (-1); 36 | temp->next = curr->next; 37 | free(temp->str); 38 | free(temp); 39 | } 40 | return (1); 41 | } 42 | 43 | 44 | /** 45 | * deleteParam - Deletes the node with a specified value 46 | * @head_ref: The List where the value are to be deleted. 47 | * @key: The value of the node to be deleted. 48 | * 49 | * Return: void 50 | */ 51 | void deleteParam(List **head_ref, char *key) 52 | { 53 | List *temp = *head_ref, *prev = NULL; 54 | 55 | if (temp != NULL && _strcmp(temp->str, key) == 0) 56 | { 57 | *head_ref = temp->next; 58 | free(temp->str); 59 | free(temp); 60 | return; 61 | } 62 | 63 | while (temp != NULL && _strcmp(temp->str, key) != 0) 64 | { 65 | prev = temp; 66 | temp = temp->next; 67 | } 68 | 69 | if (temp == NULL) 70 | return; 71 | 72 | prev->next = temp->next; 73 | free(temp->str); 74 | free(temp); 75 | } 76 | 77 | 78 | /** 79 | * get_node - get the value of the node at index specified 80 | * @head: The List where the value are to be deleted. 81 | * @index: The position of the node to be deleted. 82 | * 83 | * Return: on success: Value of the node, on Failure: NULL 84 | */ 85 | char *get_node(List *head, int index) 86 | { 87 | List *current = head; 88 | int count = 0; 89 | 90 | while (current != NULL) 91 | { 92 | if (count == index) 93 | return (current->str); 94 | count++; 95 | current = current->next; 96 | } 97 | return (NULL); 98 | } 99 | -------------------------------------------------------------------------------- /0x01-ls/main.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * main - A program that takes the name of a directory as a parameter and 5 | * prints its content. 6 | * @argc: no of inputs. 7 | * @argv: inputs. 8 | * 9 | * Return: on success: HLS_SUCCESS - 0 , on Failure: HLS_MAJOR_ERROR -2. 10 | */ 11 | int main(int __attribute__((unused)) argc, char **argv) 12 | { 13 | int exit_value = HLS_SUCCESS; 14 | Direntry *direntry = NULL; 15 | List *dirnames = NULL; 16 | char *names[2] = {"./", NULL}; 17 | char options[MAX_OPTION_SIZE]; 18 | int error_occured = 0; 19 | Options *options_s = NULL; 20 | 21 | options[0] = '\0'; 22 | /* default: current directory */ 23 | if (argc == 1 || (argc == 2 && _strcmp(argv[1], ".") == 0)) 24 | dirnames = array_to_list(names); 25 | else if (argc > 1) 26 | { 27 | exit_value = validate_options(argv + 1, options); 28 | /* default: current directory */ 29 | if (exit_value == HLS_SUCCESS) 30 | dirnames = array_to_list(argv + 1); 31 | if (exit_value == HLS_SUCCESS && list_size(dirnames) == 0) 32 | dirnames = array_to_list(names); 33 | } 34 | if (list_size(dirnames)) 35 | { 36 | options_s = inititate_options(options); 37 | sort_list(&dirnames, &node_cmp, options_s->reverse); 38 | exit_value = scan_files(&dirnames, &direntry); 39 | if (exit_value != HLS_SUCCESS) 40 | error_occured = 1; 41 | print_file_list(options_s, &dirnames, &direntry, error_occured); 42 | free_options(options_s); 43 | free_direntry(direntry); 44 | free_list(dirnames); 45 | } 46 | return (exit_value != HLS_SUCCESS || error_occured ? HLS_MAJOR_ERROR 47 | : HLS_SUCCESS); 48 | } 49 | -------------------------------------------------------------------------------- /0x01-ls/options.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * validate_options - validates the op given by the user and 5 | * fill the op 6 | * @argv: user inputs 7 | * @op: op to be validated. 8 | * 9 | * Return: on success: HLS_SUCCESS - 0 , on Failure: HLS_INVALID_OPTION. 10 | */ 11 | int validate_options(char **argv, char *op) 12 | { 13 | unsigned int i; 14 | char valid_options[6] = {'1', 'a', 'A', 'r', 'l', 'S'}; 15 | int exit_value = HLS_SUCCESS; 16 | 17 | op[0] = '\0'; 18 | for (i = 0 ; argv[i] != NULL; i++) 19 | { 20 | if (argv[i][0] == '-' && _strstr(op, argv[i]) == NULL) 21 | _strcat(op, argv[i] + 1); 22 | } 23 | for (i = 0; i < _strlen(op) && exit_value == HLS_SUCCESS; i++) 24 | { 25 | if (_strchr(valid_options, op[i]) == NULL) 26 | exit_value = HLS_INVALID_OPTION; 27 | } 28 | if (exit_value != HLS_SUCCESS) 29 | print_error(exit_value, op + i - 1); 30 | return (exit_value); 31 | } 32 | 33 | /** 34 | * inititate_options - INitialtes the op given by the user and 35 | * fill the op structure 36 | * @op: user op inputs 37 | * 38 | * Return: Options structure 39 | */ 40 | Options *inititate_options(char *op) 41 | { 42 | Options *options_s = malloc(sizeof(Options)); 43 | 44 | if (options_s != NULL) 45 | { 46 | if (op && (_strchr(op, '1') != NULL || _strchr(op, 'l') != NULL)) 47 | options_s->delimeter = _strdup("\n"); 48 | else 49 | options_s->delimeter = _strdup(" "); 50 | if (op && _strchr(op, 'a') != NULL) 51 | options_s->all = 1; 52 | else 53 | options_s->all = 0; 54 | if (op && _strchr(op, 'A') != NULL && _strchr(op, 'a') == NULL) 55 | options_s->almost_all = 1; 56 | else 57 | options_s->almost_all = 0; 58 | if (op && _strchr(op, 'r') != NULL) 59 | options_s->reverse = 1; 60 | else 61 | options_s->reverse = 0; 62 | if (op && _strchr(op, 'l') != NULL) 63 | options_s->long_format = 1; 64 | else 65 | options_s->long_format = 0; 66 | if (op && _strchr(op, 'S') != NULL) 67 | options_s->sort_size = 1; 68 | else 69 | options_s->sort_size = 0; 70 | } 71 | return (options_s); 72 | } 73 | 74 | 75 | /** 76 | * free_options - frees the op structure 77 | * @op: user op inputs structure 78 | * 79 | * Return: void 80 | */ 81 | void free_options(Options *op) 82 | { 83 | if (op != NULL) 84 | { 85 | free(op->delimeter); 86 | free(op); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /0x01-ls/options.h: -------------------------------------------------------------------------------- 1 | #ifndef _OPTIONS_H_ 2 | #define _OPTIONS_H_ 3 | 4 | /** 5 | * struct Options - Options struct used to store the file options from input 6 | * @all : If -a option is given all =1 else 0 7 | * @almost_all : If -A option is given almost_all =1 else 0 8 | * @delimeter : If -1 option is given delimeter ="\n" else " " 9 | * @reverse : If -r option is given almost_all =1 else 0 10 | * @long_format : If -l option is given long_format =1 else 0 11 | * @sort_size : If -S option is given sort_size =1 else 0 12 | */ 13 | typedef struct Options 14 | { 15 | int all; 16 | int almost_all; 17 | char *delimeter; 18 | int reverse; 19 | int long_format; 20 | int sort_size; 21 | } Options; 22 | 23 | Options *inititate_options(char *options); 24 | void free_options(Options *options); 25 | #endif 26 | -------------------------------------------------------------------------------- /0x01-ls/print_error.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * print_error - Prints thes the error 5 | * @error_code: error_code 6 | * @name: file input option 7 | * 8 | * Return: void 9 | */ 10 | void print_error(int error_code, char *name) 11 | { 12 | char *dir; 13 | 14 | switch (error_code) 15 | { 16 | case HLS_INVALID_FILE_DIR: 17 | dir = _strdup(name); 18 | dir[_strlen(dir) - 1] = '\0'; 19 | if (file_exist(dir) && name[_strlen(name) - 1] == '/') 20 | printf("hls: cannot access %s: Not a directory\n", name); 21 | else 22 | printf("hls: cannot access %s: No such file or directory\n", name); 23 | free(dir); 24 | break; 25 | case HLS_PERMISSION_DENIED: 26 | printf("hls: cannot open directory %s: Permission denied\n", name); 27 | break; 28 | case HLS_INVALID_OPTION: 29 | printf("hls: invalid option -- '%c'\n", name[0]); 30 | printf("Try 'hls --help' for more information.\n"); 31 | break; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /0x01-ls/sort_direntry.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | 4 | 5 | /** 6 | * dirent_file_cmp - compares the value of the 2 nodes alphabetically 7 | * @node1: node1 8 | * @node2: node2 9 | * @reverse: reverse enabled or disabled. 10 | * 11 | * Return: compared value of the 2 nodes alphabetically. 12 | * 0 if matches else > or < 0 13 | */ 14 | int dirent_file_cmp(Direntry *node1, Direntry *node2, int reverse) 15 | { 16 | char *a; 17 | char *b; 18 | int r = 0; 19 | 20 | a = _strdup(node1->str); 21 | b = _strdup(node2->str); 22 | if (_strcmp(a, ".") != 0 && _strcmp(a, "..") != 0) 23 | a = ltrim(a); 24 | if (_strcmp(b, ".") != 0 && _strcmp(b, "..") != 0) 25 | b = ltrim(b); 26 | r = _strcasecmp(a, b); 27 | if (r) 28 | { 29 | free(a); 30 | free(b); 31 | return (reverse == 0 ? r : -r); 32 | } 33 | r = _strcmp(a, b); 34 | free(a); 35 | free(b); 36 | return (reverse == 0 ? -r : r); 37 | } 38 | 39 | /** 40 | * dirent_cmp - compares the value of the 2 nodes alphabetically 41 | * @node1: node1 42 | * @node2: node2 43 | * @reverse: reverse enabled or disabled. 44 | * 45 | * Return: compared value of the 2 nodes alphabetically. 46 | * 0 if matches else > or < 0 47 | */ 48 | int dirent_cmp(Direntry *node1, Direntry *node2, int reverse) 49 | { 50 | char *a; 51 | char *b; 52 | int r = 0; 53 | 54 | a = _strdup(basename(node1->str)); 55 | b = _strdup(basename(node2->str)); 56 | if (_strcmp(a, ".") != 0 && _strcmp(a, "..") != 0) 57 | a = ltrim(a); 58 | if (_strcmp(b, ".") != 0 && _strcmp(b, "..") != 0) 59 | b = ltrim(b); 60 | r = _strcasecmp(a, b); 61 | if (r) 62 | { 63 | free(a); 64 | free(b); 65 | return (reverse == 0 ? r : -r); 66 | } 67 | r = _strcmp(a, b); 68 | free(a); 69 | free(b); 70 | return (reverse == 0 ? -r : r); 71 | } 72 | 73 | /** 74 | * dirent_cmp_size - compares the value of the 2 nodes by file size 75 | * @node1: node1 76 | * @node2: node2 77 | * @reverse: reverse enabled or disabled. 78 | * 79 | * Return: compared value of the 2 nodes by file size. 80 | * 0 if matches else > or < 0 81 | */ 82 | int dirent_cmp_size(Direntry *node1, Direntry *node2, int reverse) 83 | { 84 | long a = file_size(node1->str); 85 | long b = file_size(node2->str); 86 | 87 | if (a == b) 88 | return (dirent_cmp(node1, node2, reverse)); 89 | return (reverse == 0 ? (a > b ? -1 : 1) : (a < b ? -1 : 1)); 90 | } 91 | 92 | /** 93 | * swap - swaps the value of the 2 Direntres 94 | * @a: Direntry 1 95 | * @b: Direntry 2 96 | * 97 | * Return: void 98 | */ 99 | void swap(Direntry *a, Direntry *b) 100 | { 101 | char *temp; 102 | int tdir; 103 | long tsize; 104 | 105 | tdir = a->is_dir; 106 | a->is_dir = b->is_dir; 107 | b->is_dir = tdir; 108 | 109 | tsize = a->size; 110 | a->size = b->size; 111 | b->size = tsize; 112 | 113 | temp = a->str; 114 | a->str = b->str; 115 | b->str = temp; 116 | } 117 | 118 | 119 | /** 120 | * sort_direntres - sorts the direntry based on the cmp functions 121 | * @a: direntry to be sorted 122 | * @c: cmp function to be applied for sorting 123 | * @r: reverse enabled or disabled. 124 | * 125 | * Return: void 126 | */ 127 | void sort_direntres(Direntry **a, int (*c)(Direntry *, Direntry *, int), int r) 128 | { 129 | Direntry *traverse = *a; 130 | Direntry *yes; 131 | 132 | if (*a == NULL) 133 | return; 134 | for (; traverse != NULL; traverse = traverse->next) 135 | { 136 | for (yes = *a; yes->next != NULL; yes = yes->next) 137 | { 138 | if ((*c)(yes, yes->next, r) > 0) 139 | swap(yes, yes->next); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /0x01-ls/sort_list.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * node_cmp - compares the value of the 2 nodes alphabetically 5 | * @node1: node1 6 | * @node2: node2 7 | * @reverse: reverse enabled or disabled. 8 | * 9 | * Return: compared value of the 2 nodes alphabetically. 10 | * 0 if matches else > or < 0 11 | */ 12 | int node_cmp(List *node1, List *node2, int reverse) 13 | { 14 | int r = _strcasecmp(node1->str, node2->str); 15 | 16 | if (r) 17 | return (reverse == 0 ? r : -r); 18 | r = _strcmp(node1->str, node2->str); 19 | return (reverse == 0 ? -r : r); 20 | } 21 | 22 | /** 23 | * node_cmp_size - compares the value of the 2 nodes by file size 24 | * @node1: node1 25 | * @node2: node2 26 | * @reverse: reverse enabled or disabled. 27 | * 28 | * Return: compared value of the 2 nodes by file size. 29 | * 0 if matches else > or < 0 30 | */ 31 | int node_cmp_size(List *node1, List *node2, int reverse) 32 | { 33 | long a = file_size(node1->str); 34 | long b = file_size(node2->str); 35 | 36 | if (a == b) 37 | return (node_cmp(node1, node2, reverse)); 38 | return (reverse == 0 ? (a > b ? -1 : 1) : (a < b ? -1 : 1)); 39 | } 40 | 41 | /** 42 | * swap_list - swaps the value of the 2 nodes 43 | * @node1: node1 44 | * @node2: node2 45 | * 46 | * Return: void 47 | */ 48 | void swap_list(List *node1, List *node2) 49 | { 50 | char *temp = node1->str; 51 | 52 | node1->str = node2->str; 53 | node2->str = temp; 54 | } 55 | 56 | 57 | /** 58 | * sort_list - sorts the list based on the cmp functions 59 | * @a: list to be sorted 60 | * @cmp: cmp function to be applied for sorting 61 | * @reverse: reverse enabled or disabled. 62 | * 63 | * Return: void 64 | */ 65 | void sort_list(List **a, int (*cmp)(List *a, List *b, int r), int reverse) 66 | { 67 | List *traverse = *a; 68 | List *yes; 69 | 70 | if (*a == NULL) 71 | return; 72 | for (; traverse != NULL; traverse = traverse->next) 73 | { 74 | for (yes = *a; yes->next != NULL; yes = yes->next) 75 | { 76 | if ((*cmp)(yes, yes->next, reverse) > 0) 77 | swap_list(yes, yes->next); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /0x01-ls/strings.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * _strlen - calculate the length of a string 5 | * @s: This is the string whose length has to be calculated. 6 | * 7 | * Return: Number of bytes in the string s. 8 | */ 9 | unsigned int _strlen(const char *s) 10 | { 11 | int i; 12 | 13 | i = 0; 14 | while (s[i]) 15 | i++; 16 | return (i); 17 | } 18 | 19 | /** 20 | * _strcat - concatinates the given 2 strings 21 | * @dest: string to be concatinated to 22 | * @src: string to be concatinated with 23 | * Description: concatinates the given 2 strings 24 | * Return: concatinated string 25 | */ 26 | char *_strcat(char *dest, const char *src) 27 | { 28 | int dest_len; 29 | int i; 30 | 31 | dest_len = _strlen(dest); 32 | for (i = 0; src[i] != '\0'; i++) 33 | dest[dest_len + i] = src[i]; 34 | dest[dest_len + i] = '\0'; 35 | return (dest); 36 | } 37 | 38 | /** 39 | * _strchr - Returns a pointer to the 1st occurrence of the 40 | * character c in the string s 41 | * @s: string to be searched in 42 | * @c: character to be looked for 43 | * 44 | * Return: Pointer to the matched character or NULL if character is not found. 45 | */ 46 | char *_strchr(const char *s, int c) 47 | { 48 | const char ch = c; 49 | 50 | while (*s != ch) 51 | { 52 | if (*s == '\0') 53 | return (NULL); 54 | s++; 55 | } 56 | return ((char *)s); 57 | } 58 | 59 | /** 60 | * _strrchr - Returns a pointer to the last occurrence of the 61 | * character c in the string s 62 | * @s: string to be searched in 63 | * @c: character to be looked for 64 | * 65 | * Return: Pointer to the matched character or NULL if character is not found. 66 | */ 67 | char *_strrchr(const char *s, int c) 68 | { 69 | char *rtnval = 0; 70 | 71 | do { 72 | if (*s == c) 73 | rtnval = (char *)s; 74 | } while (*s++); 75 | return (rtnval); 76 | } 77 | 78 | /** 79 | * _strdup - Creates a duplicate of the string pointed to by str 80 | * @str: pointer to the null-terminated string to duplicate 81 | * Description: Creates a duplicate of the string pointed to by str 82 | * Return: A pointer to the newly allocated string, 83 | * or a null pointer if an error occurred. 84 | */ 85 | char *_strdup(const char *str) 86 | { 87 | int len; 88 | int i; 89 | char *s; 90 | 91 | i = 0; 92 | if (str == NULL) 93 | return (NULL); 94 | len = _strlen(str); 95 | s = malloc(sizeof(*s) * (len + 1)); 96 | while (i < len) 97 | { 98 | s[i] = str[i]; 99 | i++; 100 | } 101 | s[i] = '\0'; 102 | return (s); 103 | } 104 | -------------------------------------------------------------------------------- /0x01-ls/strings.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRINGS_H_ 2 | #define _STRINGS_H_ 3 | 4 | unsigned int _strlen(const char *s); 5 | int _strcmp(const char *s1, const char *s2); 6 | char *_strcat(char *dest, const char *src); 7 | char *_strchr(const char *s, int c); 8 | int _strncmp(const char *s1, const char *s2, unsigned int k); 9 | char *_strdup(const char *str); 10 | char *_strstr(char *haystack, char *needle); 11 | int _strcasecmp(const char *s1, const char *s2); 12 | char *_strtok(char *str, const char *comp); 13 | char *_strrchr(const char *s, int c); 14 | char *_strcpy(char *dest, const char *src); 15 | char *ltrim(char *src); 16 | #endif 17 | -------------------------------------------------------------------------------- /0x01-ls/strings_2.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * _strcmp - Compare characters of two strings 5 | * @s1: C string to be compared. 6 | * @s2: C string to be compared. 7 | * 8 | * Return: An integral value indicating the relationship 9 | * between the strings 10 | */ 11 | 12 | int _strcmp(const char *s1, const char *s2) 13 | { 14 | while (*s1 && (*s1 == *s2)) 15 | s1++, s2++; 16 | return (*(unsigned char *)s1 - *(unsigned char *)s2); 17 | } 18 | 19 | /** 20 | * _strncmp - Compare characters of two strings 21 | * @s1: C string to be compared. 22 | * @s2: C string to be compared. 23 | * @k: Maximum number of characters to compare 24 | * Description:Compares up to k characters of the C string s1 25 | * to those of the C string s2. 26 | * Return: An integral value indicating the relationship 27 | * between the strings 28 | */ 29 | int _strncmp(const char *s1, const char *s2, unsigned int k) 30 | { 31 | unsigned int i; 32 | int n1; 33 | int n2; 34 | int t; 35 | unsigned int n; 36 | 37 | i = 0; 38 | t = 0; 39 | n1 = _strlen(s1); 40 | n2 = _strlen(s2); 41 | n = (n1 >= n2) ? n1 : n2; 42 | n = (k > n) ? n : k; 43 | while (i < n) 44 | { 45 | if (s1[i] != s2[i]) 46 | { 47 | t = s1[i] - s2[i]; 48 | break; 49 | } 50 | else 51 | t = 0; 52 | i++; 53 | } 54 | return (t); 55 | } 56 | 57 | /** 58 | * _tolower - converts a lower case character to upper case 59 | * @ch: C character to be converted. 60 | * 61 | * Return: converted character 62 | */ 63 | char _tolower(unsigned char ch) 64 | { 65 | if (ch >= 'A' && ch <= 'Z') 66 | ch = 'a' + (ch - 'A'); 67 | return (ch); 68 | } 69 | 70 | /** 71 | * _strcasecmp - Compare characters of two strings ignoring case 72 | * @s1: C string to be compared. 73 | * @s2: C string to be compared. 74 | * 75 | * Return: An integral value indicating the relationship 76 | * between the strings 77 | */ 78 | int _strcasecmp(const char *s1, const char *s2) 79 | { 80 | const unsigned char *us1 = (const unsigned char *)s1; 81 | const unsigned char *us2 = (const unsigned char *)s2; 82 | 83 | while (_tolower(*us1) == _tolower(*us2++)) 84 | if (*us1++ == '\0') 85 | return (0); 86 | return (_tolower(*us1) - _tolower(*--us2)); 87 | } 88 | -------------------------------------------------------------------------------- /0x01-ls/strings_3.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * _strtok - A function breaks a string into a sequence of 5 | * zero or more nonempty tokens. 6 | * @str: C string to be looked in. 7 | * @comp: delimeter 8 | * 9 | * Return: A pointer to the next token, or NULL if there are no more tokens. 10 | */ 11 | char *_strtok(char *str, const char *comp) 12 | { 13 | static int pos, start; 14 | static char *s; 15 | int j = 0; 16 | 17 | if (str != NULL) 18 | s = str; 19 | 20 | while (s[pos] != '\0') 21 | { 22 | j = 0; 23 | while (comp[j] != '\0') 24 | { 25 | if (s[pos] == comp[j]) 26 | { 27 | s[pos] = '\0'; 28 | pos = pos + 1; 29 | if (s[start] != '\0') 30 | return (&s[start]); 31 | start = pos; 32 | pos--; 33 | break; 34 | } 35 | j++; 36 | } 37 | pos++; 38 | } 39 | s[pos] = '\0'; 40 | if (s[start] == '\0') 41 | return (NULL); 42 | return (&s[start]); 43 | } 44 | 45 | 46 | /** 47 | * _memcmp - compares the first n characters of the object pointed to by s1 48 | * to the first n characters of the object pointed to by s2. 49 | * @s1: string @s1 50 | * @s2: string @s2 51 | * @n: no of characters to be compated 52 | * 53 | * Return: Integer greater than, equal to, or less than zero, accordingly as 54 | * the object pointed to by s1 is greater than, equal to, or less than the 55 | * object pointed to by s2. 56 | */ 57 | int _memcmp(const void *s1, const void *s2, unsigned int n) 58 | { 59 | const unsigned char *p1 = s1, *p2 = s2; 60 | 61 | while (n--) 62 | { 63 | if (*p1 != *p2) 64 | return (*p1 - *p2); 65 | p1++, p2++; 66 | } 67 | return (0); 68 | } 69 | 70 | /** 71 | * _strstr - Finds the 1st occurrence of the substring needle in 72 | * the string haystack. 73 | * @haystack: string to be searched in 74 | * @needle: string to be looked for in @haystack 75 | * 76 | * Return: A pointer to the beginning of the substring, or NULL 77 | * if the substring is not found. 78 | */ 79 | char *_strstr(char *haystack, char *needle) 80 | { 81 | int n; 82 | 83 | n = _strlen(needle); 84 | while (*haystack) 85 | if (!_memcmp(haystack++, needle, n)) 86 | return (haystack - 1); 87 | return (0); 88 | } 89 | 90 | /** 91 | * _strcpy - The _strcpy() function copies the string pointed to by src, 92 | * including the terminating null byte ('\0') to the buffer pointed to by dest. 93 | * @dest: string to be copied into 94 | * @src: string to be copied 95 | * 96 | * Return: a pointer to the destination string dest. 97 | */ 98 | char *_strcpy(char *dest, const char *src) 99 | { 100 | int i; 101 | 102 | i = 0; 103 | for (i = 0; src[i] != '\0'; i++) 104 | dest[i] = src[i]; 105 | dest[i] = '\0'; 106 | return (dest); 107 | } 108 | 109 | /** 110 | * ltrim - ltrims the string(removes leading .) 111 | * @src: node1 112 | * 113 | * Return: ltrimmed string 114 | */ 115 | char *ltrim(char *src) 116 | { 117 | char *original = src; 118 | char *p = original; 119 | int trimmed = 0; 120 | 121 | do { 122 | if (*original != '.' || trimmed) 123 | { 124 | trimmed = 1; 125 | *p++ = *original; 126 | } 127 | } while (*original++ != '\0'); 128 | return (src); 129 | } 130 | -------------------------------------------------------------------------------- /0x01-ls/test/..hidden3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x01-ls/test/..hidden3 -------------------------------------------------------------------------------- /0x01-ls/test/.hidden1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x01-ls/test/.hidden1 -------------------------------------------------------------------------------- /0x01-ls/test/.hidden2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x01-ls/test/.hidden2 -------------------------------------------------------------------------------- /0x01-ls/test/ABC: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x01-ls/test/ABC -------------------------------------------------------------------------------- /0x01-ls/test/File2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x01-ls/test/File2 -------------------------------------------------------------------------------- /0x01-ls/test/abc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x01-ls/test/abc -------------------------------------------------------------------------------- /0x01-ls/test/file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x01-ls/test/file -------------------------------------------------------------------------------- /0x01-ls/test/file3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x01-ls/test/file3 -------------------------------------------------------------------------------- /0x01-ls/test/myfile: -------------------------------------------------------------------------------- 1 | Makefile -------------------------------------------------------------------------------- /0x01-ls/utils.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | 4 | /** 5 | * is_directory - Verifies if a file path is a directory 6 | * @filepath: file path 7 | * 8 | * Return: on success: 1 , on Failure:0. 9 | */ 10 | int is_directory(const char *filepath) 11 | { 12 | struct stat path_stat; 13 | 14 | lstat(filepath, &path_stat); 15 | return (S_ISDIR(path_stat.st_mode)); 16 | } 17 | 18 | /** 19 | * file_size - Verifies if a file path is a directory 20 | * @filepath: file path 21 | * 22 | * Return: the file size. 23 | */ 24 | long file_size(const char *filepath) 25 | { 26 | struct stat path_stat; 27 | 28 | lstat(filepath, &path_stat); 29 | return ((long)(path_stat.st_size)); 30 | } 31 | /** 32 | * file_exist - Verifies if a file path exists 33 | * @filepath: file path 34 | * 35 | * Return: on success: 1 , on Failure:0. 36 | */ 37 | int file_exist(char *filepath) 38 | { 39 | struct stat buffer; 40 | 41 | return (lstat(filepath, &buffer) == 0); 42 | } 43 | 44 | 45 | /** 46 | * basename - returns only the filename for a file path 47 | * @filepath: file path 48 | * 49 | * Return: a pointers to null-terminated strings 50 | */ 51 | char *basename(const char *filepath) 52 | { 53 | char *p = _strrchr(filepath, '/'); 54 | 55 | return (p ? p + 1 : (char *)filepath); 56 | } 57 | -------------------------------------------------------------------------------- /0x01-ls/widths.c: -------------------------------------------------------------------------------- 1 | #include "hls.h" 2 | 3 | /** 4 | * no_digits - Number of digits in a number 5 | * @n: Number 6 | * 7 | * Return: Number of digits in a number. 8 | */ 9 | unsigned int no_digits(long n) 10 | { 11 | int count = 0; 12 | 13 | while (n != 0) 14 | { 15 | n /= 10; 16 | ++count; 17 | } 18 | return (count); 19 | } 20 | 21 | /** 22 | * widths - gets the widths of the biggest file, user, grp in the list. 23 | * @en: The Direntry where the size of each drientry are to be looked in. 24 | * 25 | * Return: size of the biggest file 26 | */ 27 | int *widths(Direntry *en) 28 | { 29 | int tsize = 0, tsize2 = 0, tsize1 = 0; 30 | int *sizes; /*fsize , user_size , group_size*/ 31 | struct stat sb; 32 | struct passwd *usr; 33 | struct group *grp; 34 | 35 | sizes = malloc(3 * (sizeof(int))); 36 | if (en != NULL) 37 | { 38 | if (lstat(en->str, &sb) == -1) 39 | exit(HLS_MINOR_ERROR); 40 | usr = getpwuid(sb.st_uid); 41 | grp = getgrgid(sb.st_gid); 42 | sizes[0] = no_digits(file_size(en->str)); 43 | sizes[1] = usr != NULL ? _strlen(usr->pw_name) : no_digits(sb.st_uid); 44 | sizes[2] = grp != NULL ? _strlen(grp->gr_name) : no_digits(sb.st_gid); 45 | } 46 | while (en != NULL) 47 | { 48 | if (lstat(en->str, &sb) == -1) 49 | exit(HLS_MINOR_ERROR); 50 | usr = getpwuid(sb.st_uid); 51 | grp = getgrgid(sb.st_gid); 52 | tsize = no_digits(file_size(en->str)); 53 | tsize1 = usr != NULL ? _strlen(usr->pw_name) : no_digits(sb.st_uid); 54 | tsize2 = grp != NULL ? _strlen(grp->gr_name) : no_digits(sb.st_gid); 55 | if (tsize > sizes[0]) 56 | sizes[0] = tsize; 57 | if (tsize1 > sizes[1]) 58 | sizes[1] = tsize1; 59 | if (tsize2 > sizes[2]) 60 | sizes[2] = tsize2; 61 | en = en->next; 62 | } 63 | return (sizes); 64 | } 65 | -------------------------------------------------------------------------------- /0x02-getline/1-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /** 7 | * main - entry point. 8 | * 9 | * Return: always 0. 10 | */ 11 | #include "_getline.h" 12 | 13 | int main(void) { 14 | int fd, fd2, fd3; 15 | char *line, *line2, *line3; 16 | 17 | fd = open("normal_0", O_RDONLY); 18 | fd2 = open("normal_1", O_RDONLY); 19 | fd3 = open("the_swing", O_RDONLY); 20 | do { 21 | if ((line = _getline(fd))) { 22 | printf("%s\n", line); 23 | free(line); 24 | } 25 | if ((line2 = _getline(fd2))) { 26 | printf("%s\n",line2); 27 | free(line2); 28 | } 29 | if ((line3 = _getline(fd3))) { 30 | printf("%s\n", line3); 31 | free(line3); 32 | } 33 | } while (line || line2 || line3); 34 | close(fd); 35 | close(fd2); 36 | close(fd3); 37 | _getline(-1); 38 | return (0); 39 | } 40 | -------------------------------------------------------------------------------- /0x02-getline/3_line.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from itertools import zip_longest 4 | 5 | files = [open(filename) for filename in ['normal_0','normal_1','the_swing']] 6 | 7 | for lines in zip_longest(*files, fillvalue=''): 8 | print("".join(lines), end="") 9 | -------------------------------------------------------------------------------- /0x02-getline/5-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "_getline.h" 7 | 8 | /** 9 | * main - entry point. 10 | * 11 | * Return: always 0. 12 | */ 13 | int main(void) 14 | { 15 | int fd1, fd2, fd3; 16 | char *line1; 17 | char *line2; 18 | char *line3; 19 | int i; 20 | 21 | fd1 = open("the_swing", O_RDONLY); 22 | fd2 = open("man_gcc", O_RDONLY); 23 | fd3 = open("man_cat", O_RDONLY); 24 | printf("---------THE SWING (first 5 lines)-----------\n"); 25 | i = 0; 26 | while ((line1 = _getline(fd1))) 27 | { 28 | printf("%s\n", line1); 29 | free(line1); 30 | i++; 31 | if (i == 5) 32 | { 33 | break; 34 | } 35 | } 36 | printf("----------MAN GCC (first 5 lines)----------\n"); 37 | i = 0; 38 | while ((line2 = _getline(fd2))) 39 | { 40 | printf("%s\n", line2); 41 | free(line2); 42 | i++; 43 | if (i == 5) 44 | { 45 | break; 46 | } 47 | } 48 | printf("-----------MAN CAT (first 5 lines)---------\n"); 49 | i = 0; 50 | while ((line3 = _getline(fd3))) 51 | { 52 | printf("%s\n", line3); 53 | free(line3); 54 | i++; 55 | if (i == 5) 56 | { 57 | break; 58 | } 59 | } 60 | printf("---------THE SWING (END)-----------\n"); 61 | while ((line1 = _getline(fd1))) 62 | { 63 | printf("%s\n", line1); 64 | free(line1); 65 | } 66 | close(fd1); 67 | close(fd2); 68 | close(fd3); 69 | _getline(-1); 70 | printf("---------THE SWING (FULL-TEXT)-----------\n"); 71 | fd1 = open("the_swing", O_RDONLY); 72 | while ((line1 = _getline(fd1))) 73 | { 74 | printf("%s\n", line1); 75 | free(line1); 76 | } 77 | close(fd1); 78 | return (EXIT_SUCCESS); 79 | } 80 | -------------------------------------------------------------------------------- /0x02-getline/6-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "_getline.h" 7 | 8 | #define LINE_LEN 21 9 | 10 | /** 11 | * main - entry point. 12 | * 13 | * Return: always 0. 14 | */ 15 | int main(void) 16 | { 17 | int fd; 18 | char *line; 19 | int i; 20 | 21 | fd = open("zero", O_RDONLY); 22 | if (-1 == fd) 23 | { 24 | fprintf(stderr, "nop\n"); 25 | return (EXIT_FAILURE); 26 | } 27 | while ((line = _getline(fd))) 28 | { 29 | for (i = 0; i < LINE_LEN; i++) 30 | { 31 | /*if (i) 32 | { 33 | printf(" "); 34 | }*/ 35 | printf("%c", line[i]); 36 | } 37 | printf("\n"); 38 | free(line); 39 | } 40 | close(fd); 41 | return (EXIT_SUCCESS); 42 | } 43 | -------------------------------------------------------------------------------- /0x02-getline/README.md: -------------------------------------------------------------------------------- 1 | # 0x02. C - Static variables, getline 2 | -------------------------------------------------------------------------------- /0x02-getline/_getline.h: -------------------------------------------------------------------------------- 1 | #ifndef _GET_LINE_H_ 2 | #define _GET_LINE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define READ_SIZE 1024 10 | #define c_buff(buffer) memset(buffer, 0, sizeof(buffer)) 11 | 12 | /** 13 | * struct stream_s - used to store all related info of a particular stream. 14 | * @fd: the file descriptor 15 | * @buff: The buff for each fd 16 | * @buff_size: size of the buff 17 | * @eof: eof flag for each fd 18 | * @next: pointer to next stream 19 | * A value is not unique. It can correspond to several keys 20 | */ 21 | typedef struct stream_s 22 | { 23 | int fd; 24 | char *buff; 25 | int buff_size; 26 | int eof; 27 | struct stream_s *next; 28 | } StreamInfo; 29 | 30 | 31 | 32 | StreamInfo *initialize_get_Stash(StreamInfo **ss, int fd, int *error_occured); 33 | void deleteStash(StreamInfo **ss, StreamInfo *stream); 34 | void setStash(StreamInfo *stream, int *error_occured); 35 | void freeStash(StreamInfo **ss); 36 | 37 | char *get_update_Stash(StreamInfo *stream, int at, int *error_occured); 38 | 39 | char *_getline(const int fd); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /0x02-getline/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /** 7 | * main - entry point. 8 | * 9 | * Return: always 0. 10 | */ 11 | #include "_getline.h" 12 | 13 | int main(void) 14 | { 15 | int fd; 16 | char *line; 17 | 18 | fd = open("main.c", 0); 19 | while ((line = _getline(fd))) 20 | { 21 | printf("%s\n", line); 22 | free(line); 23 | } 24 | close(fd); 25 | return (0); 26 | } 27 | -------------------------------------------------------------------------------- /0x03-proc_filesystem/README.md: -------------------------------------------------------------------------------- 1 | # 0x02. Python - /proc filesystem 2 | 3 | ### System programming & Algorithm ― Linux programming 4 | 5 | 6 | Task : Hack the VM 7 | 8 | Write a script that finds a string in the heap of a running process, and replaces it. 9 | 10 | * Usage: read_write_heap.py pid search_string replace_string 11 | * where pid is the pid of the running process 12 | * and strings are ASCII 13 | * The script should look only in the heap of the process 14 | * Output: you can print whatever you think is interesting 15 | * On usage error, print an error message on stdout and exit with status code 1 16 | 17 | 18 | 19 | File: read_write_heap.py 20 | 21 | 22 | ### Usefull Links: 23 | 24 | https://www.kernel.org/doc/Documentation/filesystems/proc.txt 25 | 26 | https://unix.stackexchange.com/questions/6301/how-do-i-read-from-proc-pid-mem-under-linux/6302#6302 27 | 28 | https://stackoverflow.com/questions/12977179/reading-living-process-memory-without-interrupting-it-proc-kcore-is-an-option 29 | -------------------------------------------------------------------------------- /0x03-proc_filesystem/read_write_heap.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import sys 3 | import re 4 | 5 | 6 | def print_usage(): 7 | print("Usage: read_write_heap.py pid search_s replace_s") 8 | exit(1) 9 | 10 | 11 | def read_write_heap(pid, search_s, replace_s, only_writable=True): 12 | mem_perm = 'rw' if only_writable else 'r-' 13 | maps_filename = "/proc/{}/maps".format(pid) 14 | mem_filename = "/proc/{}/mem".format(pid) 15 | try: 16 | with open(maps_filename, 'r') as maps_file: 17 | with open(mem_filename, 'rb+', 0) as mem_file: 18 | for line in maps_file.readlines(): 19 | addr_perm = r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r][-w])' 20 | m = re.search(addr_perm, line) 21 | h = re.search(r'(\[heap\])', line) 22 | if m.group(3) == mem_perm and h and h.group(0) == "[heap]": 23 | start_addr = int(m.group(1), 16) 24 | end_addr = int(m.group(2), 16) 25 | mem_file.seek(start_addr) 26 | heap = mem_file.read(end_addr - start_addr) 27 | pos = heap.find(bytes(search_s, "ASCII")) 28 | if pos: 29 | mem_file.seek(start_addr + pos) 30 | adjusted_str = replace_s.ljust(len(search_s)) 31 | mem_file.write(bytes(adjusted_str, "ASCII")) 32 | else: 33 | print("Couldn't find the %s in the heap", search_s) 34 | except IOError as e: 35 | print("[ERROR] Can not open file {}:".format(maps_filename)) 36 | print(" I/O error({}): {}".format(e.errno, e.strerror)) 37 | exit(1) 38 | 39 | 40 | try: 41 | if len(sys.argv) != 4: 42 | print_usage() 43 | pid = int(sys.argv[1]) 44 | search_s = sys.argv[2] 45 | replace_s = sys.argv[3] 46 | if (len(search_s) == 0 or len(replace_s) == 0): 47 | print_usage() 48 | read_write_heap(pid, search_s, replace_s) 49 | except Exception as e: 50 | print_usage() 51 | -------------------------------------------------------------------------------- /0x05-signals/0-handle_signal.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | 3 | /** 4 | * sig_handler - handler for the signal SIGINT 5 | * @signum: signal number 6 | * Return : void. 7 | */ 8 | void sig_handler(int signum) 9 | { 10 | printf("Gotcha! [%d]\n", signum); 11 | fflush(stdout); 12 | } 13 | 14 | /** 15 | * handle_signal - a function that set a handler for the signal SIGINT 16 | * Return: 0 on success, or -1 on error. 17 | */ 18 | int handle_signal(void) 19 | { 20 | if (signal(SIGINT, sig_handler) == SIG_ERR) 21 | return (-1); 22 | return (0); 23 | } 24 | -------------------------------------------------------------------------------- /0x05-signals/1-current_handler_signal.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | 3 | /** 4 | * current_handler_signal - a function that retrieves the current handler of 5 | * the signal SIGINT. 6 | * Return: void. 7 | */ 8 | void (*current_handler_signal(void))(int) 9 | { 10 | void (*old_handler)(int) = NULL; 11 | 12 | old_handler = signal(SIGINT, print_hello); 13 | if (old_handler == SIG_ERR) 14 | return (NULL); 15 | return (old_handler); 16 | } 17 | -------------------------------------------------------------------------------- /0x05-signals/1-set_print_hello.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | 3 | /** 4 | * print_hello - handler for the signal SIGINT 5 | * @signum: signal number 6 | * Return : void. 7 | */ 8 | void print_hello(int signum) 9 | { 10 | printf("Hello! :)%d\n", signum); 11 | } 12 | 13 | /** 14 | * set_print_hello - a function that set a handler for the signal SIGINT 15 | * Return: 0 on success, or -1 on error. 16 | */ 17 | void set_print_hello(void) 18 | { 19 | signal(SIGINT, print_hello); 20 | return; 21 | } 22 | -------------------------------------------------------------------------------- /0x05-signals/10-pid_exist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | /** 4 | * pid_exist - a function that tests if a process exists, given its PID. 5 | * @pid: pid to look for 6 | * Return: 1 if the process with the PID pid exists, or 0 otherwise. 7 | */ 8 | int pid_exist(pid_t pid) 9 | { 10 | return (kill(pid, 0) == 0 ? 1 : (errno == ESRCH ? 0 : 1)); 11 | } 12 | -------------------------------------------------------------------------------- /0x05-signals/100-all_in_one.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | 3 | /** 4 | * sigaction_handler - handler for the signal SIGINT 5 | * @signum: signal number 6 | * @info: sinal info 7 | * @vp: pointer to user context 8 | * Return : void. 9 | */ 10 | void sigaction_handler(int signum, siginfo_t *info, void *vp) 11 | { 12 | (void)vp; 13 | (void)signum; 14 | psiginfo(info, "Caught"); 15 | fflush(stdout); 16 | } 17 | 18 | /** 19 | * all_in_one - A function that sets up a single handler for all the signals 20 | * Return: void. 21 | */ 22 | void all_in_one(void) 23 | { 24 | struct sigaction act; 25 | int i; 26 | 27 | memset(&act, '\0', sizeof(act)); 28 | act.sa_sigaction = &sigaction_handler; 29 | act.sa_flags = SA_SIGINFO; 30 | for (i = 1; i < 32; i++) 31 | { 32 | sigaction(i, &act, NULL); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /0x05-signals/101-sigset_init.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | 3 | /** 4 | * sigset_init - A function that sets up a single handler for all the signals 5 | * @set: A pointer to the signal set to initialize 6 | * @signals: A 0 terminated array of int, each one being a signal number 7 | * Return: 0 on success, or -1 on error 8 | */ 9 | int sigset_init(sigset_t *set, int *signals) 10 | { 11 | int i = 0; 12 | struct sigaction sigact; 13 | 14 | sigemptyset(set); 15 | while (signals[i] != 0) 16 | { 17 | sigact.sa_flags = SA_SIGINFO; 18 | sigact.sa_handler = SIG_IGN; 19 | sigaction(signals[i], &sigact, NULL); 20 | if (sigaddset(set, signals[i]) < 0) 21 | return (-1); 22 | i++; 23 | } 24 | return (0); 25 | } 26 | -------------------------------------------------------------------------------- /0x05-signals/102-signals_block.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | /** 3 | * signals_block - A function that block a given set of signals from being 4 | * delivered to the current process 5 | * @signals: A 0 terminated array of int, each one being a signal number 6 | * Return: 0 on success, or -1 on error 7 | */ 8 | int signals_block(int *signals) 9 | { 10 | int i = 0; 11 | sigset_t intmask; 12 | 13 | while (signals[i] != 0) 14 | { 15 | if (sigaddset(&intmask, signals[i]) < 0) 16 | return (-1); 17 | sigprocmask(SIG_BLOCK, &intmask, NULL); 18 | i++; 19 | } 20 | return (0); 21 | } 22 | -------------------------------------------------------------------------------- /0x05-signals/103-signals_unblock.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | /** 3 | * signals_unblock - A function that un block a given set of signals from being 4 | * delivered to the current process 5 | * @signals: A 0 terminated array of int, each one being a signal number 6 | * Return: 0 on success, or -1 on error 7 | */ 8 | int signals_unblock(int *signals) 9 | { 10 | int i = 0; 11 | sigset_t intmask; 12 | 13 | while (signals[i] != 0) 14 | { 15 | if (sigaddset(&intmask, signals[i]) < 0) 16 | return (-1); 17 | sigprocmask(SIG_UNBLOCK, &intmask, NULL); 18 | i++; 19 | } 20 | return (0); 21 | } 22 | -------------------------------------------------------------------------------- /0x05-signals/104-handle_pending.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | /** 3 | * handle_pending - a function that sets up a handler for all the pending 4 | * signals of the current process 5 | * @handler: A pointer to the handler function to set for the pending signals 6 | * Return: 0 on success, or -1 on error 7 | */ 8 | int handle_pending(void (*handler)(int)) 9 | { 10 | struct sigaction sigact; 11 | sigset_t waiting_mask; 12 | int i; 13 | 14 | sigpending(&waiting_mask); 15 | for (i = 1; i < 32; i++) 16 | { 17 | sigact.sa_flags = SA_SIGINFO; 18 | sigact.sa_handler = handler; 19 | sigaction(i, &sigact, NULL); 20 | if (sigaddset(&waiting_mask, i) < 0) 21 | return (-1); 22 | } 23 | return (0); 24 | } 25 | -------------------------------------------------------------------------------- /0x05-signals/2-handle_sigaction.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | 3 | /** 4 | * termination_handler - handler for the signal SIGINT 5 | * @signum: signal number 6 | * Return : void. 7 | */ 8 | void termination_handler(int signum) 9 | { 10 | printf("Gotcha! [%d]\n", signum); 11 | fflush(stdout); 12 | } 13 | 14 | /** 15 | * handle_sigaction - a function that set a handler for the signal SIGINT 16 | * Return: 0 on success, or -1 on error. 17 | */ 18 | int handle_sigaction(void) 19 | { 20 | struct sigaction sa; 21 | 22 | /* Set up the structure to specify the new action. */ 23 | sa.sa_handler = termination_handler; 24 | sigemptyset(&sa.sa_mask); 25 | /* Restart functions if interrupted by handler */ 26 | sa.sa_flags = SA_RESTART; 27 | 28 | return (sigaction(SIGINT, &sa, NULL)); 29 | } 30 | -------------------------------------------------------------------------------- /0x05-signals/3-current_handler_sigaction.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | 3 | /** 4 | * current_handler_sigaction - a function that retrieves the current handler of 5 | * the signal SIGINT. 6 | * Return: A pointer to the current handler of SIGINT, or NULL on failure 7 | */ 8 | void (*current_handler_sigaction(void))(int) 9 | { 10 | struct sigaction curr_act; 11 | 12 | if (sigaction(SIGINT, NULL, &curr_act) < 0) 13 | return (NULL); 14 | return (curr_act.sa_handler); 15 | } 16 | -------------------------------------------------------------------------------- /0x05-signals/3-set_print_hello.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | 3 | /** 4 | * print_hello - handler for the signal SIGINT 5 | * @signum: signal number 6 | * Return : void. 7 | */ 8 | void print_hello(int signum) 9 | { 10 | printf("Hello! :)%d\n", signum); 11 | } 12 | 13 | /** 14 | * set_print_hello - a function that set a handler for the signal SIGINT 15 | * Return: 0 on success, or -1 on error. 16 | */ 17 | void set_print_hello(void) 18 | { 19 | signal(SIGINT, print_hello); 20 | return; 21 | } 22 | -------------------------------------------------------------------------------- /0x05-signals/4-trace_signal_sender.c: -------------------------------------------------------------------------------- 1 | #include "signals.h" 2 | 3 | /** 4 | * termination_handler - handler for the signal SIGINT 5 | * @signum: signal number 6 | * @info: sinal info 7 | * @vp: pointer to user context 8 | * Return : void. 9 | */ 10 | void termination_handler(int signum, siginfo_t *info, void *vp) 11 | { 12 | (void)vp; 13 | (void)signum; 14 | printf("SIGQUIT sent by %d\n", info->si_pid); 15 | } 16 | 17 | /** 18 | * trace_signal_sender - defines a handler for the signal SIGQUIT 19 | * (Control-\ in a shell) 20 | * Return: 0 on success, or -1 on error. 21 | */ 22 | int trace_signal_sender(void) 23 | { 24 | struct sigaction new_action, old_action; 25 | 26 | /* Set up the structure to specify the new action. */ 27 | new_action.sa_sigaction = termination_handler; 28 | sigemptyset(&new_action.sa_mask); 29 | new_action.sa_flags = 0; 30 | 31 | return (sigaction(SIGQUIT, &new_action, &old_action)); 32 | } 33 | -------------------------------------------------------------------------------- /0x05-signals/5-signal_describe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * main - A program that prints a description of a given signal 7 | * @argc: No of command line args 8 | * @argv : command line args 9 | * Return: EXIT_SUCCESS or EXIT_FAILURE 10 | */ 11 | int main(int argc, char **argv) 12 | { 13 | if (argc != 2) 14 | { 15 | printf("Usage: %s \n", argv[0]); 16 | return (EXIT_FAILURE); 17 | } 18 | printf("%d: %s\n", atoi(argv[1]), strsignal(atoi(argv[1]))); 19 | return (EXIT_SUCCESS); 20 | } 21 | -------------------------------------------------------------------------------- /0x05-signals/6-suspend.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | 8 | /** 9 | * sig_handler - handler for the signal SIGINT 10 | * @signum: signal number 11 | * Return : void. 12 | */ 13 | void sig_handler(int signum) 14 | { 15 | printf("Caught %d\n", signum); 16 | printf("Signal received\n"); 17 | } 18 | 19 | 20 | /** 21 | * handle_signal - a function that set a handler for the signal SIGINT 22 | * Return: 0 on success, or -1 on error. 23 | */ 24 | int handle_signal(void) 25 | { 26 | if (signal(SIGINT, sig_handler) == SIG_ERR) 27 | return (-1); 28 | return (0); 29 | } 30 | /** 31 | * main - a program that sets a handler for the signal `SIGINT, 32 | * and exits right after the signal is received and handled 33 | * Return: EXIT_SUCCESS or EXIT_FAILURE 34 | */ 35 | int main(void) 36 | { 37 | if (handle_signal() < 0) 38 | return (EXIT_FAILURE); 39 | 40 | pause(); 41 | return (EXIT_SUCCESS); 42 | } 43 | -------------------------------------------------------------------------------- /0x05-signals/7-signal_send.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | /** 8 | * main - a program that sends the signal SIGINT to a process, given its PID 9 | * @argc: No of command line args 10 | * @argv : command line args 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(int argc, char **argv) 14 | { 15 | if (argc != 2) 16 | { 17 | printf("Usage: %s \n", argv[0]); 18 | return (EXIT_FAILURE); 19 | } 20 | if (kill(atoi(argv[1]), SIGINT) < 0) 21 | return (EXIT_FAILURE); 22 | return (EXIT_SUCCESS); 23 | } 24 | -------------------------------------------------------------------------------- /0x05-signals/8-signal_send.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #A sh script that sends the signal SIGQUIT to a process, given its PID 3 | if [ "$#" -ne 1 ]; then 4 | printf "Usage: %s \n" "$0" 5 | exit 1 6 | fi 7 | if kill -s QUIT "$1" >/dev/null 2>&1; then 8 | exit 0 9 | else 10 | exit 1 11 | fi 12 | -------------------------------------------------------------------------------- /0x05-signals/9-handle_signal.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | trap "echo Nope" ABRT IO TERM 3 | -------------------------------------------------------------------------------- /0x05-signals/README.md: -------------------------------------------------------------------------------- 1 | # 0x05. C - Signals 2 | 3 | ### System programming & Algorithm ― Linux programming 4 | 5 | 6 | * TASK 0: A function that set a handler for the signal SIGINT using signal() 7 | 8 | File: 0-handle_signal.c 9 | 10 | * TASK 1: A function that retrieves the current handler of the signal SIGINT 11 | 12 | File: 1-current_handler_signal.c 13 | 14 | * TASK 2: A function that set a handler for the signal SIGINT using sigaction() 15 | 16 | File: 2-handle_sigaction.c 17 | 18 | * TASK 3: A function that retrieves the current handler of the signal SIGINT 19 | 20 | File: 3-current_handler_sigaction.c 21 | 22 | * TASK 4: A function that defines a handler for the signal SIGQUIT (Control-\ in a shell) 23 | 24 | File: 4-trace_signal_sender.c 25 | 26 | * TASK 5: A program that prints a description of a given signal 27 | 28 | File: 5-signal_describe.c 29 | 30 | * TASK 6: A program that sets a handler for the signal `SIGINT`, and exits right after the signal is received and handled 31 | 32 | File: 6-suspend.c 33 | 34 | * TASK 7: A program that sends the signal SIGINT to a process, given its PID 35 | 36 | File: 7-signal_send.c 37 | 38 | * TASK 8: A sh script that sends the signal SIGQUIT to a process, given its PID 39 | 40 | File: 8-signal_send.sh 41 | 42 | * TASK 9: A sh script that set a handler for the signals SIGABRT, SIGIO and SIGTERM 43 | 44 | File: 9-handle_signal.sh 45 | 46 | * TASK 10: A function that tests if a process exists, given its PID. 47 | 48 | File: 10-pid_exist.c 49 | 50 | * TASK 11: A blog post about [signals](https://medium.com/@SravanthiSinha/lets-signal-b0378c9a9928) 51 | 52 | 53 | * TASK 12: A function that sets up a single handler for all the signals 54 | 55 | File: 100-all_in_one.c 56 | 57 | * TASK 13: A function that initializes a sigset. 58 | 59 | File: 101-sigset_init.c 60 | 61 | * TASK 14: A function that block a given set of signals from being delivered to the current process 62 | 63 | File: 102-signals_block.c 64 | 65 | * TASK 15: A function that unblock a given set of signals from being delivered to the current process 66 | 67 | File: 103-signals_unblock.c 68 | 69 | * TASK 16: A function that sets up a handler for all the pending signals of the current process 70 | 71 | File: 104-handle_pending.c 72 | 73 | ### Useful Resources: 74 | 75 | https://www.gnu.org/software/libc/manual/html_node/Signal-Handling.html#Signal-Handling 76 | 77 | http://www.comptechdoc.org/os/linux/programming/linux_pgsignals.html 78 | 79 | https://doc.lagout.org/programmation/unix/The%20Linux%20Programming%20Interface.pdf 80 | 81 | https://stackoverflow.com/questions/9152979/check-if-process-exists-given-its-pid/9153003 82 | 83 | https://www.ibm.com/support/knowledgecenter/en/ssw_i5_54/apis/sigeset.htm 84 | -------------------------------------------------------------------------------- /0x05-signals/handle_pending.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | for i in `seq 1 8` 3 | do 4 | kill "-$i" "$1" >/dev/null 2>&1 5 | done 6 | for i in `seq 11 15` 7 | do 8 | kill "-$i" "$1" >/dev/null 2>&1 9 | done 10 | kill -10 "$1" >/dev/null 2>&1 11 | -------------------------------------------------------------------------------- /0x05-signals/signals.h: -------------------------------------------------------------------------------- 1 | #ifndef __SIGNALS__ 2 | #define __SIGNALS__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int handle_signal(void); 10 | void (*current_handler_signal(void))(int); 11 | int handle_sigaction(void); 12 | void (*current_handler_sigaction(void))(int); 13 | int trace_signal_sender(void); 14 | int pid_exist(pid_t pid); 15 | void all_in_one(void); 16 | int sigset_init(sigset_t *set, int *signals); 17 | int signals_block(int *signals); 18 | int signals_unblock(int *signals); 19 | int handle_pending(void (*handler)(int)); 20 | void print_hello(int); 21 | #endif 22 | -------------------------------------------------------------------------------- /0x06-readelf/Makefile: -------------------------------------------------------------------------------- 1 | # CC = gcc-4.8 2 | # CFLAGS = -Wall -Werror -Wextra -pedantic -g 3 | 4 | _SRC = 0-hreadelf.c \ 5 | validate_elf.c \ 6 | elf_utils.c \ 7 | elf_utils2.c \ 8 | elf_utils3.c \ 9 | process_elf_header.c 10 | 11 | _SRC1 = 1-hreadelf.c \ 12 | validate_elf.c \ 13 | elf_utils.c \ 14 | elf_utils2.c \ 15 | elf_utils3.c \ 16 | process_elf_header.c \ 17 | process_elf_section_header.c 18 | 19 | _SRC2 = 2-hreadelf.c \ 20 | validate_elf.c \ 21 | elf_utils.c \ 22 | elf_utils2.c \ 23 | elf_utils3.c \ 24 | process_elf_header.c \ 25 | process_elf_section_header.c \ 26 | process_elf_program_header.c 27 | 28 | _SRC3 = 100-hreadelf.c \ 29 | validate_elf.c \ 30 | elf_utils.c \ 31 | elf_utils2.c \ 32 | elf_utils3.c \ 33 | elf_utils4.c \ 34 | process_elf_header.c \ 35 | process_elf_section_header.c \ 36 | process_elf_symbol_tables.c 37 | 38 | SRC = $(patsubst %,$(SDIR)/%,$(_SRC)) 39 | 40 | SRC1 = $(patsubst %,$(SDIR)/%,$(_SRC1)) 41 | 42 | SRC2 = $(patsubst %,$(SDIR)/%,$(_SRC2)) 43 | 44 | SRC3 = $(patsubst %,$(SDIR)/%,$(_SRC3)) 45 | 46 | _OBJ = $(_SRC:.c=.o) 47 | OBJECTS = $(patsubst %,$(ODIR)/%,$(_OBJ)) 48 | 49 | _OBJ1 = $(_SRC1:.c=.o) 50 | OBJECTS1 = $(patsubst %,$(ODIR)/%,$(_OBJ1)) 51 | 52 | _OBJ2 = $(_SRC2:.c=.o) 53 | OBJECTS2 = $(patsubst %,$(ODIR)/%,$(_OBJ2)) 54 | 55 | _OBJ3 = $(_SRC3:.c=.o) 56 | OBJECTS3 = $(patsubst %,$(ODIR)/%,$(_OBJ3)) 57 | 58 | _DEPS = readelf.h 59 | DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) 60 | 61 | IDIR = ./inc 62 | SDIR = ./src 63 | ODIR = . 64 | 65 | OUTPUT = 0-hreadelf 66 | OUTPUT1 = 1-hreadelf 67 | OUTPUT2 = 2-hreadelf 68 | OUTPUT3 = 100-hreadelf 69 | 70 | $(ODIR)/%.o : $(SDIR)/%.c 71 | $(CC) $(CFLAGS) -c -o $@ $< -I$(IDIR) 72 | 73 | all : $(OUTPUT1) $(OUTPUT) $(OUTPUT2) $(OUTPUT3) 74 | 75 | $(OUTPUT) : $(OBJECTS) 76 | $(CC) -o $@ $^ $(LINKS) 77 | 78 | $(OUTPUT1) : $(OBJECTS1) 79 | $(CC) -o $@ $^ $(LINKS) 80 | 81 | $(OUTPUT2) : $(OBJECTS2) 82 | $(CC) -o $@ $^ $(LINKS) 83 | 84 | $(OUTPUT3) : $(OBJECTS3) 85 | $(CC) -o $@ $^ $(LINKS) 86 | 87 | .PHONY : clean 88 | 89 | clean : 90 | rm -f $(OUTPUT) $(OUTPUT1) $(OUTPUT3) $(OBJECTS) $(OBJECTS1) $(OUTPUT2) $(OBJECTS2) $(OBJECTS3) 91 | 92 | re: $(OBJ) $(OBJ1) $(OBJ2) $(OBJ3) 93 | -------------------------------------------------------------------------------- /0x06-readelf/README.md: -------------------------------------------------------------------------------- 1 | ## 0x06. C - ELF: readelf 2 | ### System programming & Algorithm ― Linux programming 3 | 4 | 0-hreadelf - a program that displays the information contained in the ELF file header of an ELF file. 5 | ``` 6 | Usage: 0-hreadelf elf_filename 7 | ``` 8 | standard output, error output and status are exact same as readelf -W -h 9 | 10 | 1-hreadelf - a program that displays the information contained in the ELF sections' headers of an ELF file. 11 | ``` 12 | Usage: 1-hreadelf elf_filename 13 | ``` 14 | standard output, error output and status are the exact same as readelf -W -S 15 | 16 | 2-hreadelf - a program that displays the information contained in the ELF program headers of an ELF file. 17 | ``` 18 | Usage: 2-hreadelf elf_filename 19 | ``` 20 | standard output, error output and status are the exact same as readelf -W -l 21 | 22 | 100-hreadelf - a program that displays the information contained in the ELF symbol tables of an ELF file. 23 | ``` 24 | Usage: 100-hreadelf elf_filename 25 | ``` 26 | standard output, error output and status are the exact same as readelf -W -s 27 | 28 | ## Useful Resources: 29 | * man elf(5), man readelf(1) 30 | * See also /usr/include/elf.h 31 | * [ELF wiki](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 32 | * [ELF](http://www.cs.stevens.edu/~jschauma/810/elf.html) 33 | * [The ELF Object File Format: Introduction ](http://www.linuxjournal.com/article/1059) 34 | * [The ELF Object File Format by Dissection](http://www.linuxjournal.com/node/1060/print) 35 | * [ELF_Tutorial](http://wiki.osdev.org/ELF_Tutorial#ELF_Data_Types) 36 | * [FILE Format](https://docs.oracle.com/cd/E19683-01/816-1386/6m7qcoblj/index.html#chapter6-73445) 37 | -------------------------------------------------------------------------------- /0x06-readelf/src/0-hreadelf.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * main - A program that takes the name of a elf file as a parameter and 5 | * displays the information contained in the ELF file header of an ELF file. 6 | * @argc: no of inputs. 7 | * @argv: inputs. 8 | * 9 | * Return: on success: 0 , on Failure: 1. 10 | */ 11 | int main(int argc, char *argv[]) 12 | { 13 | ElfN_Ehdr ehdr; 14 | int exit_status = 0, arch = 0; 15 | FILE *file; 16 | 17 | /* validate user input */ 18 | if (argc < 2) 19 | { 20 | printf("Usage: %s elf_filename\n", argv[0]); 21 | exit(1); 22 | } 23 | /* open the elf file */ 24 | file = fopen(argv[1], "rb"); 25 | if (file) 26 | { 27 | if (fread(ehdr.e_ident, EI_NIDENT, 1, file) && 28 | elf_check_file(ehdr.e_ident)) 29 | { 30 | get_architecture(ehdr.e_ident[EI_CLASS], &arch); 31 | if (arch == 64) 32 | { 33 | read_elf_header_64(&ehdr, file); 34 | } else if (arch == 32) 35 | { 36 | read_elf_header_32(&ehdr, file); 37 | } 38 | print_elf_header(ehdr); 39 | } else 40 | printf("%s: %s\n", E, argv[0]); 41 | exit_status = 1; 42 | /* 43 | * finally close the file 44 | */ 45 | fclose(file); 46 | } else 47 | { 48 | printf("%s: Error: '%s': No such file\n", argv[0], argv[1]); 49 | exit_status = 1; 50 | } 51 | return (exit_status); 52 | } 53 | -------------------------------------------------------------------------------- /0x06-readelf/src/1-hreadelf.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * main - A program that takes the name of a elf file as a parameter and 5 | * displays the information contained in section headers of an ELF file. 6 | * @argc: no of inputs. 7 | * @argv: inputs. 8 | * 9 | * Return: on success: 0 , on Failure: 1. 10 | */ 11 | int main(int argc, char *argv[]) 12 | { 13 | ElfN_Ehdr ehdr; 14 | int exit_status = 0, arch = 0; 15 | FILE *file; 16 | 17 | /* validate user input */ 18 | if (argc < 2) 19 | { 20 | printf("Usage: %s elf_filename\n", argv[0]); 21 | exit(1); 22 | } 23 | /* open the elf file */ 24 | file = fopen(argv[1], "rb"); 25 | if (file) 26 | { 27 | if (fread(ehdr.e_ident, EI_NIDENT, 1, file) && 28 | elf_check_file(ehdr.e_ident)) 29 | { 30 | get_architecture(ehdr.e_ident[EI_CLASS], &arch); 31 | read_elf_section_header_N(&ehdr, file, arch); 32 | } else 33 | printf("%s: %s\n", E, argv[0]); 34 | exit_status = 1; 35 | /* 36 | * finally close the file 37 | */ 38 | fclose(file); 39 | } else 40 | { 41 | printf("%s: Error: '%s': No such file\n", argv[0], argv[1]); 42 | exit_status = 1; 43 | } 44 | return (exit_status); 45 | } 46 | -------------------------------------------------------------------------------- /0x06-readelf/src/100-hreadelf.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * main - A program that takes the name of a elf file as a parameter and 5 | * displays the information contained in Symbol tables of an ELF file. 6 | * @argc: no of inputs. 7 | * @argv: inputs. 8 | * 9 | * Return: on success: 0 , on Failure: 1. 10 | */ 11 | int main(int argc, char *argv[]) 12 | { 13 | ElfN_Ehdr ehdr; 14 | int exit_status = 0, arch = 0; 15 | FILE *file; 16 | 17 | /* validate user input */ 18 | if (argc < 2) 19 | { 20 | printf("Usage: %s elf_filename\n", argv[0]); 21 | exit(1); 22 | } 23 | /* open the elf file */ 24 | file = fopen(argv[1], "rb"); 25 | if (file) 26 | { 27 | if (fread(ehdr.e_ident, EI_NIDENT, 1, file) && 28 | elf_check_file(ehdr.e_ident)) 29 | { 30 | get_architecture(ehdr.e_ident[EI_CLASS], &arch); 31 | read_elf_symbol_table_N(&ehdr, file, arch); 32 | } else 33 | printf("%s: %s\n", E, argv[0]); 34 | exit_status = 1; 35 | /* finally close the file*/ 36 | fclose(file); 37 | } else 38 | { 39 | printf("%s: Error: '%s': No such file\n", argv[0], argv[1]); 40 | exit_status = 1; 41 | } 42 | return (exit_status); 43 | } 44 | -------------------------------------------------------------------------------- /0x06-readelf/src/2-hreadelf.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * main - A program that takes the name of a elf file as a parameter and 5 | * displays the information contained in the program header of an ELF file. 6 | * @argc: no of inputs. 7 | * @argv: inputs. 8 | * 9 | * Return: on success: 0 , on Failure: 1. 10 | */ 11 | int main(int argc, char *argv[]) 12 | { 13 | ElfN_Ehdr ehdr; 14 | int exit_status = 0, arch = 0; 15 | FILE *file; 16 | 17 | /* validate user input */ 18 | if (argc < 2) 19 | { 20 | printf("Usage: %s elf_filename\n", argv[0]); 21 | exit(1); 22 | } 23 | /* open the elf file */ 24 | file = fopen(argv[1], "rb"); 25 | if (file) 26 | { 27 | if (fread(ehdr.e_ident, EI_NIDENT, 1, file) && 28 | elf_check_file(ehdr.e_ident)) 29 | { 30 | get_architecture(ehdr.e_ident[EI_CLASS], &arch); 31 | read_elf_program_header_N(&ehdr, file, arch); 32 | } else 33 | printf("%s: %s\n", E, argv[0]); 34 | exit_status = 1; 35 | /* 36 | * finally close the file 37 | */ 38 | fclose(file); 39 | } else 40 | { 41 | printf("%s: Error: '%s': No such file\n", argv[0], argv[1]); 42 | exit_status = 1; 43 | } 44 | return (exit_status); 45 | } 46 | -------------------------------------------------------------------------------- /0x06-readelf/src/elf_utils3.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * get_byte_big_endian - fetches the bytes in big endian formatted data 5 | * @data: data to be fetched 6 | * @size: size of the data 7 | * 8 | * Return: the bytes in big endian format data. 9 | */ 10 | uint64_t get_byte_big_endian(uint64_t data, int size) 11 | { 12 | switch (size) 13 | { 14 | case 2: 15 | return (be16toh(data)); 16 | case 4: 17 | return (be32toh(data)); 18 | case 8: 19 | return (be64toh(data)); 20 | default: 21 | return (0); 22 | } 23 | } 24 | 25 | /** 26 | * get_byte_host - fetches the bytes 27 | * @data: data to be fetched 28 | * @size: size of the data 29 | * 30 | * Return: the data. 31 | */ 32 | uint64_t get_byte_host(uint64_t data, int __attribute__ ((unused)) size) 33 | { 34 | return (data); 35 | } 36 | 37 | 38 | /** 39 | * get_vma - gets the value with appropriate format and end string 40 | * @no: input no be formated. 41 | * @format: d - decimal, hex- hexadecimal 42 | * @end: end string f- file bytes , b -bytes 43 | * Return: formatted value 44 | */ 45 | char *get_vma(unsigned int no, char format, char end) 46 | { 47 | char buff[32]; 48 | 49 | if (format == 'd' && end == 'b') 50 | sprintf(buff, "%d (bytes)", no); 51 | else if (format == 'd' && end == 'f') 52 | sprintf(buff, "%d (bytes into file)", no); 53 | else if (format == 'd') 54 | sprintf(buff, "%d", no); 55 | else if (format == 'x') 56 | sprintf(buff, "0x%x", no); 57 | return (strdup(buff)); 58 | } 59 | 60 | 61 | /** 62 | * read_section- fetches the section 63 | * @sh: section header 64 | * @fd: file descriptor of input elf file 65 | * Return: string representation of the file 66 | */ 67 | char *read_section(int fd, ElfN_Shdr sh) 68 | { 69 | char *buff = malloc(sh.sh_size + 1); 70 | 71 | if (!buff) 72 | { 73 | printf("Failed to allocate\n"); 74 | } 75 | 76 | assert(buff != NULL); 77 | assert(lseek(fd, (off_t) sh.sh_offset, SEEK_SET) == 78 | (off_t) sh.sh_offset); 79 | assert(read(fd, (void *)buff, sh.sh_size) == (ssize_t) sh.sh_size); 80 | buff[sh.sh_size] = '\0'; 81 | return (buff); 82 | } 83 | -------------------------------------------------------------------------------- /0x06-readelf/src/elf_utils4.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * get_symbol_type - gets the symbol type 5 | * @type: symbol type of elf 6 | * Return: symbol type of elf 7 | */ 8 | char *get_symbol_type(unsigned int type) 9 | { 10 | char buff[32]; 11 | 12 | switch (type) 13 | { 14 | case STT_NOTYPE: 15 | return ("NOTYPE"); 16 | case STT_OBJECT: 17 | return ("OBJECT"); 18 | case STT_FUNC: 19 | return ("FUNC"); 20 | case STT_SECTION: 21 | return ("SECTION"); 22 | case STT_FILE: 23 | return ("FILE"); 24 | case STT_COMMON: 25 | return ("COMMON"); 26 | case STT_TLS: 27 | return ("TLS"); 28 | default: 29 | return ("NOTYPE"); 30 | } 31 | } 32 | 33 | /** 34 | * get_symbol_binding - gets the binding type 35 | * @binding: binding type of elf 36 | * Return: binding type of elf 37 | */ 38 | char *get_symbol_binding(unsigned int binding) 39 | { 40 | char buff[32]; 41 | 42 | switch (binding) 43 | { 44 | case STB_LOCAL: 45 | return ("LOCAL"); 46 | case STB_GLOBAL: 47 | return ("GLOBAL"); 48 | case STB_WEAK: 49 | return ("WEAK"); 50 | default: 51 | snprintf(buff, sizeof(buff), (": %d"), binding); 52 | return (strdup(buff)); 53 | } 54 | } 55 | 56 | /** 57 | * get_symbol_visibility - gets the visibility type 58 | * @visibility: visibility type of elf 59 | * Return: visibility type of elf 60 | */ 61 | char *get_symbol_visibility(unsigned int visibility) 62 | { 63 | switch (visibility) 64 | { 65 | case STV_DEFAULT: 66 | return ("DEFAULT"); 67 | case STV_INTERNAL: 68 | return ("INTERNAL"); 69 | case STV_HIDDEN: 70 | return ("HIDDEN"); 71 | case STV_PROTECTED: 72 | return ("PROTECTED"); 73 | default: 74 | abort(); 75 | } 76 | } 77 | 78 | /** 79 | * get_symbol_index_type - gets the symbol index type 80 | * @type: type of symbol 81 | * Return: symbol index type 82 | */ 83 | char *get_symbol_index_type(unsigned int type) 84 | { 85 | char buff[32]; 86 | 87 | switch (type) 88 | { 89 | case SHN_UNDEF: 90 | return ("UND"); 91 | case SHN_ABS: 92 | return ("ABS"); 93 | case SHN_COMMON: 94 | return ("COM"); 95 | default: 96 | if (type >= SHN_LOPROC && type <= SHN_HIPROC) 97 | sprintf(buff, "PRC[0x%04x]", type); 98 | else if (type >= SHN_LOOS && type <= SHN_HIOS) 99 | sprintf(buff, "OS [0x%04x]", type); 100 | else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE) 101 | sprintf(buff, "RSV[0x%04x]", type); 102 | else 103 | sprintf(buff, "%3d", type); 104 | break; 105 | } 106 | 107 | return (strdup(buff)); 108 | } 109 | -------------------------------------------------------------------------------- /0x06-readelf/src/validate_elf.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * elf_check_file - checks if the elf file is valid 5 | * @magic: magic string 6 | * 7 | * Return: on success: true , on Failure: false. 8 | */ 9 | bool elf_check_file(unsigned char *magic) 10 | { 11 | 12 | if (magic[0] != ELFMAG0) 13 | { 14 | /* printf("ELF Header EI_MAG0 incorrect.\n"); */ 15 | return (false); 16 | } 17 | if (magic[1] != ELFMAG1) 18 | { 19 | /* printf("ELF Header EI_MAG1 incorrect.\n"); */ 20 | return (false); 21 | } 22 | if (magic[2] != ELFMAG2) 23 | { 24 | /* printf("ELF Header EI_MAG2 incorrect.\n"); */ 25 | return (false); 26 | } 27 | if (magic[3] != ELFMAG3) 28 | { 29 | /* printf("ELF Header EI_MAG3 incorrect.\n"); */ 30 | return (false); 31 | } 32 | return (true); 33 | } 34 | 35 | /** 36 | * get_architecture - fetches the architecture of the elf file 37 | * @c: char 38 | * @arch: architecture - 32 /64 39 | * 40 | * Return: on success: true , on Failure: false. 41 | */ 42 | bool get_architecture(char c, int *arch) 43 | { 44 | if (c == ELFCLASS32) 45 | { 46 | *arch = 32; 47 | } else if (c == ELFCLASS64) 48 | { 49 | *arch = 64; 50 | } else 51 | return (false); 52 | return (true); 53 | } 54 | -------------------------------------------------------------------------------- /0x06-readelf/tests/checker.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | FILES="./tests/elf_files/*" 3 | i=0 4 | for f in $FILES 5 | do 6 | diff <(./$1-hreadelf $f) <(readelf -W -$2 $f) >/dev/null 7 | if [ $? -ne 0 ] 8 | then 9 | echo $f 10 | fi 11 | done 12 | -------------------------------------------------------------------------------- /0x06-readelf/tests/elf_files/jpeg.mod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x06-readelf/tests/elf_files/jpeg.mod -------------------------------------------------------------------------------- /0x06-readelf/tests/elf_files/libperl.so.5.18: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x06-readelf/tests/elf_files/libperl.so.5.18 -------------------------------------------------------------------------------- /0x06-readelf/tests/elf_files/netbsd32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x06-readelf/tests/elf_files/netbsd32 -------------------------------------------------------------------------------- /0x06-readelf/tests/elf_files/python.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x06-readelf/tests/elf_files/python.obj -------------------------------------------------------------------------------- /0x06-readelf/tests/elf_files/sftp-server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x06-readelf/tests/elf_files/sftp-server -------------------------------------------------------------------------------- /0x06-readelf/tests/elf_files/solaris32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x06-readelf/tests/elf_files/solaris32 -------------------------------------------------------------------------------- /0x06-readelf/tests/elf_files/sortix32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x06-readelf/tests/elf_files/sortix32 -------------------------------------------------------------------------------- /0x06-readelf/tests/elf_files/sparcbigendian32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x06-readelf/tests/elf_files/sparcbigendian32 -------------------------------------------------------------------------------- /0x06-readelf/tests/elf_files/ubuntu64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x06-readelf/tests/elf_files/ubuntu64 -------------------------------------------------------------------------------- /0x06-readelf/tests/elf_files/vgpreload_memcheck-x86-linux.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x06-readelf/tests/elf_files/vgpreload_memcheck-x86-linux.so -------------------------------------------------------------------------------- /0x07-nm_objdump/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc-4.8 2 | CFLAGS = -Wall -Werror -Wextra -pedantic -g 3 | 4 | _SRC = nm.c \ 5 | validate_elf.c \ 6 | elf_utils.c \ 7 | elf_utils1.c \ 8 | elf_utils2.c \ 9 | helper.c \ 10 | process_elf_header.c \ 11 | print_buffer.c \ 12 | process_elf_section_header.c \ 13 | process_elf_symbol_tables.c 14 | 15 | _SRC1 = objdump.c \ 16 | validate_elf.c \ 17 | elf_utils.c \ 18 | elf_utils1.c \ 19 | elf_utils2.c \ 20 | helper.c \ 21 | process_elf_header.c \ 22 | print_buffer.c \ 23 | process_elf_section_header.c 24 | 25 | 26 | SRC = $(patsubst %,$(SDIR)/%,$(_SRC)) 27 | 28 | SRC1 = $(patsubst %,$(SDIR)/%,$(_SRC1)) 29 | 30 | _OBJ = $(_SRC:.c=.o) 31 | OBJECTS = $(patsubst %,$(ODIR)/%,$(_OBJ)) 32 | 33 | _OBJ1 = $(_SRC1:.c=.o) 34 | OBJECTS1 = $(patsubst %,$(ODIR)/%,$(_OBJ1)) 35 | 36 | IDIR = ./inc 37 | SDIR = ./src 38 | ODIR = . 39 | 40 | OUTPUT = hnm 41 | OUTPUT1 = hobjdump 42 | 43 | $(ODIR)/%.o : $(SDIR)/%.c 44 | $(CC) $(CFLAGS) -c -o $@ $< -I$(IDIR) 45 | 46 | all : $(OUTPUT) $(OUTPUT1) 47 | 48 | $(OUTPUT) : $(OBJECTS) 49 | $(CC) -o $@ $^ $(LINKS) 50 | 51 | $(OUTPUT1) : $(OBJECTS1) 52 | $(CC) -o $@ $^ $(LINKS) 53 | 54 | .PHONY : clean 55 | 56 | clean : 57 | rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT1) $(OBJECTS1) 58 | 59 | re: $(OBJ) $(OBJ1) 60 | -------------------------------------------------------------------------------- /0x07-nm_objdump/README.md: -------------------------------------------------------------------------------- 1 | ## 0x07. C - ELF: nm/objdump 2 | ### System programming & Algorithm ― Linux programming 3 | 4 | nm.c - A program that reproduce the GNU nm command 5 | ``` 6 | Usage: hnm [objfile ...] 7 | ``` 8 | standard output, error output and status are exact same as nm -p 9 | 10 | objdump.c - A program that reproduce the GNU nmobjdump command 11 | ``` 12 | Usage: hobjdump [objfile ...] 13 | ``` 14 | standard output, error output and status are exact same as objdump -sf 15 | 16 | ## Useful Resources: 17 | * man elf(5), man readelf(1) 18 | * See also /usr/include/elf.h 19 | * [ELF wiki](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 20 | * [ELF](http://www.cs.stevens.edu/~jschauma/810/elf.html) 21 | * [The ELF Object File Format: Introduction ](http://www.linuxjournal.com/article/1059) 22 | * [The ELF Object File Format by Dissection](http://www.linuxjournal.com/node/1060/print) 23 | * [ELF_Tutorial](http://wiki.osdev.org/ELF_Tutorial#ELF_Data_Types) 24 | * [FILE Format](https://docs.oracle.com/cd/E19683-01/816-1386/6m7qcoblj/index.html#chapter6-73445) 25 | -------------------------------------------------------------------------------- /0x07-nm_objdump/src/elf_utils.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * get_byte_big_endian - fetches the bytes in big endian formatted data 5 | * @data: data to be fetched 6 | * @size: size of the data 7 | * 8 | * Return: the bytes in big endian format data. 9 | */ 10 | uint64_t get_byte_big_endian(uint64_t data, int size) 11 | { 12 | switch (size) 13 | { 14 | case 2: 15 | return (be16toh(data)); 16 | case 4: 17 | return (be32toh(data)); 18 | case 8: 19 | return (be64toh(data)); 20 | default: 21 | return (0); 22 | } 23 | } 24 | 25 | /** 26 | * get_byte_host - fetches the bytes 27 | * @data: data to be fetched 28 | * @size: size of the data 29 | * 30 | * Return: the data. 31 | */ 32 | uint64_t get_byte_host(uint64_t data, int __attribute__ ((unused)) size) 33 | { 34 | return (data); 35 | } 36 | 37 | 38 | /** 39 | * get_vma - gets the value with appropriate format and end string 40 | * @no: input no be formated. 41 | * @format: d - decimal, hex- hexadecimal 42 | * @end: end string f- file bytes , b -bytes 43 | * Return: formatted value 44 | */ 45 | char *get_vma(unsigned int no, char format, char end) 46 | { 47 | char buff[32]; 48 | 49 | if (format == 'd' && end == 'b') 50 | sprintf(buff, "%d (bytes)", no); 51 | else if (format == 'd' && end == 'f') 52 | sprintf(buff, "%d (bytes into file)", no); 53 | else if (format == 'd') 54 | sprintf(buff, "%d", no); 55 | else if (format == 'x') 56 | sprintf(buff, "0x%x", no); 57 | return (strdup(buff)); 58 | } 59 | 60 | 61 | /** 62 | * read_section- fetches the section 63 | * @sh: section header 64 | * @fd: file descriptor of input elf file 65 | * Return: string representation of the file 66 | */ 67 | char *read_section(int fd, ElfN_Shdr sh) 68 | { 69 | char *buff = malloc(sh.sh_size + 1); 70 | 71 | if (!buff) 72 | { 73 | printf("Failed to allocate\n"); 74 | } 75 | 76 | assert(buff != NULL); 77 | assert(lseek(fd, (off_t) sh.sh_offset, SEEK_SET) == 78 | (off_t) sh.sh_offset); 79 | assert(read(fd, (void *)buff, sh.sh_size) == (ssize_t) sh.sh_size); 80 | buff[sh.sh_size] = '\0'; 81 | return (buff); 82 | } 83 | 84 | /** 85 | * get_file_type - gets the file type of elf 86 | * @e_type: file type of elf 87 | * Return: file type of elf 88 | */ 89 | char *get_file_type(unsigned int e_type) 90 | { 91 | char buff[32]; 92 | 93 | switch (e_type) 94 | { 95 | case ET_NONE: 96 | return (strdup("NONE (None)")); 97 | case ET_REL: 98 | return (strdup("REL (Relocatable file)")); 99 | case ET_EXEC: 100 | return (strdup("EXEC (Executable file)")); 101 | case ET_DYN: 102 | return (strdup("DYN (Shared object file)")); 103 | case ET_CORE: 104 | return (strdup("CORE (Core file)")); 105 | default: 106 | if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC)) 107 | snprintf(buff, sizeof(buff), 108 | ("Processor Specific: (%x)"), e_type); 109 | else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS)) 110 | snprintf(buff, sizeof(buff), ("OS Specific: (%x)"), 111 | e_type); 112 | else 113 | snprintf(buff, sizeof(buff), (": %x"), e_type); 114 | return (strdup(buff)); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /0x07-nm_objdump/src/elf_utils2.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * get_arch_mach_name - fetches the architecture of the elf file 5 | * @e_machine: machine 6 | * Return: architecture of machine 7 | */ 8 | char *get_arch_mach_name(unsigned int e_machine) 9 | { 10 | if (e_machine == EM_386) 11 | return ("i386"); 12 | else if (e_machine == EM_X86_64) 13 | return ("i386:x86-64"); 14 | return ("UNKNOWN!"); 15 | } 16 | /** 17 | * get_file_format_name - fetches the file format of the elf file 18 | * @ehdr: elf header struct 19 | * Return: file format of elf 20 | */ 21 | char *get_file_format_name(ElfN_Ehdr ehdr) 22 | { 23 | if (ehdr.e_machine == EM_386) 24 | return ("i386"); 25 | else if (ehdr.e_machine == EM_X86_64) 26 | return ("x86-64"); 27 | return (ehdr.e_ident[EI_DATA] == ELFDATA2LSB ? "little" : "big"); 28 | } 29 | /** 30 | * get_flags - fetches the flags approriately based on elf file 31 | * @ehdr: elf header struct 32 | * @sh_tbl: sections structure 33 | * @fd: input file's file descriptor 34 | * Return: flags 35 | */ 36 | int get_flags(ElfN_Ehdr *ehdr, ElfN_Shdr sh_tbl[], int fd) 37 | { 38 | int flags = BFD_NO_FLAGS; 39 | 40 | if (ehdr->e_type == ET_EXEC) 41 | flags |= EXEC_P; 42 | if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN && 43 | elf_has_section_type(sh_tbl, ehdr->e_shnum, SHT_REL)) 44 | flags |= HAS_RELOC; 45 | if (!(flags & EXEC_P) && ehdr->e_type != ET_DYN && 46 | elf_has_section_type(sh_tbl, ehdr->e_shnum, SHT_RELA)) 47 | flags |= HAS_RELOC; 48 | if (ehdr->e_type != ET_EXEC && 49 | elf_has_section_type(sh_tbl, ehdr->e_shnum, SHT_DYNSYM)) 50 | flags |= DYNAMIC; 51 | if (elf_has_symbols(sh_tbl, ehdr->e_shnum, fd, ehdr->e_shstrndx)) 52 | flags |= HAS_SYMS; 53 | if (elf_has_section_type(sh_tbl, ehdr->e_shnum, SHT_HASH) || 54 | elf_has_section_type(sh_tbl, ehdr->e_shnum, SHT_GNU_HASH)) 55 | flags |= D_PAGED; 56 | return (flags); 57 | } 58 | -------------------------------------------------------------------------------- /0x07-nm_objdump/src/helper.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | /** 3 | * lenHelper - determines the no of digits in the hex of a number 4 | * @x: decimal number 5 | * Return: no of digits 6 | */ 7 | int lenHelper(uint64_t x) 8 | { 9 | if (x > 4026531840) 10 | return (9); 11 | if (x > 251658240) 12 | return (8); 13 | if (x > 15728640) 14 | return (7); 15 | if (x > 170335) 16 | return (6); 17 | if (x > 61476) 18 | return (5); 19 | if (x > 4096) 20 | return (4); 21 | return (1); 22 | } 23 | -------------------------------------------------------------------------------- /0x07-nm_objdump/src/nm.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * main - A program that takes the name of a elf file as a parameter and 5 | * displays the information contained in Symbol tables of an ELF file. 6 | * @argc: no of inputs. 7 | * @argv: inputs. 8 | * 9 | * Return: on success: 0 , on Failure: 1. 10 | */ 11 | int main(int argc, char *argv[]) 12 | { 13 | ElfN_Ehdr ehdr; 14 | int exit_status = 0, arch = 0; 15 | FILE *file; 16 | 17 | /* validate user input */ 18 | if (argc < 2) 19 | { 20 | printf("Usage: %s elf_filename\n", argv[0]); 21 | exit(1); 22 | } 23 | /* open the elf file */ 24 | file = fopen(argv[1], "rb"); 25 | if (file) 26 | { 27 | if (fread(ehdr.e_ident, EI_NIDENT, 1, file) && 28 | elf_check_file(ehdr.e_ident)) 29 | { 30 | get_architecture(ehdr.e_ident[EI_CLASS], &arch); 31 | if (!read_elf_symbol_table_N(&ehdr, file, arch)) 32 | fprintf(stderr, "%s: %s: no symbols\n", argv[0], argv[1]); 33 | } else 34 | printf("%s: %s\n", E, argv[0]); 35 | exit_status = 1; 36 | /* finally close the file*/ 37 | fclose(file); 38 | } else 39 | { 40 | printf("%s: Error: '%s': No such file\n", argv[0], argv[1]); 41 | exit_status = 1; 42 | } 43 | return (exit_status); 44 | } 45 | -------------------------------------------------------------------------------- /0x07-nm_objdump/src/objdump.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * main - A program that takes the name of a elf file as a parameter and 5 | * displays the information contained in Symbol tables of an ELF file. 6 | * @argc: no of inputs. 7 | * @argv: inputs. 8 | * 9 | * Return: on success: 0 , on Failure: 1. 10 | */ 11 | int main(int argc, char *argv[]) 12 | { 13 | ElfN_Ehdr ehdr; 14 | int exit_status = 0, arch = 0; 15 | FILE *file; 16 | 17 | /* validate user input */ 18 | if (argc < 2) 19 | { 20 | printf("Usage: %s elf_filename\n", argv[0]); 21 | exit(1); 22 | } 23 | /* open the elf file */ 24 | file = fopen(argv[1], "rb"); 25 | if (file) 26 | { 27 | if (fread(ehdr.e_ident, EI_NIDENT, 1, file) && 28 | elf_check_file(ehdr.e_ident)) 29 | { 30 | get_architecture(ehdr.e_ident[EI_CLASS], &arch); 31 | read_elf_section_header_N(&ehdr, file, arch, argv[1]); 32 | } else 33 | printf("%s: %s\n", E, argv[0]); 34 | exit_status = 1; 35 | /* finally close the file*/ 36 | fclose(file); 37 | } else 38 | { 39 | printf("%s: Error: '%s': No such file\n", argv[0], argv[1]); 40 | exit_status = 1; 41 | } 42 | return (exit_status); 43 | } 44 | -------------------------------------------------------------------------------- /0x07-nm_objdump/src/print_buffer.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * print_char - Prints the char 5 | * @c: character to be printed 6 | * Return: no of bytes printed 7 | */ 8 | int print_char(char c) 9 | { 10 | return (write(1, &c, 1)); 11 | } 12 | /** 13 | * char_print_hex - Prints the char in hex 14 | * @n: number to be printed 15 | */ 16 | void char_print_hex(char n) 17 | { 18 | int first = (int)((n & 0xf0) >> 4); 19 | int second = (int)(n & 0x0f); 20 | 21 | if (first > 9) 22 | { 23 | print_char('a' + (first - 10)); 24 | } else 25 | { 26 | print_char('0' + first); 27 | } 28 | if (second > 9) 29 | { 30 | print_char('a' + (second - 10)); 31 | } else 32 | { 33 | print_char('0' + second); 34 | } 35 | } 36 | /** 37 | * print_int_hex - Prints the number in hex 38 | * @n: number to be printed 39 | */ 40 | void print_int_hex(int n) 41 | { 42 | int mask; 43 | int n_copy = n, count = 0, i = 0; 44 | int prints[4] = { 0, 0, 0, 0 }; 45 | 46 | while (n_copy > 0) 47 | { 48 | n_copy /= 256; 49 | count++; 50 | } 51 | 52 | for (; count >= 0; count--) 53 | { 54 | mask = 0xff; 55 | for (i = 0; i < count; i++) 56 | mask *= 0x100; 57 | prints[3 - count] = (n & mask); 58 | for (i = 0; i < count; i++) 59 | prints[3 - count] = (prints[3 - count] >> 8); 60 | } 61 | for (i = 0; i < 4; i++) 62 | { 63 | char_print_hex((char)prints[i]); 64 | } 65 | } 66 | /** 67 | * print_buffer - Prints the buffer dump 68 | * @b: contents to be dumped 69 | * @size: size of the contents 70 | * @address: offset of the content 71 | */ 72 | void print_buffer(char *b, int size, uint64_t address) 73 | { 74 | uint64_t end = address + size; 75 | int currpos = 0, currrow = 0, c = 0, padding = lenHelper(address); 76 | 77 | if (padding < 4) 78 | padding = 4; 79 | while (currpos < size) 80 | { 81 | printf(" %0*lx", padding, address); 82 | fflush(stdout); 83 | do { 84 | if (currpos % 4 == 0) 85 | print_char(' '); 86 | if (currpos > size) 87 | { 88 | SPACE; 89 | } 90 | else 91 | { 92 | if (address < end) 93 | char_print_hex(*(b + currpos)); 94 | else 95 | SPACE; 96 | } 97 | currpos++; 98 | address++; 99 | } while (currpos % 16 != 0); 100 | SPACE; 101 | currpos = currrow * 16; 102 | do { 103 | (isprint(*(b + currpos))) ? print_char(*(b + currpos)) : print_char('.'); 104 | currpos++; 105 | c++; 106 | } while (currpos % 16 != 0 && currpos < size); 107 | while (c++ < 16) 108 | print_char(' '); 109 | c = 0; 110 | currrow++; 111 | print_char('\n'); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /0x07-nm_objdump/src/process_elf_header.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * read_elf_header_32 - fills the ehdr with suitable(32) architecture data 5 | * @ehdr: elf header structure 6 | * @file: input file 7 | */ 8 | void read_elf_header_32(ElfN_Ehdr *ehdr, FILE *file) 9 | { 10 | ssize_t n; 11 | Elf32_Ehdr ehdr32; 12 | uint64_t (*get_byte)(uint64_t, int); 13 | 14 | get_byte = (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) ? get_byte_big_endian 15 | : get_byte_host; 16 | n = fread(&ehdr32.e_type, sizeof(ehdr32) - EI_NIDENT, 1, file); 17 | if (n != 1) 18 | exit(EXIT_FAILURE); 19 | 20 | ehdr->e_type = GET_BYTE(ehdr32.e_type); 21 | ehdr->e_machine = GET_BYTE(ehdr32.e_machine); 22 | ehdr->e_version = GET_BYTE(ehdr32.e_version); 23 | ehdr->e_entry = GET_BYTE(ehdr32.e_entry); 24 | ehdr->e_phoff = GET_BYTE(ehdr32.e_phoff); 25 | ehdr->e_shoff = GET_BYTE(ehdr32.e_shoff); 26 | ehdr->e_flags = GET_BYTE(ehdr32.e_flags); 27 | ehdr->e_ehsize = GET_BYTE(ehdr32.e_ehsize); 28 | ehdr->e_phentsize = GET_BYTE(ehdr32.e_phentsize); 29 | ehdr->e_phnum = GET_BYTE(ehdr32.e_phnum); 30 | ehdr->e_shentsize = GET_BYTE(ehdr32.e_shentsize); 31 | ehdr->e_shnum = GET_BYTE(ehdr32.e_shnum); 32 | ehdr->e_shstrndx = GET_BYTE(ehdr32.e_shstrndx); 33 | } 34 | 35 | /** 36 | * read_elf_header_64 - fills the ehdr with suitable(64) architecture data 37 | * @ehdr: elf header structure 38 | * @file: input file 39 | */ 40 | void read_elf_header_64(ElfN_Ehdr *ehdr, FILE *file) 41 | { 42 | uint64_t (*get_byte)(uint64_t, int); 43 | ssize_t n; 44 | Elf64_Ehdr ehdr64; 45 | 46 | get_byte = (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) ? get_byte_big_endian 47 | : get_byte_host; 48 | n = fread(&ehdr64.e_type, sizeof(ehdr64) - EI_NIDENT, 1, file); 49 | if (n != 1) 50 | exit(EXIT_FAILURE); 51 | 52 | ehdr->e_type = GET_BYTE(ehdr64.e_type); 53 | ehdr->e_machine = GET_BYTE(ehdr64.e_machine); 54 | ehdr->e_version = GET_BYTE(ehdr64.e_version); 55 | ehdr->e_entry = GET_BYTE(ehdr64.e_entry); 56 | ehdr->e_phoff = GET_BYTE(ehdr64.e_phoff); 57 | ehdr->e_shoff = GET_BYTE(ehdr64.e_shoff); 58 | ehdr->e_flags = GET_BYTE(ehdr64.e_flags); 59 | ehdr->e_ehsize = GET_BYTE(ehdr64.e_ehsize); 60 | ehdr->e_phentsize = GET_BYTE(ehdr64.e_phentsize); 61 | ehdr->e_phnum = GET_BYTE(ehdr64.e_phnum); 62 | ehdr->e_shentsize = GET_BYTE(ehdr64.e_shentsize); 63 | ehdr->e_shnum = GET_BYTE(ehdr64.e_shnum); 64 | ehdr->e_shstrndx = GET_BYTE(ehdr64.e_shstrndx); 65 | } 66 | -------------------------------------------------------------------------------- /0x07-nm_objdump/src/validate_elf.c: -------------------------------------------------------------------------------- 1 | #include "readelf.h" 2 | 3 | /** 4 | * elf_check_file - checks if the elf file is valid 5 | * @magic: magic string 6 | * 7 | * Return: on success: true , on Failure: false. 8 | */ 9 | bool elf_check_file(unsigned char *magic) 10 | { 11 | 12 | if (magic[0] != ELFMAG0) 13 | { 14 | /* printf("ELF Header EI_MAG0 incorrect.\n"); */ 15 | return (false); 16 | } 17 | if (magic[1] != ELFMAG1) 18 | { 19 | /* printf("ELF Header EI_MAG1 incorrect.\n"); */ 20 | return (false); 21 | } 22 | if (magic[2] != ELFMAG2) 23 | { 24 | /* printf("ELF Header EI_MAG2 incorrect.\n"); */ 25 | return (false); 26 | } 27 | if (magic[3] != ELFMAG3) 28 | { 29 | /* printf("ELF Header EI_MAG3 incorrect.\n"); */ 30 | return (false); 31 | } 32 | return (true); 33 | } 34 | 35 | /** 36 | * get_architecture - fetches the architecture of the elf file 37 | * @c: char 38 | * @arch: architecture - 32 /64 39 | * 40 | * Return: on success: true , on Failure: false. 41 | */ 42 | bool get_architecture(char c, int *arch) 43 | { 44 | if (c == ELFCLASS32) 45 | { 46 | *arch = 32; 47 | } else if (c == ELFCLASS64) 48 | { 49 | *arch = 64; 50 | } else 51 | return (false); 52 | return (true); 53 | } 54 | -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/0-checker.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | FILES="./tests/elf_files/*" 3 | i=0 4 | for f in $FILES 5 | do 6 | diff <(./hnm $f) <(nm -p $f) 7 | if [ $? -ne 0 ] 8 | then 9 | echo $f 10 | fi 11 | done 12 | -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/1-checker.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | FILES="./tests/elf_files/*" 3 | i=0 4 | for f in $FILES 5 | do 6 | diff <(./hobjdump $f) <(objdump -sf $f) > /dev/null 7 | if [ $? -ne 0 ] 8 | then 9 | echo $f 10 | fi 11 | done 12 | -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/elf_files/jpeg.mod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x07-nm_objdump/tests/elf_files/jpeg.mod -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/elf_files/libperl.so.5.18: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x07-nm_objdump/tests/elf_files/libperl.so.5.18 -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/elf_files/netbsd32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x07-nm_objdump/tests/elf_files/netbsd32 -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/elf_files/python.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x07-nm_objdump/tests/elf_files/python.obj -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/elf_files/sftp-server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x07-nm_objdump/tests/elf_files/sftp-server -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/elf_files/solaris32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x07-nm_objdump/tests/elf_files/solaris32 -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/elf_files/sortix32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x07-nm_objdump/tests/elf_files/sortix32 -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/elf_files/sparcbigendian32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x07-nm_objdump/tests/elf_files/sparcbigendian32 -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/elf_files/ubuntu64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x07-nm_objdump/tests/elf_files/ubuntu64 -------------------------------------------------------------------------------- /0x07-nm_objdump/tests/elf_files/vgpreload_memcheck-x86-linux.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SravanthiSinha/holbertonschool-linux_programming/b1d1eb1d45a52fe8e3e043378b86e777d0ba7536/0x07-nm_objdump/tests/elf_files/vgpreload_memcheck-x86-linux.so -------------------------------------------------------------------------------- /0x08-malloc/0-main.c: -------------------------------------------------------------------------------- 1 | #include "malloc.h" 2 | #include 3 | #include 4 | 5 | typedef struct rec 6 | { 7 | int i; 8 | float PI; 9 | char A; 10 | } RECORD; 11 | 12 | /** 13 | * main - Program entry point 14 | * 15 | * Return: EXIT_SUCCESS or EXIT_FAILURE 16 | */ 17 | int main(void) 18 | { 19 | struct rec *ptr_one; 20 | 21 | ptr_one = (struct rec *)naive_malloc(sizeof(struct rec)); 22 | ptr_one->i = 10; 23 | ptr_one->PI = 3.14; 24 | ptr_one->A = 'a'; 25 | 26 | printf("First value: %d\n", ptr_one->i); 27 | printf("Second value: %f\n", ptr_one->PI); 28 | printf("Third value: %c\n", ptr_one->A); 29 | 30 | return (0); 31 | } 32 | -------------------------------------------------------------------------------- /0x08-malloc/1-main.c: -------------------------------------------------------------------------------- 1 | #include "malloc.h" 2 | #include 3 | #include 4 | 5 | typedef struct rec 6 | { 7 | int i; 8 | float PI; 9 | char A; 10 | } RECORD; 11 | 12 | /** 13 | * main - Program entry point 14 | * 15 | * Return: EXIT_SUCCESS or EXIT_FAILURE 16 | */ 17 | int main(void) 18 | { 19 | struct rec *ptr_one; 20 | 21 | ptr_one = (struct rec *)_malloc(sizeof(struct rec)); 22 | ptr_one->i = 10; 23 | ptr_one->PI = 3.14; 24 | ptr_one->A = 'a'; 25 | 26 | printf("First value: %d\n", ptr_one->i); 27 | printf("Second value: %f\n", ptr_one->PI); 28 | printf("Third value: %c\n", ptr_one->A); 29 | 30 | return (0); 31 | } 32 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/1-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * main - Program entry point 7 | * 8 | * Return: EXIT_SUCCESS or EXIT_FAILURE 9 | */ 10 | int main(void) 11 | { 12 | char *ptr; 13 | 14 | printf("Starting break is %p\n", sbrk(0)); 15 | ptr = sbrk(1); 16 | if (ptr == (void *)-1) 17 | { 18 | return (1); 19 | } 20 | printf("Break after extension is %p\n", sbrk(0)); 21 | *ptr = 'H'; 22 | printf("Address of our char is %p\n", ptr); 23 | printf("Value at this address is '%c'\n", *ptr); 24 | return (0); 25 | } 26 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/2-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *naive_malloc(size_t size); 7 | 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | char *str; 16 | int i; 17 | 18 | printf("Starting break is %p\n", sbrk(0)); 19 | 20 | for (i = 0; i < 10; i++) 21 | { 22 | str = naive_malloc(10); 23 | strcpy(str, "Holberton"); 24 | str[9] = '\0'; 25 | printf("%p: %s\n", (void *)str, str); 26 | } 27 | 28 | printf("Final break is %p\n", sbrk(0)); 29 | return (EXIT_SUCCESS); 30 | } 31 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/2-main_malloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /** 7 | * main - Program entry point 8 | * 9 | * Return: EXIT_SUCCESS or EXIT_FAILURE 10 | */ 11 | int main(void) 12 | { 13 | char *str; 14 | int i; 15 | 16 | printf("Starting break is %p\n", sbrk(0)); 17 | 18 | for (i = 0; i < 10; i++) 19 | { 20 | str = malloc(10); 21 | strcpy(str, "Holberton"); 22 | str[9] = '\0'; 23 | printf("%p: %s, ", (void *)str, str); 24 | printf("program break: %p\n", sbrk(0)); 25 | 26 | } 27 | 28 | printf("Final break is %p\n", sbrk(0)); 29 | return (EXIT_SUCCESS); 30 | } 31 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/2-naive_malloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * naive_malloc - malloc with no extra byte is allocated and everything is 5 | * contiguous and packed in memory 6 | * @size: No of bytes to be allocated 7 | * Return: A pointer to the allocated memory 8 | */ 9 | void *naive_malloc(size_t size) 10 | { 11 | void *previous_break; 12 | 13 | previous_break = sbrk(size); 14 | /* check for error */ 15 | if (previous_break == (void *)-1) 16 | { 17 | /* on error malloc returns NULL */ 18 | return (NULL); 19 | } 20 | return (previous_break); 21 | } 22 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/3-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *naive_malloc_header(size_t size); 7 | 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | char *str; 16 | int i; 17 | 18 | printf("Starting break is %p\n", sbrk(0)); 19 | 20 | for (i = 0; i < 10; i++) 21 | { 22 | void *chunk; 23 | 24 | str = naive_malloc_header(10); 25 | strcpy(str, "Holberton"); 26 | str[21] = '\0'; 27 | printf("%p: %s, ", (void *)str, str); 28 | chunk = (void *)(str - sizeof(size_t)); 29 | printf("chunk starting at address %p, ", (void *)chunk); 30 | printf("chunk size is %lu\n", *((size_t *) chunk)); 31 | } 32 | 33 | printf("Final break is %p\n", sbrk(0)); 34 | return (EXIT_SUCCESS); 35 | } 36 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/3-naive_malloc_header.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * naive_malloc_header - malloc which allocates more space than asked 5 | * in order to store a small header at the beginning of the allocated chunk. 6 | * @size: No of bytes to be allocated 7 | * Return: A pointer to the allocated memory 8 | */ 9 | void *naive_malloc_header(size_t size) 10 | { 11 | void *previous_break; 12 | size_t header_size = sizeof(size_t); 13 | 14 | previous_break = sbrk(header_size + size); 15 | /* check for error */ 16 | if (previous_break == (void *)-1) 17 | { 18 | /* on error malloc returns NULL */ 19 | return (NULL); 20 | } 21 | 22 | *((char *)previous_break) = header_size + size; 23 | return ((void *)((char *)previous_break + header_size)); 24 | } 25 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/4-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *naive_malloc_page(size_t size); 7 | 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | char *str; 16 | int i; 17 | 18 | printf("Starting break is %p\n", sbrk(0)); 19 | 20 | for (i = 0; i < 10; i++) 21 | { 22 | void *chunk; 23 | 24 | str = naive_malloc_page(10); 25 | strcpy(str, "Holberton"); 26 | str[21] = '\0'; 27 | printf("%p: %s, ", (void *)str, str); 28 | chunk = (void *)(str - sizeof(size_t)); 29 | printf("chunk addr: %p, ", (void *)chunk); 30 | printf("size: %lu, ", *((size_t *) chunk)); 31 | printf("break: %p\n", sbrk(0)); 32 | } 33 | 34 | printf("Final break is %p\n", sbrk(0)); 35 | return (EXIT_SUCCESS); 36 | } 37 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/4-main_beyond.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *naive_malloc_page(size_t size); 7 | 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | char *str; 16 | int i; 17 | 18 | printf("Starting break is %p\n", sbrk(0)); 19 | 20 | for (i = 0; i < 10; i++) 21 | { 22 | void *chunk; 23 | 24 | str = naive_malloc_page(1016); 25 | strcpy(str, "Holberton"); 26 | str[21] = '\0'; 27 | printf("%p: %s, ", (void *)str, str); 28 | chunk = (void *)(str - sizeof(size_t)); 29 | printf("chunk addr: %p, ", (void *)chunk); 30 | printf("size: %lu, ", *((size_t *) chunk)); 31 | printf("break: %p\n", sbrk(0)); 32 | } 33 | 34 | printf("Final break is %p\n", sbrk(0)); 35 | return (EXIT_SUCCESS); 36 | } 37 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/4-naive_malloc_page.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static void *heap_start; 5 | static size_t no_chunks = 0; 6 | 7 | /** 8 | * naive_malloc_page - malloc which keep track of the address of the first 9 | * chunk in chain and number of chunks used 10 | * @size: No of bytes to be allocated 11 | * Return: A pointer to the allocated memory 12 | */ 13 | void *naive_malloc_page(size_t size) 14 | { 15 | void *previous_break = NULL; 16 | size_t header_size = sizeof(size_t), unused_chunk, used_chunk; 17 | size_t i = 0; 18 | 19 | if (no_chunks == 0) 20 | { 21 | /*The first time our malloc is called, we need to extend the program break by the virtual memory page size. */ 22 | heap_start = sbrk(0); 23 | unused_chunk = (size_t) sysconf(_SC_PAGESIZE); 24 | previous_break = sbrk(unused_chunk); 25 | if (previous_break == (void *)-1) 26 | return (NULL); 27 | /*set used bytes */ 28 | *((size_t *) previous_break) = header_size + size; 29 | /* setting unused chunk */ 30 | *((size_t *) ((char *)previous_break + header_size + size)) = 31 | unused_chunk - size - header_size; 32 | no_chunks++; 33 | return ((void *)((char *)previous_break + header_size)); 34 | } 35 | previous_break = heap_start; 36 | for (i = 0; i < no_chunks; i++) 37 | { 38 | used_chunk = *((size_t *) previous_break); 39 | previous_break = (void *)((char *)previous_break + used_chunk); 40 | unused_chunk = *((size_t *) previous_break); 41 | } 42 | /*set used bytes */ 43 | *((size_t *) previous_break) = header_size + size; 44 | previous_break = (void *)((char *)previous_break + header_size); 45 | /* setting unused chunk */ 46 | *((size_t *) ((char *)previous_break + size)) = 47 | unused_chunk - header_size - size; 48 | 49 | no_chunks++; 50 | return (previous_break); 51 | } 52 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/5-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *naive_malloc_extend(size_t size); 7 | 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | char *str; 16 | int i; 17 | 18 | printf("Starting break is %p\n", sbrk(0)); 19 | 20 | for (i = 0; i < 10; i++) 21 | { 22 | void *chunk; 23 | 24 | str = naive_malloc_extend(1016); 25 | strcpy(str, "Holberton"); 26 | str[21] = '\0'; 27 | printf("%p: %s, ", (void *)str, str); 28 | chunk = (void *)(str - sizeof(size_t)); 29 | printf("chunk addr: %p, ", (void *)chunk); 30 | printf("size: %lu, ", *((size_t *) chunk)); 31 | printf("break: %p\n", sbrk(0)); 32 | } 33 | 34 | printf("Final break is %p\n", sbrk(0)); 35 | return (EXIT_SUCCESS); 36 | } 37 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/5-naive_malloc_extend.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static void *heap_start; 5 | static size_t no_chunks = 0; 6 | 7 | /** 8 | * naive_malloc_extend - malloc which keep track of the address of the first 9 | * chunk in chain and number of chunks useda and allocate more space when a 10 | * page is full 11 | * @size: No of bytes to be allocated 12 | * Return: A pointer to the allocated memory 13 | */ 14 | void *naive_malloc_extend(size_t size) 15 | { 16 | void *previous_break = NULL; 17 | size_t header_size = sizeof(size_t), unused_chunk, used_chunk; 18 | size_t i = 0; 19 | 20 | if (no_chunks == 0) 21 | { 22 | /*The first time our malloc is called, we need to extend the program break by the virtual memory page size. */ 23 | heap_start = sbrk(0); 24 | unused_chunk = (size_t) sysconf(_SC_PAGESIZE); 25 | previous_break = sbrk(unused_chunk); 26 | if (previous_break == (void *)-1) 27 | return (NULL); 28 | /*set used bytes */ 29 | *((size_t *) previous_break) = header_size + size; 30 | /* setting unused chunk */ 31 | *((size_t *) ((char *)previous_break + header_size + size)) = 32 | unused_chunk - header_size - size; 33 | no_chunks++; 34 | return ((void *)((char *)previous_break + header_size)); 35 | } 36 | previous_break = heap_start; 37 | for (i = 0; i < no_chunks; i++) 38 | { 39 | used_chunk = *((size_t *) previous_break); 40 | previous_break = (void *)((char *)previous_break + used_chunk); 41 | unused_chunk = *((size_t *) previous_break); 42 | } 43 | /*set used bytes */ 44 | *((size_t *) previous_break) = header_size + size; 45 | previous_break = (void *)((char *)previous_break + header_size); 46 | /* setting unused chunk */ 47 | if (unused_chunk <= (header_size + size)) 48 | { 49 | sbrk((size_t) sysconf(_SC_PAGESIZE)); 50 | *((size_t *) ((char *)previous_break + size)) = 51 | unused_chunk + (size_t) sysconf(_SC_PAGESIZE) - 52 | header_size - size; 53 | } else 54 | *((size_t *) ((char *)previous_break + size)) = 55 | unused_chunk - header_size - size; 56 | no_chunks++; 57 | return (previous_break); 58 | } 59 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/6-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *naive_malloc_align(size_t size); 7 | 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | char *str; 16 | int i; 17 | 18 | printf("Starting break is %p\n", sbrk(0)); 19 | 20 | for (i = 0; i < 10; i++) 21 | { 22 | void *chunk; 23 | 24 | str = naive_malloc_align(10); 25 | strcpy(str, "Holberton"); 26 | str[21] = '\0'; 27 | printf("%p: %s, ", (void *)str, str); 28 | chunk = (void *)(str - sizeof(size_t)); 29 | printf("chunk addr: %p, ", (void *)chunk); 30 | printf("size: %lu, ", *((size_t *) chunk)); 31 | printf("break: %p\n", sbrk(0)); 32 | } 33 | 34 | printf("Final break is %p\n", sbrk(0)); 35 | return (EXIT_SUCCESS); 36 | } 37 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/6-naive_malloc_align.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static void *heap_start; 5 | static size_t no_chunks = 0; 6 | 7 | /** 8 | * get_next_multiple - returns a number rounded up to the next multiple of 8 9 | * @size: No of bytes to be allocated 10 | * Return: A pointer to the aligned address 11 | */ 12 | size_t get_next_multiple(size_t size) 13 | { 14 | int n = size; 15 | 16 | /*We allocate extra space when the size is not a multiple of 8 */ 17 | if (n % 8) 18 | n = n + (8 - n % 8); 19 | return (n); 20 | } 21 | 22 | /** 23 | * naive_malloc_align - malloc which keep track of the address of the first 24 | * chunk in chain and number of chunks useda and allocate more space when a 25 | * page is full 26 | * @size: No of bytes to be allocated 27 | * Return: A pointer to the allocated memory that is aligned for any type 28 | */ 29 | void *naive_malloc_align(size_t size) 30 | { 31 | void *previous_break = NULL; 32 | size_t header_size = sizeof(size_t), unused_chunk, used_chunk; 33 | size_t i = 0; 34 | 35 | size = get_next_multiple(size); 36 | if (no_chunks == 0) 37 | { 38 | /*The first time our malloc is called, we need to extend the program break by the virtual memory page size. */ 39 | heap_start = sbrk(0); 40 | unused_chunk = (size_t) sysconf(_SC_PAGESIZE); 41 | previous_break = sbrk(unused_chunk); 42 | if (previous_break == (void *)-1) 43 | return (NULL); 44 | /*set used bytes */ 45 | *((size_t *) previous_break) = header_size + size; 46 | /* setting unused chunk */ 47 | *((size_t *) ((char *)previous_break + header_size + size)) = 48 | unused_chunk - header_size - size; 49 | no_chunks++; 50 | return ((void *)((char *)previous_break + header_size)); 51 | } 52 | previous_break = heap_start; 53 | for (i = 0; i < no_chunks; i++) 54 | { 55 | used_chunk = *((size_t *) previous_break); 56 | previous_break = (void *)((char *)previous_break + used_chunk); 57 | unused_chunk = *((size_t *) previous_break); 58 | } 59 | /*set used bytes */ 60 | *((size_t *) previous_break) = header_size + size; 61 | previous_break = (void *)((char *)previous_break + header_size); 62 | /* setting unused chunk */ 63 | if (unused_chunk <= (header_size + size)) 64 | { 65 | sbrk((size_t) sysconf(_SC_PAGESIZE)); 66 | *((size_t *) ((char *)previous_break + size)) = 67 | unused_chunk + (size_t) sysconf(_SC_PAGESIZE) - 68 | header_size - size; 69 | } else 70 | *((size_t *) ((char *)previous_break + size)) = 71 | unused_chunk - header_size - size; 72 | no_chunks++; 73 | return (previous_break); 74 | } 75 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/7-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *naive_malloc(size_t size); 7 | 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | char *str; 16 | int i; 17 | 18 | printf("Starting break is %p\n", sbrk(0)); 19 | 20 | for (i = 0; i < 10; i++) 21 | { 22 | void *chunk; 23 | 24 | str = naive_malloc(10); 25 | strcpy(str, "Holberton"); 26 | str[21] = '\0'; 27 | printf("%p: %s, ", (void *)str, str); 28 | chunk = (void *)(str - sizeof(size_t)); 29 | printf("chunk addr: %p, ", (void *)chunk); 30 | printf("size: %lu, ", *((size_t *) chunk)); 31 | printf("break: %p\n", sbrk(0)); 32 | } 33 | 34 | printf("Final break is %p\n", sbrk(0)); 35 | return (EXIT_SUCCESS); 36 | } 37 | -------------------------------------------------------------------------------- /0x08-malloc/EYNTK/7-naive_malloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define PAGE_SIZE ((size_t) sysconf(_SC_PAGESIZE)) 4 | #define align8(x) (x % 8) ? (x + (8 - x % 8)) : x 5 | 6 | static void *heap_start; 7 | 8 | /** 9 | * naive_malloc - malloc which keep track of the address of the first 10 | * chunk in chain and also allocate more space when a page is full 11 | * @size: No of bytes to be allocated 12 | * Return: A pointer to the allocated memory that is aligned for any type 13 | */ 14 | void *naive_malloc(size_t size) 15 | { 16 | void *previous_break = NULL; 17 | size_t header_size = sizeof(size_t), unused_chunk, used_chunk, chunk; 18 | 19 | if (size <= 0) 20 | return (NULL); 21 | size = align8(size); 22 | chunk = header_size + size; 23 | if (heap_start == NULL) 24 | { 25 | heap_start = sbrk(0); 26 | unused_chunk = PAGE_SIZE; 27 | previous_break = sbrk(unused_chunk); 28 | if (previous_break == (void *)-1) 29 | return (NULL); 30 | *((size_t *) previous_break) = chunk; /*set used bytes */ 31 | *((size_t *) ((char *)previous_break + chunk)) = unused_chunk - chunk; /* setting unused chunk */ 32 | return ((void *)((char *)previous_break + header_size)); 33 | } 34 | previous_break = heap_start; 35 | do 36 | { 37 | used_chunk = *((size_t *) previous_break); 38 | previous_break = (void *)((char *)previous_break + used_chunk); 39 | unused_chunk = *((size_t *) previous_break); 40 | } 41 | while (unused_chunk <= chunk); 42 | *((size_t *) previous_break) = chunk; 43 | previous_break = (void *)((char *)previous_break + header_size); 44 | if (unused_chunk <= chunk) 45 | { 46 | if (sbrk(PAGE_SIZE) == (void *)-1) 47 | return (NULL); 48 | *((size_t *) ((char *)previous_break + size)) = 49 | unused_chunk + PAGE_SIZE - chunk; 50 | } else 51 | *((size_t *) ((char *)previous_break + size)) = 52 | unused_chunk - chunk; 53 | return (previous_break); 54 | } 55 | -------------------------------------------------------------------------------- /0x08-malloc/README.md: -------------------------------------------------------------------------------- 1 | # 0x08. C - malloc 2 | 3 | #### System programming & Algorithm ― Linux programming 4 | 5 | 6 | ## Development details 7 | The project concepts are explored with examples in EYNTK folder 8 | 9 | * malloc.h - includes all the library functions and user-defined ones 10 | 11 | * naive_malloc.c - Basic naive_malloc which returns a pointer to the allocated memory that is suitably aligned for any kind of variable 12 | 13 | 14 | # Useful Resources: 15 | 16 | * [[EYNTK] Writing your own dynamic allocation library](https://intranet.hbtn.io/concepts/80) 17 | 18 | * The manual pages of sbrk/brk and malloc. 19 | 20 | * [Hack the Virtual Memory: malloc, the heap & the program break](https://blog.holbertonschool.com/hack-the-virtual-memory-malloc-the-heap-the-program-break/) 21 | -------------------------------------------------------------------------------- /0x08-malloc/malloc.c: -------------------------------------------------------------------------------- 1 | #include "malloc.h" 2 | 3 | void *global_base = NULL; 4 | 5 | /** 6 | * find_block - A function that looks for a free block in the heap 7 | * @last: pointer to the last block of the heap 8 | * @size: No of bytes requested. 9 | * Return: pointer to the avilable free block. 10 | */ 11 | t_block find_block(t_block *last, size_t size) 12 | { 13 | t_block current = global_base; 14 | 15 | while (current && !(current->free && current->size >= size)) 16 | { 17 | *last = current; 18 | current = current->next; 19 | } 20 | return (current); 21 | } 22 | 23 | /** 24 | * extend_heap - A function that extends the heap 25 | * @last: pointer to the last block of the heap 26 | * @s: No of bytes requested. 27 | * Return: current block to be used. 28 | */ 29 | t_block extend_heap(t_block last, size_t s) 30 | { 31 | t_block current; 32 | 33 | current = sbrk(0); 34 | if (sbrk(BLOCK_SIZE + s) == (void *)-1) 35 | { 36 | perror("sbrk failed"); 37 | return (NULL); 38 | } 39 | current->size = s; 40 | current->next = NULL; 41 | if (last) 42 | last->next = current; 43 | current->free = 0; 44 | return (current); 45 | } 46 | 47 | /** 48 | * split_block - A function that splits the block based on the requested size. 49 | * @current: current block to be allocated 50 | * @s: No of bytes requested. 51 | */ 52 | void split_block(t_block current, size_t s) 53 | { 54 | t_block new; 55 | 56 | new = (t_block) (current->data + s); 57 | new->size = current->size - s - BLOCK_SIZE; 58 | new->next = current->next; 59 | new->free = 1; 60 | current->size = s; 61 | current->next = new; 62 | } 63 | 64 | /** 65 | * _malloc - A function which allocates size bytes and returns a pointer to the 66 | * allocated memory. 67 | * @size: No of bytes to be allocated 68 | * Return: On success - A pointer to the allocated memory that is suitably 69 | * aligned for any kind of variable 70 | * On failure - NULL 71 | */ 72 | void *_malloc(size_t size) 73 | { 74 | t_block current, last; 75 | size_t s; 76 | 77 | s = align8(size); 78 | if (global_base) 79 | { 80 | /* First find a block */ 81 | last = global_base; 82 | current = find_block(&last, s); 83 | if (current) 84 | { 85 | /* can we split */ 86 | if ((current->size - s) >= (BLOCK_SIZE + 8)) 87 | split_block(current, s); 88 | current->free = 0; 89 | } else 90 | { 91 | /* No fitting block , extend the heap */ 92 | current = extend_heap(last, s); 93 | if (!current) 94 | return (NULL); 95 | } 96 | } else 97 | { 98 | /* first time */ 99 | current = extend_heap(NULL, s); 100 | if (!current) 101 | return (NULL); 102 | global_base = current; 103 | } 104 | return (current->data); 105 | } 106 | -------------------------------------------------------------------------------- /0x08-malloc/malloc.h: -------------------------------------------------------------------------------- 1 | #ifndef _MALLOC_H 2 | #define _MALLOC_H 3 | 4 | #include 5 | #include 6 | 7 | #define PAGE_SIZE ((size_t) sysconf(_SC_PAGESIZE)) 8 | #define align8(x) ((x % 8) ? (x + (8 - x % 8)) : x) 9 | 10 | typedef struct s_block *t_block; 11 | 12 | /** 13 | * struct s_block - Holds the details of each block 14 | * @size: size of block 15 | * @next: pointer to next block 16 | */ 17 | struct s_block 18 | { 19 | size_t size; 20 | struct s_block *next; 21 | }; 22 | 23 | #define BLOCK_SIZE sizeof(struct s_block) 24 | 25 | void *naive_malloc(size_t size); 26 | void *_malloc(size_t size); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /0x08-malloc/naive_malloc.c: -------------------------------------------------------------------------------- 1 | #include "malloc.h" 2 | 3 | static void *heap_start; 4 | 5 | /** 6 | * naive_malloc - malloc which keep track of the address of the first 7 | * chunk in chain and also allocate more space when a page is full 8 | * @size: No of bytes to be allocated 9 | * Return: A pointer to the allocated memory that is aligned for any type 10 | */ 11 | void *naive_malloc(size_t size) 12 | { 13 | void *previous_break = NULL; 14 | size_t header_size = sizeof(size_t), unused_chunk, used_chunk, chunk; 15 | 16 | if (size <= 0) 17 | return (NULL); 18 | size = align8(size); 19 | chunk = header_size + size; 20 | if (heap_start == NULL) 21 | { 22 | heap_start = sbrk(0); 23 | unused_chunk = PAGE_SIZE; 24 | previous_break = sbrk(unused_chunk); 25 | if (previous_break == (void *)-1) 26 | return (NULL); 27 | *((size_t *) previous_break) = chunk ; /*set used bytes */ 28 | *((size_t *)((char *)previous_break + chunk)) = 29 | unused_chunk - chunk; /* setting unused chunk */ 30 | return ((void *)((char *)previous_break + header_size)); 31 | } 32 | previous_break = heap_start; 33 | do { 34 | used_chunk = *((size_t *) previous_break); 35 | previous_break = (void *)((char *)previous_break + used_chunk); 36 | unused_chunk = *((size_t *) previous_break); 37 | } while (unused_chunk <= chunk); 38 | *((size_t *) previous_break) = chunk; 39 | previous_break = (void *)((char *)previous_break + header_size); 40 | if (unused_chunk <= chunk) 41 | { 42 | if (sbrk(PAGE_SIZE) == (void *)-1) 43 | return (NULL); 44 | *((size_t *) ((char *)previous_break + size)) = 45 | unused_chunk + PAGE_SIZE - chunk; 46 | } else 47 | *((size_t *) ((char *)previous_break + size)) = 48 | unused_chunk - chunk; 49 | return (previous_break); 50 | } 51 | -------------------------------------------------------------------------------- /0x09-libasm/0-strlen.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_strlen ; EXPORT our 'asm_strlen' function 5 | 6 | section .text 7 | ; size_t asm_strlen(char *s) 8 | ; returns the size of the string 9 | asm_strlen: 10 | ;;prologue 11 | push rbp ; Set up stack frame 12 | mov rbp, rsp 13 | push rdi 14 | ;;prologue end 15 | 16 | mov rcx, 0x0 ; Declare a counter 17 | 18 | ;loop_str - while (*s ! = '\0') 19 | loop_str: 20 | cmp [rdi], byte 0 ; Compare the value with NULL 21 | je end 22 | add rdi, 1 ; Increment the string 23 | inc rcx ; Increment the counter 24 | jmp loop_str 25 | end: 26 | mov rax, rcx ; Set the return value 27 | ;;epilogue 28 | pop rdi 29 | mov rsp, rbp ; Restore previous stack frame 30 | pop rbp 31 | ;;epilogue end 32 | ret ; Return from procedure 33 | -------------------------------------------------------------------------------- /0x09-libasm/1-strcmp.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_strcmp ; EXPORT our 'asm_strcmp' function 5 | 6 | section .text 7 | ; int asm_strcmp(const char *s1, const char *s2) 8 | ; compares the 2 string 9 | asm_strcmp: 10 | ;;prologue 11 | push rbp ; Set up stack frame 12 | mov rbp, rsp 13 | 14 | push r15 15 | push r14 16 | ;;prologue end 17 | 18 | mov r15b, 0 ; variable c1 19 | mov r14b, 0 ; variable c2 20 | 21 | ;loop_str - while loop 22 | loop_str: 23 | mov r15b, byte [rdi] ; c1 = *s1; 24 | mov r14b, byte [rsi] ; c2 = *s2; 25 | add rdi, 1 ; Increment the first string *s1++; 26 | add rsi, 1 ; Increment the second string *s2++; 27 | cmp r15b, r14b ; (c1 != c2) 28 | jne loopend 29 | cmp r15b, byte 0 ; (!c1) 30 | je eq 31 | jmp loop_str 32 | loopend: 33 | 34 | cmp r15b, r14b ; c1 < c2 35 | jl neg 36 | jmp pos 37 | 38 | neg: 39 | mov rax, 0xFFFFFFFF ; Set return value -1 40 | jmp end 41 | 42 | pos: 43 | mov rax, 0x1 ; Set return value 1 44 | jmp end 45 | 46 | eq: 47 | mov rax, 0x0 ; Set return value 0 48 | jmp end 49 | 50 | end: 51 | ;;epilogue 52 | pop r14 53 | pop r15 54 | mov rsp, rbp ; Restore previous stack frame 55 | pop rbp 56 | ;;epilogue end 57 | ret ; Return from procedure 58 | -------------------------------------------------------------------------------- /0x09-libasm/100-putc.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | global asm_putc ; EXPORT our 'asm_putc' function 4 | 5 | section .text 6 | 7 | ; size_t asm_putc(int c); 8 | ; Prints the input char 9 | 10 | asm_putc: 11 | ;;prologue 12 | push rbp ; Setup stack frame 13 | mov rbp, rsp 14 | ; Save registers that are gonna be used in this 15 | push rsi ; procedure, in case they were used before 16 | push rcx 17 | push rdx 18 | push rdi 19 | ;;prologue end 20 | 21 | ; Setup 'write' syscall 22 | mov eax, 1 ; Write syscall 23 | mov edx, 1 ; Write 1 byte 24 | lea rsi, [rsp] ; Address of the character to be printed (Address of the stack) 25 | mov edi, 1 ; write to stdout 26 | syscall 27 | 28 | ;; epilogue 29 | pop rdi ; Restore used registers 30 | pop rdx 31 | pop rcx 32 | pop rsi 33 | mov rsp, rbp ; Restore previous stack frame 34 | pop rbp 35 | ;;epilogue end 36 | 37 | ret ; Return from procedure 38 | -------------------------------------------------------------------------------- /0x09-libasm/1000-puti.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | EXTERN asm_putc ; IMPORT out 'asm_putc' function 3 | global asm_puti ; EXPORT our 'asm_puti' function 4 | section .text 5 | ; size_t asm_puti(int n); 6 | ; Prints the lowercase alphabet 7 | 8 | asm_puti: 9 | ;; prologue 10 | push rbp ; Setup stack frame 11 | mov rbp, rsp 12 | push rsi ;Save registers that are gonna be used in this 13 | push rdi ; procedure, in case they were used before 14 | push rdx 15 | push r13 16 | push r14 17 | push r8 18 | ;; prologue end 19 | 20 | mov rsi, 0 ;size_t counter = 0 21 | xor r13, r13 22 | mov r13, rdi ;long no = n 23 | cmp r13d, 0 ;if(no<0) 24 | js negative 25 | mov rax, r13 26 | jmp print_number 27 | 28 | negative: 29 | mov r8, 1 30 | movsx r13, edi 31 | neg r13 32 | inc rsi 33 | mov rdi, 45 34 | call asm_putc 35 | mov rax, r13 36 | print_number: 37 | mov r13, rax 38 | inc rsi 39 | cdq 40 | mov rbx, 10 41 | xor rdx, rdx 42 | idiv rbx 43 | push rdx 44 | cmp r13, 10 ;if(n >= 10) 45 | jge print_number 46 | mov r14, rsi 47 | cmp r8, 1 48 | jne loop 49 | dec r14 50 | loop: 51 | cmp r14, byte 0 52 | je end 53 | pop rdi 54 | add rdi, 48 55 | call asm_putc 56 | dec r14 57 | jmp loop 58 | end: 59 | mov rax, rsi 60 | 61 | ;; epilogue 62 | pop r8 63 | pop r14 64 | pop r13 65 | pop rdx ; Restore used registers 66 | pop rdi 67 | pop rsi 68 | mov rsp, rbp 69 | pop rbp 70 | ;; epilogue end 71 | 72 | ret 73 | -------------------------------------------------------------------------------- /0x09-libasm/1001-puti_base.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_puti_base ; EXPORT our 'asm_puti_base' function 5 | extern asm_putc, asm_strlen ; Import our function from external file 6 | section .text 7 | ; size_t asm_puti_base(int n, const char *base) 8 | ; Prints a signed integer in a given base on the standard output 9 | 10 | asm_puti_base: 11 | ;;prologue 12 | push rbp ; Set up stack frame 13 | mov rbp, rsp 14 | push rdx 15 | push r8 16 | push r9 17 | push rdi 18 | ;;prologue end 19 | 20 | mov rdi, rsi 21 | 22 | call asm_strlen ; Call to strlen, measure the length of string 23 | pop rdi 24 | push rax 25 | lea rdx, [rsp] 26 | xor r9d, r9d 27 | mov eax, edi 28 | test eax, eax 29 | js negative 30 | print: 31 | mov ebx, [rdx] ; Copy the length of string to ebx 32 | xor ecx, ecx ; set counter to 0 33 | not ecx ; Invert ecx bits to count backwards 34 | iloop: xor edx, edx ; Reset edx to make the division 35 | div ebx ; Divide the number (in edx:eax) by length of string 36 | sub rsp, 1 ; Reserve one byte on stack to put the remainder 37 | mov [rsp], dl ; Save the remainder of division (number / length) 38 | test eax, eax ; Check when we reach zero 39 | loopnz iloop ; While not zero, decrement ecx and loop 40 | not ecx ; Invert bits again to get positive number of bytes 41 | pstr: movzx r8d, BYTE [rsp] ; After we reach zero start copying bytes from stack 42 | movzx edi, BYTE [rsi + r8] ; in reverse order to be printed 43 | call asm_putc ; Print each digit 44 | add r9b, al ; Transfer the result of call to putc to our counter 45 | add rsp, 1 ; Restore each byte from the stack 46 | loopnz pstr ; While not zero, decrement the counter (ecx) and loop 47 | mov eax, r9d ; When zero, copy the acumulator to return value 48 | 49 | end: 50 | add rsp, 8 ; Remove 8 bytes from stack (used by rax) 51 | 52 | ;;epilogue 53 | pop r9 54 | pop r8 55 | pop rdx 56 | mov rsp, rbp ; Restore previous stack frame 57 | pop rbp 58 | ;;epilogue end 59 | ret ; Return from procedure 60 | 61 | negative: ; Subroutine to deal with negative numbers 62 | neg eax ; Make positive (flip sign) 63 | push rax ; Preserve the number on stack 64 | mov edi, '-' ; Define 1st arg to putc 65 | call asm_putc ; Call putc to print the minus sign 66 | add r9b, al ; Add the return value to r9 to be returned later 67 | pop rax ; Restore the number 68 | mov edi, eax ; Use the number as 1st argument to next routine 69 | jmp print ; Jump to 'print' subroutine 70 | -------------------------------------------------------------------------------- /0x09-libasm/101-puts.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | global asm_puts ; EXPORT our 'asm_puts' function 4 | EXTERN asm_strlen ; IMPORT out 'asm_strlen' function 5 | section .text 6 | 7 | ; size_t asm_puts(const char *str) 8 | ; Prints the string 9 | 10 | asm_puts: 11 | push rbp ; Setup stack frame 12 | mov rbp, rsp 13 | 14 | call asm_strlen ; Call asm_strlen to measure the string length 15 | mov edx, eax ; Use the length of the string as 3rd arg to write syscall 16 | mov esi, edi ; 2nd arg is the string 17 | mov edi, 1 ; 1st arg is the file descriptor to write to (1 for STDOUT) 18 | mov eax, 1 ; eax carries the syscall number (1 for write) 19 | syscall 20 | mov rsp, rbp ; Restore previous stack frame 21 | pop rbp 22 | ret ; Return 23 | -------------------------------------------------------------------------------- /0x09-libasm/102-strcasecmp.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_strcasecmp ; EXPORT our 'asm_strcasecmp' function 5 | 6 | section .text 7 | 8 | ; int asm_strcasecmp(const char *s1, const char *s2) 9 | ; compares the 2 string 10 | asm_strcasecmp: 11 | ;;prologue 12 | push rbp ; Set up stack frame 13 | mov rbp, rsp 14 | 15 | push r15 16 | push r14 17 | ;;prologue end 18 | 19 | mov r15b, 0 ; variable c1 20 | mov r14b, 0 ; variable c2 21 | 22 | ;loop_str - while loop 23 | loop_str: 24 | mov r15b, [rdi] ; c1 = *s1; 25 | mov r14b, [rsi] ; c2 = *cs2; 26 | add rdi, 1 ; Increment the first string *cs1++; 27 | add rsi, 1 ; Increment the second string *cs2++; 28 | 29 | cmp r15b, 41h 30 | jb end1 31 | 32 | cmp r15b, 5bh 33 | jg end1 34 | 35 | add r15b,20H 36 | end1: 37 | cmp r14b, 41h 38 | jb end2 39 | 40 | cmp r14b, 5bh 41 | jg end2 42 | 43 | add r14b,20H 44 | end2: 45 | 46 | cmp r15b, r14b ; (c1 != c2) 47 | jne loopend 48 | cmp r15b, byte 0 ; (!c1) 49 | je eq 50 | jmp loop_str 51 | loopend: 52 | mov rax, r15 53 | sub rax, r14 54 | jmp end 55 | eq: 56 | mov rax, 0x0 ; Set return value 0 57 | jmp end 58 | 59 | end: 60 | ;;epilogue 61 | pop r14 62 | pop r15 63 | mov rsp, rbp ; Restore previous stack frame 64 | pop rbp 65 | ;;epilogue end 66 | ret ; Return from procedure 67 | -------------------------------------------------------------------------------- /0x09-libasm/103-strncasecmp.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_strncasecmp ; EXPORT our 'asm_strncasecmp' function 5 | 6 | section .text 7 | 8 | ; int asm_strncasecmp(const char *s1, const char *s2, size_t n); 9 | ; compares n bytes of the 2 string 10 | asm_strncasecmp: 11 | ;;prologue 12 | push rbp ; Set up stack frame 13 | mov rbp, rsp 14 | 15 | push rcx 16 | push r15 17 | push r14 18 | ;;prologue end 19 | 20 | mov r15b, 0 ; variable c1 21 | mov r14b, 0 ; variable c2 22 | mov rcx, rdx ; counter i 23 | ;loop_str - while loop 24 | loop_str: 25 | mov r15b, [rdi] ; c1 = *s1; 26 | mov r14b, [rsi] ; c2 = *cs2; 27 | add rdi, 1 ; Increment the first string *cs1++; 28 | add rsi, 1 ; Increment the second string *cs2++; 29 | 30 | cmp rcx, 0 ; (count > 0) 31 | jle eq 32 | cmp r15b, 41h 33 | jb end1 34 | 35 | cmp r15b, 5bh 36 | jg end1 37 | 38 | add r15b,20H 39 | end1: 40 | cmp r14b, 41h 41 | jb end2 42 | 43 | cmp r14b, 5bh 44 | jg end2 45 | 46 | add r14b,20H 47 | end2: 48 | 49 | cmp r15b, r14b ; (c1 != c2) 50 | jne loopend 51 | cmp r15b, byte 0 ; (!c1) 52 | je eq 53 | sub rcx, 1; 54 | jmp loop_str 55 | loopend: 56 | mov rax, r15 57 | sub rax, r14 58 | jmp end 59 | eq: 60 | mov rax, 0x0 ; Set return value 0 61 | jmp end 62 | 63 | end: 64 | ;;epilogue 65 | pop r14 66 | pop r15 67 | pop rcx 68 | mov rsp, rbp ; Restore previous stack frame 69 | pop rbp 70 | ;;epilogue end 71 | ret ; Return from procedure 72 | -------------------------------------------------------------------------------- /0x09-libasm/104-strspn.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_strspn ; EXPORT our 'asm_strspn' function 5 | 6 | section .text 7 | ; size_t strspn(const char *s, const char *accept) 8 | ; Calculate the length of the initial substring of @s which only contain letters in @accept 9 | asm_strspn: 10 | ;;prologue 11 | push rbp ; Set up stack frame 12 | mov rbp, rsp 13 | push rcx 14 | push r15 15 | push r14 16 | push r13 17 | ;;prologue end 18 | 19 | mov r15b, 0 ; variable char *p 20 | mov r14b, 0 ; variable char *a 21 | mov r13b, 0 22 | mov rcx, 0h 23 | 24 | mov r15, rdi ; p = s; 25 | ;loop_str - while loop 26 | loop_str: 27 | cmp [r15], byte 0 ; while (*p != '\0') 28 | je loopend 29 | mov r14, rsi ; a = accept; 30 | loop_str_str: 31 | cmp [r14], byte 0 ; (*a != '\0') 32 | je e 33 | mov r13b, [r15] 34 | cmp r13b, [r14] ; (*p == *a) 35 | je e 36 | add r14, 1 ; ++a 37 | jmp loop_str_str 38 | e: 39 | cmp [r14], byte 0 ; (*a != '\0') 40 | je loopend 41 | add r15, 1 ; ++p; 42 | inc rcx 43 | jmp loop_str 44 | loopend: 45 | mov rax, rcx ; Return count 46 | 47 | ;;epilogue 48 | pop r13 ; Restore previous stack frame 49 | pop r14 50 | pop r15 51 | pop rcx 52 | mov rsp, rbp 53 | pop rbp 54 | ;;epilogue end 55 | ret ; Return from procedure 56 | -------------------------------------------------------------------------------- /0x09-libasm/105-strcspn.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_strcspn ; EXPORT our 'asm_strcspn' function 5 | 6 | section .text 7 | ; size_t strcspn(const char *s, const char *reject) 8 | ; Calculate the length of the initial substring of @s which doesn't contain letters in @reject 9 | asm_strcspn: 10 | ;;prologue 11 | push rbp ; Set up stack frame 12 | mov rbp, rsp 13 | push rcx 14 | push r15 15 | push r14 16 | push r13 17 | ;;prologue end 18 | 19 | mov r15b, 0 ; variable char *p 20 | mov r14b, 0 ; variable char *r 21 | mov r13b, 0 22 | mov rcx, 0h 23 | 24 | mov r15, rdi ; p = s; 25 | ;loop_str - while loop 26 | loop_str: 27 | cmp [r15], byte 0 ; while (*p != '\0') 28 | je loopend 29 | mov r14, rsi ; r = reject; 30 | loop_str_str: 31 | cmp [r14], byte 0 ; (*r != '\0') 32 | je e 33 | mov r13b, [r15] 34 | cmp r13b, [r14] ; (*p == *r) 35 | je loopend 36 | add r14, 1 ; ++r 37 | jmp loop_str_str 38 | e: 39 | add r15, 1 ; ++p; 40 | inc rcx 41 | jmp loop_str 42 | loopend: 43 | mov rax, rcx ; Return count 44 | 45 | ;;epilogue 46 | pop r13 ; Restore previous stack frame 47 | pop r14 48 | pop r15 49 | pop rcx 50 | mov rsp, rbp 51 | pop rbp 52 | ;;epilogue end 53 | ret ; Return from procedure 54 | -------------------------------------------------------------------------------- /0x09-libasm/106-strpbrk.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_strpbrk ; EXPORT our 'asm_strpbrk' function 5 | 6 | section .text 7 | ; size_t strbrk(const char *s, const char *accept) 8 | ; Find the first occurrence of a set of characters 9 | asm_strpbrk: 10 | ;;prologue 11 | push rbp ; Set up stack frame 12 | mov rbp, rsp 13 | push r15 14 | push r14 15 | push r13 16 | ;;prologue end 17 | 18 | mov r15b, 0 ; variable char *cs1 19 | mov r14b, 0 ; variable char *cs2 20 | mov r13b, 0 21 | 22 | mov r15, rdi ; cs1 = s; 23 | ;loop_str - while loop 24 | loop_str: 25 | cmp [r15], byte 0 ; while (*cs1 != '\0') 26 | je loopend 27 | mov r14, rsi ; cs2 = accept; 28 | loop_str_str: 29 | cmp [r14], byte 0 ; (*cs2 != '\0') 30 | je e 31 | mov r13b, [r15] 32 | cmp r13b, [r14] ; (*cs1 == *cs2) 33 | je end 34 | add r14, 1 ; ++cs2 35 | jmp loop_str_str 36 | e: 37 | add r15, 1 ; ++cs1; 38 | jmp loop_str 39 | loopend: 40 | mov r15, 0x0 ; Return NULL 41 | end: 42 | mov rax, r15 ; Return the first occurrence 43 | 44 | ;;epilogue 45 | pop r13 ; Restore previous stack frame 46 | pop r14 47 | pop r15 48 | mov rsp, rbp 49 | pop rbp 50 | ;;epilogue end 51 | ret ; Return from procedure 52 | -------------------------------------------------------------------------------- /0x09-libasm/2-strncmp.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_strncmp ; EXPORT our 'asm_strncmp' function 5 | 6 | section .text 7 | ; int asm_strncmp(const char *s1, const char *s2, size_t n); 8 | ; compares the n bytes of string s1 and s2 9 | asm_strncmp: 10 | ;;prologue 11 | push rbp ; Set up stack frame 12 | mov rbp, rsp 13 | push rcx 14 | push r15 15 | push r14 16 | ;;prologue end 17 | 18 | mov r15b, 0 ; variable c1 19 | mov r14b, 0 ; variable c2 20 | mov rcx, rdx ; counter i 21 | 22 | ;loop_str - while loop 23 | loop_str: 24 | mov r15b, byte [rdi] ; c1 = *s1; 25 | mov r14b, byte [rsi] ; c2 = *s2; 26 | add rdi, 1 ; Increment the first string *s1++; 27 | add rsi, 1 ; Increment the second string *s2++; 28 | cmp rcx, 0 ; (count > 0) 29 | jle eq 30 | cmp r15b, r14b ; (c1 != c2) 31 | jne loopend 32 | cmp r15b, byte 0 ; (!c1) 33 | je eq 34 | sub rcx, 1; 35 | jmp loop_str 36 | loopend: 37 | 38 | cmp r15b, r14b ; c1 < c2 39 | jl neg 40 | jmp pos 41 | 42 | neg: 43 | mov rax, 0xFFFFFFFF ; Set return value -1 44 | jmp end 45 | 46 | pos: 47 | mov rax, 0x1 ; Set return value 1 48 | jmp end 49 | 50 | eq: 51 | mov rax, 0x0 ; Set return value 0 52 | jmp end 53 | 54 | end: 55 | ;;epilogue 56 | pop r14 57 | pop r15 58 | pop rcx 59 | mov rsp, rbp ; Restore previous stack frame 60 | pop rbp 61 | ;;epilogue end 62 | ret ; Return from procedure 63 | -------------------------------------------------------------------------------- /0x09-libasm/3-strchr.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_strchr ; EXPORT our 'asm_strchr' function 5 | 6 | section .text 7 | ; char *asm_strchr(const char *s, int c) 8 | ; return pointer to string from postion of 'c' in string s 9 | asm_strchr: 10 | ;;prologue 11 | push rbp ; Set up stack frame 12 | mov rbp, rsp 13 | ;;prologue end 14 | mov rax, rdi 15 | 16 | ;loop_str - while loop 17 | loop_str: 18 | cmp byte [rax], sil ; (*s != c) 19 | je end 20 | cmp byte [rax], byte 0 ; (*s == '\0') 21 | je nullend 22 | inc rax ; Increment the first string *s++; 23 | jmp loop_str 24 | 25 | nullend: 26 | mov rax, 0x0 27 | 28 | end: 29 | ;;epilogue 30 | mov rsp, rbp ; Restore previous stack frame 31 | pop rbp 32 | ;;epilogue end 33 | ret ; Return from procedure 34 | -------------------------------------------------------------------------------- /0x09-libasm/4-strstr.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_strstr ; EXPORT our 'asm_strstr' function 5 | 6 | section .text 7 | ; int asm_strstr(const char *str, const char *substr); 8 | ; finds the first occurrence of the substring in the string 9 | asm_strstr: 10 | ;;prologue 11 | push rbp ; Set up stack frame 12 | mov rbp, rsp 13 | push r15 14 | push r14 15 | push r13 16 | ;;prologue end 17 | 18 | mov r15b, 0 ; variable char *str 19 | mov r14b, 0 ; variable char *substr 20 | mov r13b, 0 21 | 22 | cmp [rsi], byte 0 ; if (!*str) 23 | mov r15, rdi 24 | je end 25 | ;loop_str - while loop 26 | loop_str: 27 | cmp [rdi], byte 0 ; while (!*str) 28 | je nullend 29 | mov r15, rdi ; *Begin = *str; 30 | mov r14, rsi ; *pattern = *substr; 31 | loop_str_str: 32 | cmp [rdi], byte 0 ; (*str) 33 | je e 34 | cmp [r14], byte 0 ; (*pattern) 35 | je e 36 | mov r13b, [rdi] 37 | cmp r13b, [r14] ; (*str == *pattern) 38 | jne e 39 | add rdi, 1 ; Increment the first string *str++; 40 | add r14, 1 ; Increment the second string *pattern++; 41 | jmp loop_str_str 42 | e: 43 | cmp [r14], byte 0 44 | je end 45 | add r15, 1 ; Begin + 1; 46 | mov rdi, r15 ; str = Begin + 1; 47 | jmp loop_str 48 | loopend: 49 | nullend: 50 | mov r15, 0x0 51 | end: 52 | mov rax, r15 ; Return Begin; 53 | 54 | ;;epilogue 55 | pop r13 ; Restore previous stack frame 56 | pop r14 57 | pop r15 58 | mov rsp, rbp 59 | pop rbp 60 | ;;epilogue end 61 | ret ; Return from procedure 62 | -------------------------------------------------------------------------------- /0x09-libasm/5-memcpy.asm: -------------------------------------------------------------------------------- 1 | BITS 64 2 | 3 | ;; declare prerequistes 4 | global asm_memcpy ; EXPORT our 'asm_memcpy' function 5 | 6 | section .text 7 | ; int asm_memcpy(void *dest, const void *src, size_t n); 8 | ; copies n bytes from memory area src to memory area dest 9 | asm_memcpy: 10 | mov rax, rdi ; Copy the pointer to @dest string to be returned 11 | mov ecx, edx ; Copy the length @n to the counter 12 | cld ; Clear the direction flag, DL 13 | rep movsb ; Copy @n bytes from ESI (source) to EDI (destination) 14 | ret ; Return 15 | -------------------------------------------------------------------------------- /0x09-libasm/README.md: -------------------------------------------------------------------------------- 1 | # 0x09. x86 Assembly - libASM 2 | ### System programming & Algorithm ― Linux programming 3 | 4 | The Assembly syntax used is: 5 | * x86 Assembly 6 | * 64-bit architecture 7 | * Intel 8 | 9 | The tools used in the project are 10 | * Ubuntu 14.04 LTS 11 | * NASM version 2.10.09 12 | * gcc version 4.8.4 13 | * gdb - for debugging 14 | 15 | Command used to assemble the asm files 16 | ``` 17 | nasm -f elf64 18 | ``` 19 | 20 | * main - contains all the main files to test the functions created 21 | 22 | * libasm.h - The prototypes of all functions are included in this header 23 | 24 | * 0-strlen.asm - A copycat of the function strlen(3), in x86-64 Assembly 25 | 26 | * 1-strcmp.asm - A copycat of the function strcmp(3), in x86-64 Assembly 27 | 28 | * 2-strncmp.asm - A copycat of the function strncmp(3), in x86-64 Assembly 29 | 30 | * 3-strchr.asm - A copycat of the function strchr(3), in x86-64 Assembly 31 | 32 | * 4-strstr.asm - A copycat of the function strchstr(3), in x86-64 Assembly 33 | 34 | * 5-memcpy.asm - A copycat of the function memcpy(3), in x86-64 Assembly 35 | 36 | * 100-putc.asm - A function that prints a single character on the standard output 37 | 38 | * 101-puts.asm - A function that prints a string of characters on the standard output 39 | 40 | * 102-strcasecmp.asm - A copycat of the function strcasecmp(3), in x86-64 Assembly 41 | 42 | * 103-strncasecmp.asm - A copycat of the function strncasecmp(3), in x86-64 Assembly 43 | 44 | * 104-strspn.asm - A copycat of the function strspn(3), in x86-64 Assembly 45 | 46 | * 105-strcspn.asm - A copycat of the function strcspn(3), in x86-64 Assembly 47 | 48 | * 106-strpbrk.asm - A copycat of the function strpbrk(3), in x86-64 Assembly 49 | 50 | # Useful Resources: 51 | * [[EYNTK] x86-64 Assembly](https://intranet.hbtn.io/concepts/82) 52 | * [List of registers](https://en.wikipedia.org/wiki/Processor_register) 53 | * [List of Intel Instructions](http://www.penguin.cz/~literakl/intel/intel.html) 54 | * [A video to explain how the stack frame works](https://www.youtube.com/watch?v=KRaJoeVXF_8) 55 | * [Github repository containing the sources use](https://github.com/holbertonschool/0x09-libasm_concept) 56 | * [Linux code replicated](https://github.com/torvalds/linux/blob/master/lib/string.c) 57 | -------------------------------------------------------------------------------- /0x09-libasm/libasm.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBASM_H__ 2 | #define __LIBASM_H__ 3 | 4 | size_t asm_strlen(const char *str); 5 | int asm_strcmp(const char *s1, const char *s2); 6 | int asm_strncmp(const char *s1, const char *s2, size_t n); 7 | char *asm_strchr(const char *s, int c); 8 | char *asm_strstr(const char *s1, const char *s2); 9 | void *asm_memcpy(void *dest, const void *src, size_t n); 10 | size_t asm_putc(int c); 11 | size_t asm_puts(const char *str); 12 | int asm_strcasecmp(const char *s1, const char *s2); 13 | int asm_strncasecmp(const char *s1, const char *s2, size_t n); 14 | size_t asm_strspn(const char *s, const char *accept); 15 | size_t asm_strcspn(const char *s, const char *reject); 16 | char *asm_strpbrk(const char *s, const char *accept); 17 | size_t asm_puti(int n); 18 | size_t asm_puti_base(int n, const char *base); 19 | #endif 20 | -------------------------------------------------------------------------------- /0x09-libasm/main/0-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | #define S1 "Holberton School" 9 | #define S2 "" 10 | #define S3 "\0" 11 | 12 | /** 13 | * main - Program entry point 14 | * 15 | * Return: EXIT_SUCCESS or EXIT_FAILURE 16 | */ 17 | int main(void) 18 | { 19 | assert(strlen(S1) == asm_strlen(S1)); 20 | assert(strlen(S2) == asm_strlen(S2)); 21 | assert(strlen(S3) == asm_strlen(S3)); 22 | 23 | printf("All good!\n"); 24 | return (EXIT_SUCCESS); 25 | } 26 | -------------------------------------------------------------------------------- /0x09-libasm/main/1-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | #define S1 "Holberton School" 9 | #define S2 "" 10 | #define S3 "Holberton Socool" 11 | #define S4 "H" 12 | #define S5 "Ho" 13 | 14 | /** 15 | * main - Program entry point 16 | * 17 | * Return: EXIT_SUCCESS or EXIT_FAILURE 18 | */ 19 | int main(void) 20 | { 21 | assert(strcmp(S1, S1) == asm_strcmp(S1, S1)); 22 | assert(strcmp(S1, S2) == asm_strcmp(S1, S2)); 23 | assert(strcmp(S1, S3) == asm_strcmp(S1, S3)); 24 | assert(strcmp(S1, S4) == asm_strcmp(S1, S4)); 25 | assert(strcmp(S2, S1) == asm_strcmp(S2, S1)); 26 | assert(strcmp(S5, S1) == asm_strcmp(S5, S1)); 27 | 28 | printf("All good!\n"); 29 | return (EXIT_SUCCESS); 30 | } 31 | -------------------------------------------------------------------------------- /0x09-libasm/main/100-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | assert(asm_putc('H') == 1); 16 | assert(asm_putc('b') == 1); 17 | assert(asm_putc('t') == 1); 18 | assert(asm_putc('n') == 1); 19 | assert(asm_putc('\n') == 1); 20 | 21 | printf("All good!\n"); 22 | return (EXIT_SUCCESS); 23 | } 24 | -------------------------------------------------------------------------------- /0x09-libasm/main/1000-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "libasm.h" 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | assert(asm_puti(8) == 1); 16 | printf("\n"); 17 | assert(asm_puti(-1) == 2); 18 | printf("\n"); 19 | assert(asm_puti(-1024) == 5); 20 | printf("\n"); 21 | assert(asm_puti(INT_MAX) == 10); 22 | printf("\n"); 23 | assert(asm_puti(INT_MIN) == 11); 24 | printf("\n"); 25 | assert(asm_puti(0) == 1); 26 | printf("\n"); 27 | return (EXIT_SUCCESS); 28 | } 29 | -------------------------------------------------------------------------------- /0x09-libasm/main/1001-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "libasm.h" 8 | 9 | /** 10 | * main - Program entry point 11 | * 12 | * Return: EXIT_SUCCESS or EXIT_FAILURE 13 | */ 14 | int main(void) 15 | { 16 | asm_puti_base(98, "0123456789"); 17 | printf("\n"); 18 | asm_puti_base(-1, "0123456789"); 19 | printf("\n"); 20 | asm_puti_base(129342, "0123456789abcdef"); 21 | printf("\n"); 22 | asm_puti_base(781532, "01"); 23 | printf("\n"); 24 | asm_puti_base(INT_MAX, "abcdefghijklmnopqrstwxyz"); 25 | printf("\n"); 26 | asm_puti_base(INT_MIN, "0123456789ABCDEF"); 27 | printf("\n"); 28 | asm_puti_base(0, "01234567"); 29 | printf("\n"); 30 | return (EXIT_SUCCESS); 31 | } 32 | -------------------------------------------------------------------------------- /0x09-libasm/main/101-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | assert(asm_puts("H") == 1); 16 | assert(asm_puts("olberton") == 8); 17 | assert(asm_puts(" School\n") == 8); 18 | 19 | printf("All good!\n"); 20 | return (EXIT_SUCCESS); 21 | } 22 | -------------------------------------------------------------------------------- /0x09-libasm/main/102-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | #define S1 "Holberton School" 9 | #define S2 "HOLBERTON SCHOOL" 10 | #define S3 "Holberton SchooL" 11 | #define S4 "holberton socool" 12 | #define S5 "H" 13 | #define S6 "\0" 14 | /** 15 | * main - Program entry point 16 | * 17 | * Return: EXIT_SUCCESS or EXIT_FAILURE 18 | */ 19 | int main(void) 20 | { 21 | assert(strcasecmp(S1, S1) == asm_strcasecmp(S1, S1)); 22 | assert(strcasecmp(S1, S2) == asm_strcasecmp(S1, S2)); 23 | assert(strcasecmp(S1, S3) == asm_strcasecmp(S1, S3)); 24 | assert(strcasecmp(S1, S4) == asm_strcasecmp(S1, S4)); 25 | assert(strcasecmp(S1, S5) == asm_strcasecmp(S1, S5)); 26 | assert(strcasecmp(S1, S6) == asm_strcasecmp(S1, S6)); 27 | assert(strcasecmp(S5, S1) == asm_strcasecmp(S5, S1)); 28 | assert(strcasecmp(S6, S1) == asm_strcasecmp(S6, S1)); 29 | assert(strcasecmp(S6, S6) == asm_strcasecmp(S6, S6)); 30 | assert(strcasecmp(S1, S1) == asm_strcasecmp(S1, S1)); 31 | assert(strcasecmp(S1, S5) == asm_strcasecmp(S1, S5)); 32 | 33 | printf("All good!\n"); 34 | return (EXIT_SUCCESS); 35 | } 36 | -------------------------------------------------------------------------------- /0x09-libasm/main/103-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | #define S1 "Holberton School" 9 | #define S2 "HOLBERTON SCHOOL" 10 | #define S3 "Holberton SchooL" 11 | #define S4 "holberton socool" 12 | 13 | /** 14 | * main - Program entry point 15 | * 16 | * Return: EXIT_SUCCESS or EXIT_FAILURE 17 | */ 18 | int main(void) 19 | { 20 | assert(strncasecmp(S1, S3, 1) == asm_strncasecmp(S1, S3, 1)); 21 | assert(strncasecmp(S1, S2, 11) == asm_strncasecmp(S1, S2, 11)); 22 | assert(strncasecmp(S1, S3, 11) == asm_strncasecmp(S1, S3, 11)); 23 | assert(strncasecmp(S1, S2, 16) == asm_strncasecmp(S1, S2, 16)); 24 | assert(strncasecmp(S1, S3, 16) == asm_strncasecmp(S1, S3, 16)); 25 | assert(strncasecmp(S1, S4, 11) == asm_strncasecmp(S1, S4, 11)); 26 | assert(strncasecmp(S1, S4, 16) == asm_strncasecmp(S1, S4, 16)); 27 | 28 | printf("All good!\n"); 29 | return (EXIT_SUCCESS); 30 | } 31 | -------------------------------------------------------------------------------- /0x09-libasm/main/104-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | #define S1 "Holberton" 9 | #define S2 "holberton" 10 | #define S3 "HOLBERTON" 11 | 12 | #define A1 "abcdefghijklmnopqrstuvwxyz" 13 | #define A2 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 14 | 15 | /** 16 | * main - Program entry point 17 | * 18 | * Return: EXIT_SUCCESS or EXIT_FAILURE 19 | */ 20 | int main(void) 21 | { 22 | assert(strspn(S2, A1) == asm_strspn(S2, A1)); 23 | assert(strspn(S2, A2) == asm_strspn(S2, A2)); 24 | assert(strspn(S3, A1) == asm_strspn(S3, A1)); 25 | assert(strspn(S3, A2) == asm_strspn(S3, A2)); 26 | assert(strspn(S1, A1) == asm_strspn(S1, A1)); 27 | assert(strspn(S1, A2) == asm_strspn(S1, A2)); 28 | assert(strspn(S1, A1 A2) == asm_strspn(S1, A1 A2)); 29 | 30 | printf("All good!\n"); 31 | return (EXIT_SUCCESS); 32 | } 33 | -------------------------------------------------------------------------------- /0x09-libasm/main/105-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | #define S1 "Holberton" 9 | #define S2 "holberton" 10 | #define S3 "HOLBERTON" 11 | 12 | #define A1 "abcdefghijklmnopqrstuvwxyz" 13 | #define A2 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 14 | 15 | /** 16 | * main - Program entry point 17 | * 18 | * Return: EXIT_SUCCESS or EXIT_FAILURE 19 | */ 20 | int main(void) 21 | { 22 | assert(strcspn(S2, A1) == asm_strcspn(S2, A1)); 23 | assert(strcspn(S2, A2) == asm_strcspn(S2, A2)); 24 | assert(strcspn(S3, A1) == asm_strcspn(S3, A1)); 25 | assert(strcspn(S3, A2) == asm_strcspn(S3, A2)); 26 | assert(strcspn(S1, A1) == asm_strcspn(S1, A1)); 27 | assert(strcspn(S1, A2) == asm_strcspn(S1, A2)); 28 | assert(strcspn(S1, A1 A2) == asm_strcspn(S1, A1 A2)); 29 | 30 | printf("All good!\n"); 31 | return (EXIT_SUCCESS); 32 | } 33 | -------------------------------------------------------------------------------- /0x09-libasm/main/106-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | #define S1 "Holberton" 9 | #define S2 "holberton" 10 | #define S3 "HOLBERTON" 11 | 12 | #define A1 "abcdefghijklmnopqrstuvwxyz" 13 | #define A2 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 14 | #define A3 "()[]{}<>n" 15 | 16 | /** 17 | * main - Program entry point 18 | * 19 | * Return: EXIT_SUCCESS or EXIT_FAILURE 20 | */ 21 | int main(void) 22 | { 23 | assert(strpbrk(S2, A1) == asm_strpbrk(S2, A1)); 24 | assert(strpbrk(S2, A2) == asm_strpbrk(S2, A2)); 25 | assert(strpbrk(S3, A1) == asm_strpbrk(S3, A1)); 26 | assert(strpbrk(S3, A2) == asm_strpbrk(S3, A2)); 27 | assert(strpbrk(S1, A3) == asm_strpbrk(S1, A3)); 28 | 29 | printf("All good!\n"); 30 | return (EXIT_SUCCESS); 31 | } 32 | -------------------------------------------------------------------------------- /0x09-libasm/main/2-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | #define S1 "Holberton School" 9 | #define S2 "" 10 | #define S3 "Holberton Socool" 11 | #define S4 "H" 12 | 13 | /** 14 | * main - Program entry point 15 | * 16 | * Return: EXIT_SUCCESS or EXIT_FAILURE 17 | */ 18 | int main(void) 19 | { 20 | assert(strncmp(S1, S3, 1) == asm_strncmp(S1, S3, 1)); 21 | assert(strncmp(S1, S3, 11) == asm_strncmp(S1, S3, 11)); 22 | assert(strncmp(S1, S3, 15) == asm_strncmp(S1, S3, 15)); 23 | assert(strncmp(S2, S1, 10) == asm_strncmp(S2, S1, 10)); 24 | assert(strncmp(S2, S4, 2) == asm_strncmp(S2, S4, 2)); 25 | assert(strncmp(S1, S2, 1) == asm_strncmp(S1, S2, 1)); 26 | 27 | printf("All good!\n"); 28 | return (EXIT_SUCCESS); 29 | } 30 | -------------------------------------------------------------------------------- /0x09-libasm/main/3-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | #define S1 "Holberton School" 9 | #define C1 'n' 10 | #define C2 'S' 11 | #define C3 's' 12 | #define C4 '\0' 13 | 14 | /** 15 | * main - Program entry point 16 | * 17 | * Return: EXIT_SUCCESS or EXIT_FAILURE 18 | */ 19 | int main(void) 20 | { 21 | assert(strchr(S1, C1) == asm_strchr(S1, C1)); 22 | assert(strchr(S1, C2) == asm_strchr(S1, C2)); 23 | assert(strchr(S1, C3) == asm_strchr(S1, C3)); 24 | assert(strchr(S1, C4) == asm_strchr(S1, C4)); 25 | 26 | printf("All good!\n"); 27 | return (EXIT_SUCCESS); 28 | } 29 | -------------------------------------------------------------------------------- /0x09-libasm/main/4-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | #define S1 "Holberton School" 9 | #define S2 "School" 10 | #define S3 "Socool" 11 | #define S4 "" 12 | 13 | /** 14 | char* asm_strstr(const char *str, sonst char *substr) 15 | { 16 | while (*str) 17 | { 18 | const char *Begin = str; 19 | const char *pattern = substr; 20 | 21 | // If first character of sub string match, check for whole string 22 | while (*str && *pattern && *str == *pattern) 23 | { 24 | str++; 25 | pattern++; 26 | } 27 | // If complete sub string match, return starting address 28 | if (!*pattern) 29 | return (char *)Begin; 30 | 31 | str = Begin + 1; // Increament main string 32 | } 33 | return NULL; 34 | } 35 | **/ 36 | /** 37 | * main - Program entry point 38 | * 39 | * Return: EXIT_SUCCESS or EXIT_FAILURE 40 | */ 41 | int main(void) 42 | { 43 | assert(strstr(S1, S2) == asm_strstr(S1, S2)); 44 | assert(strstr(S1, S3) == asm_strstr(S1, S3)); 45 | assert(strstr(S1, S4) == asm_strstr(S1, S4)); 46 | assert(strstr(S1, S1) == asm_strstr(S1, S1)); 47 | assert(strstr(S4, S4) == asm_strstr(S4, S4)); 48 | assert(strstr(S4, S1) == asm_strstr(S4, S1)); 49 | 50 | printf("All good!\n"); 51 | return (EXIT_SUCCESS); 52 | } 53 | -------------------------------------------------------------------------------- /0x09-libasm/main/5-main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "libasm.h" 7 | 8 | /** 9 | * main - Program entry point 10 | * 11 | * Return: EXIT_SUCCESS or EXIT_FAILURE 12 | */ 13 | int main(void) 14 | { 15 | int i; 16 | char *src = strdup("Holberton"); 17 | 18 | for (i = 0; i <= 9; i++) 19 | { 20 | char *dest = strdup("......... School"); 21 | 22 | assert(asm_memcpy(dest, src, i) == dest); 23 | printf("%s\n", dest); 24 | free(dest); 25 | } 26 | free(src); 27 | printf("All good!\n"); 28 | return (EXIT_SUCCESS); 29 | } 30 | -------------------------------------------------------------------------------- /0x09-libasm/main/libasm.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBASM_H__ 2 | #define __LIBASM_H__ 3 | 4 | size_t asm_strlen(const char *str); 5 | int asm_strcmp(const char *s1, const char *s2); 6 | int asm_strncmp(const char *s1, const char *s2, size_t n); 7 | char *asm_strchr(const char *s, int c); 8 | char *asm_strstr(const char *s1, const char *s2); 9 | void *asm_memcpy(void *dest, const void *src, size_t n); 10 | size_t asm_putc(int c); 11 | size_t asm_puts(const char *str); 12 | int asm_strcasecmp(const char *s1, const char *s2); 13 | int asm_strncasecmp(const char *s1, const char *s2, size_t n); 14 | size_t asm_strspn(const char *s, const char *accept); 15 | size_t asm_strcspn(const char *s, const char *reject); 16 | char *asm_strpbrk(const char *s, const char *accept); 17 | size_t asm_puti(int n); 18 | size_t asm_puti_base(int n, const char *base); 19 | #endif 20 | -------------------------------------------------------------------------------- /0x0A_CPython/0-python_lists_bigO: -------------------------------------------------------------------------------- 1 | O(1) 2 | O(1) 3 | O(n) 4 | O(n) 5 | O(n) 6 | O(1) 7 | O(n) 8 | O(n) 9 | O(1) 10 | O(nlog(n)) 11 | O(n) 12 | O(n) 13 | -------------------------------------------------------------------------------- /0x0A_CPython/1-python.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * print_python_list - print some basic info about Python lists 6 | * @p: python object 7 | **/ 8 | void print_python_list(PyObject *p) 9 | { 10 | Py_ssize_t listsize, i; 11 | PyObject *item; 12 | 13 | printf("[*] Python list info\n"); 14 | if (!PyList_Check(p)) 15 | printf("Invalid List Object\n"); 16 | else 17 | { 18 | listsize = ((PyVarObject *) p)->ob_size; 19 | printf("[*] Size of the Python List = %lu\n", listsize); 20 | printf("[*] Allocated = %lu\n", 21 | ((PyListObject *) p)->allocated); 22 | for (i = 0; i < listsize; i++) 23 | { 24 | item = ((PyListObject *) p)->ob_item[i]; 25 | printf("Element %lu: %s\n", i, item->ob_type->tp_name); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /0x0A_CPython/100-python.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * print_python_int - prints Python Integers. 7 | * @p: python object 8 | * Return: nothing 9 | **/ 10 | void print_python_int(PyObject *p) { 11 | PyTypeObject *type; 12 | PyObject *str_repr; 13 | PyObject *pStr; 14 | 15 | type = p->ob_type; 16 | if (strcmp(type->tp_name, "int") != 0) { 17 | printf(" [ERROR] Invalid Int Object\n"); 18 | return; 19 | } 20 | str_repr = PyObject_Repr(p); 21 | pStr = PyUnicode_AsEncodedString(str_repr, "utf-8", "Error ~"); 22 | puts(((PyBytesObject *)pStr)->ob_sval); 23 | } 24 | -------------------------------------------------------------------------------- /0x0A_CPython/2-python.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void print_python_list(PyObject *p); 6 | void print_python_bytes(PyObject *p); 7 | 8 | /** 9 | * print_python_bytes - print some basic info about Python bytes objects 10 | * @p: python object 11 | * Return: nothing 12 | **/ 13 | void print_python_bytes(PyObject *p) 14 | { 15 | char *s; 16 | Py_ssize_t l, i; 17 | 18 | printf("[.] bytes object info\n"); 19 | if (!PyBytes_Check(p)) 20 | printf(" [ERROR] Invalid Bytes Object\n"); 21 | else 22 | { 23 | l = ((PyVarObject *) p)->ob_size; 24 | printf(" size: %lu\n", l); 25 | s = ((PyBytesObject *) p)->ob_sval; 26 | printf(" trying string: %s\n", s); 27 | if (l > 10) 28 | l = 10; 29 | else 30 | l++; 31 | printf(" first %lu bytes: ", l); 32 | for (i = 0; i < l - 1; i++) 33 | printf("%02x ", s[i] & 0xff); 34 | printf("%02x\n", s[l - 1] & 0xff); 35 | } 36 | } 37 | 38 | /** 39 | * print_python_list - print some basic info about Python lists 40 | * @p: python object 41 | **/ 42 | void print_python_list(PyObject *p) 43 | { 44 | Py_ssize_t listsize, i; 45 | PyObject *item; 46 | 47 | printf("[*] Python list info\n"); 48 | if (!PyList_Check(p)) 49 | printf(" [ERROR] Invalid List Object\n"); 50 | else 51 | { 52 | listsize = ((PyVarObject *) p)->ob_size; 53 | printf("[*] Size of the Python List = %lu\n", listsize); 54 | printf("[*] Allocated = %lu\n", 55 | ((PyListObject *) p)->allocated); 56 | for (i = 0; i < listsize; i++) 57 | { 58 | item = ((PyListObject *) p)->ob_item[i]; 59 | printf("Element %lu: %s\n", i, item->ob_type->tp_name); 60 | if (strcmp(item->ob_type->tp_name, "bytes") == 0) 61 | print_python_bytes(item); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /0x0A_CPython/3-python.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define DOUBLE(op) (((PyFloatObject *)(op))->ob_fval) 6 | void print_python_list(PyObject *p); 7 | void print_python_bytes(PyObject *p); 8 | void print_python_float(PyObject *p); 9 | 10 | /** 11 | * print_python_float - print some basic info about Python FLoat objects 12 | * @p: python object 13 | * Return: nothing 14 | **/ 15 | void print_python_float(PyObject *p) 16 | { 17 | char *float_str; 18 | 19 | printf("[.] float object info\n"); 20 | if (!PyFloat_Check(p)) 21 | printf(" [ERROR] Invalid Float Object\n"); 22 | else 23 | { 24 | float_str = PyOS_double_to_string(DOUBLE(p), 25 | 'r', 0, Py_DTSF_ADD_DOT_0, NULL); 26 | if (!float_str) 27 | printf(" value: %.16G\n", DOUBLE(p)); 28 | else 29 | { 30 | printf(" value: %s\n", float_str); 31 | PyMem_Free(float_str); 32 | } 33 | } 34 | fflush(stdout); 35 | } 36 | 37 | /** 38 | * print_string - prints characters of a string if its ascii else prints as '?' 39 | * @s: string to be printed 40 | * Return: nothing 41 | **/ 42 | void print_string(char *s) 43 | { 44 | size_t i; 45 | 46 | i = 0; 47 | while (s && s[i] != '\0') 48 | { 49 | if (isascii(s[i])) 50 | { 51 | putchar(s[i]); 52 | } else 53 | { 54 | putchar('?'); 55 | } 56 | i++; 57 | } 58 | } 59 | 60 | /** 61 | * print_python_bytes - print some basic info about Python bytes objects 62 | * @p: python object 63 | * Return: nothing 64 | **/ 65 | void print_python_bytes(PyObject *p) 66 | { 67 | char *s; 68 | Py_ssize_t l, i; 69 | 70 | printf("[.] bytes object info\n"); 71 | if (!PyBytes_Check(p)) 72 | printf(" [ERROR] Invalid Bytes Object\n"); 73 | else 74 | { 75 | l = ((PyVarObject *) p)->ob_size; 76 | printf(" size: %lu\n", l); 77 | s = ((PyBytesObject *) p)->ob_sval; 78 | printf(" trying string: "); 79 | print_string(s); 80 | putchar('\n'); 81 | if (l >= 10) 82 | l = 10; 83 | else 84 | l++; 85 | printf(" first %lu bytes: ", l); 86 | for (i = 0; i < l; i++) 87 | { 88 | printf("%02x", s[i] & 0xff); 89 | if (i + 1 < l) 90 | putchar(' '); 91 | } 92 | putchar('\n'); 93 | } 94 | fflush(stdout); 95 | } 96 | 97 | /** 98 | * print_python_list - print some basic info about Python lists 99 | * @p: python object 100 | **/ 101 | void print_python_list(PyObject *p) 102 | { 103 | Py_ssize_t listsize, i; 104 | PyObject *item; 105 | 106 | if (!PyList_Check(p)) 107 | printf(" [ERROR] Invalid List Object\n"); 108 | else 109 | { 110 | printf("[*] Python list info\n"); 111 | listsize = ((PyVarObject *) p)->ob_size; 112 | printf("[*] Size of the Python List = %lu\n", listsize); 113 | printf("[*] Allocated = %lu\n", 114 | ((PyListObject *) p)->allocated); 115 | for (i = 0; i < listsize; i++) 116 | { 117 | item = ((PyListObject *) p)->ob_item[i]; 118 | printf("Element %lu: %s\n", i, item->ob_type->tp_name); 119 | if (strcmp(item->ob_type->tp_name, "bytes") == 0) 120 | print_python_bytes(item); 121 | else if (strcmp(item->ob_type->tp_name, "float") == 0) 122 | print_python_float(item); 123 | } 124 | } 125 | fflush(stdout); 126 | } 127 | -------------------------------------------------------------------------------- /0x0A_CPython/4-python.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * print_python_string - prints Python strings. 7 | * @p: python object 8 | * Return: nothing 9 | **/ 10 | void print_python_string(PyObject *p) 11 | { 12 | PyTypeObject *type; 13 | PyASCIIObject *ascii_obj; 14 | unsigned long len; 15 | void *str; 16 | char *strtype; 17 | unsigned int i; 18 | unsigned short *wstring; 19 | unsigned char *wchar; 20 | 21 | printf("[.] string object info\n"); 22 | type = p->ob_type; 23 | if (strcmp(type->tp_name, "str") != 0) 24 | { 25 | printf(" [ERROR] Invalid String Object\n"); 26 | return; 27 | } 28 | 29 | len = ((PyVarObject *) p)->ob_size; 30 | ascii_obj = (PyASCIIObject *) p; 31 | if (((ascii_obj->state).compact == 1) && ((ascii_obj->state).ascii == 1) 32 | && ((ascii_obj->state).ready == 1)) 33 | strtype = "compact ascii"; 34 | if (((ascii_obj->state).compact == 1) && ((ascii_obj->state).ascii == 0) 35 | && ((ascii_obj->state).ready == 1)) 36 | strtype = "compact unicode object"; 37 | printf(" type: %s\n", strtype); 38 | printf(" length: %lu\n", len); 39 | if (strcmp("compact ascii", strtype) == 0) 40 | { 41 | str = (ascii_obj) + 1; 42 | printf(" value: %s\n", (char *)str); 43 | } 44 | if (strcmp("compact unicode object", strtype) == 0) 45 | { 46 | if ((ascii_obj->state).kind == 2) 47 | wstring = 48 | ((unsigned short *)((PyCompactUnicodeObject *) (p) + 49 | 1)); 50 | if ((ascii_obj->state).kind == 1) 51 | wchar = 52 | ((unsigned char *)((PyCompactUnicodeObject *) (p) + 53 | 1)); 54 | printf(" value: "); 55 | for (i = 0; i < len; i++) 56 | { 57 | if ((ascii_obj->state).kind == 2) 58 | printf("%lc", wstring[i]); 59 | else if ((ascii_obj->state).kind == 1) 60 | printf("%lc", wchar[i]); 61 | } 62 | printf("\n"); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /0x0A_CPython/5-python.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /** 7 | * print_python_int - prints Python Integers. 8 | * @p: python object 9 | * Return: clongthing 10 | **/ 11 | 12 | void print_python_int(PyObject *p) 13 | { 14 | PyLongObject *lng; 15 | PyVarObject *var; 16 | unsigned long clong, prev; 17 | long i, size; 18 | int neg = 0; 19 | 20 | if (!PyLong_Check(p)) 21 | { 22 | puts("Invalid Int Object"); 23 | return; 24 | } 25 | lng = (PyLongObject *)p; 26 | var = (PyVarObject *)p; 27 | clong = 0; 28 | size = var->ob_size; 29 | if (size < 0) 30 | { 31 | size *= -1; 32 | neg = 1; 33 | } 34 | for (i = size - 1; i >= 0; i--) 35 | { 36 | prev = clong; 37 | clong = 38 | (clong >> (8 * sizeof(long) - PyLong_SHIFT)) | (clong << PyLong_SHIFT); 39 | clong += (lng->ob_digit[i]); 40 | if (prev >= clong) 41 | { 42 | puts("C unsigned long int overflow"); 43 | return; 44 | } 45 | } 46 | if (neg) 47 | printf("-"); 48 | printf("%lu\n", clong); 49 | fflush(stdout); 50 | } 51 | -------------------------------------------------------------------------------- /0x0A_CPython/README.md: -------------------------------------------------------------------------------- 1 | # 0x0A. CPython 2 | 3 | * 0-python_lists_bigO - Contains the big O notations for the following lists operations 4 | 5 | * L1 - Assigning. Example: holberton[98] = 402 6 | * L2 - Appending. Example: holberton.append(98) 7 | * L3 - Concatenating a list of n elements. Example: holberton + [98, 402] 8 | * L4 - Inserting an item at a given position. Example: holberton.insert(98, 402) 9 | * L5 - Removing an element. Example: holberton.remove(98) 10 | * L6 - Removing and returning the last item in the list. Example: holberton.pop() 11 | * L7 - Poping an element at a given position. Example: holberton.pop(98) 12 | * L8 - Clearing a list. Example: holberton.clear() 13 | * L9 - Counting the list. Example: holberton.count() 14 | * L10 - Sorting the list. Example: holberton.sort() 15 | * L11 - Reversing the list. Example: holberton.reverse() 16 | * L12 - Deleting the list. Example: del holberton 17 | 18 | 19 | * 1-python.c - C functions that print some basic info about Python lists. 20 | 21 | * 2-python-c - C functions that print some basic info about Python lists, Python bytes. 22 | 23 | * 3-python-c - C functions that print some basic info about Python lists, Python bytes ans Python float objects. 24 | 25 | * 4-python-c - C functions that print Python strings. 26 | 27 | * 5-python-c - C functions that print Python Integers. 28 | 29 | ## Useful Links: 30 | 31 | * [listobject.h](/usr/include/python3.4/listobject.h) 32 | 33 | * [object.h](/usr/include/python3.4/object.h) 34 | 35 | * [Common Object Structures](https://docs.python.org/3.4/c-api/structures.html) 36 | 37 | * [List Objects](https://docs.python.org/3.4/c-api/list.html) 38 | 39 | * [Byte Object](/usr/include/python3.4/bytesobject.h) 40 | 41 | * [Float Object](/usr/include/python3.4/floatobject.h) 42 | 43 | * [Unicode](https://docs.python.org/3/c-api/unicode.html) 44 | 45 | * [Long Integer Object](/usr/include/python3.4/longintrepr.h) 46 | 47 | * [String conversion and formatting](https://docs.python.org/3/c-api/conversion.html) 48 | -------------------------------------------------------------------------------- /0x0A_CPython/tests/1-test_lists.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | 3 | lib = ctypes.CDLL('./libPyList.so') 4 | lib.print_python_list.argtypes = [ctypes.py_object] 5 | l = ['hello', 'World'] 6 | lib.print_python_list(l) 7 | del l[1] 8 | lib.print_python_list(l) 9 | l = l + [4, 5, 6.0, (9, 8), [9, 8, 1024], "Holberton"] 10 | lib.print_python_list(l) 11 | l = [] 12 | lib.print_python_list(l) 13 | l.append(0) 14 | lib.print_python_list(l) 15 | l.append(1) 16 | l.append(2) 17 | l.append(3) 18 | l.append(4) 19 | lib.print_python_list(l) 20 | l.pop() 21 | lib.print_python_list(l) 22 | -------------------------------------------------------------------------------- /0x0A_CPython/tests/100-tests.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | 3 | lib = ctypes.CDLL('./libPython.so.2') 4 | lib.print_python_int.argtypes = [ctypes.py_object] 5 | i = -1 6 | lib.print_python_int(i) 7 | i = 0 8 | lib.print_python_int(i) 9 | i = 1 10 | lib.print_python_int(i) 11 | i = 123456789 12 | lib.print_python_int(i) 13 | i = -123456789 14 | lib.print_python_int(i) 15 | i = 12345678901 16 | lib.print_python_int(i) 17 | i = 10304719833506056896 18 | lib.print_python_int(i) 19 | i = -9223372036854775808 20 | lib.print_python_int(i) 21 | i = 9223372036854775807 22 | lib.print_python_int(i) 23 | i = 18446744073709551615 24 | lib.print_python_int(i) 25 | i = -18446744073709551615 26 | lib.print_python_int(i) 27 | i = 18446744073709551616 28 | lib.print_python_int(i) 29 | i = 1111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000 30 | lib.print_python_int(i) 31 | i = -1111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000 32 | lib.print_python_int(i) 33 | -------------------------------------------------------------------------------- /0x0A_CPython/tests/2-tests.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | 3 | lib = ctypes.CDLL('./libPython.so') 4 | lib.print_python_list.argtypes = [ctypes.py_object] 5 | lib.print_python_bytes.argtypes = [ctypes.py_object] 6 | s = b"Hello" 7 | lib.print_python_bytes(s); 8 | b = b'\xff\xf8\x00\x00\x00\x00\x00\x00'; 9 | lib.print_python_bytes(b); 10 | b = b'What does the \'b\' character do in front of a string literal?'; 11 | lib.print_python_bytes(b); 12 | l = [b'Hello', b'World'] 13 | lib.print_python_list(l) 14 | del l[1] 15 | lib.print_python_list(l) 16 | l = l + [4, 5, 6.0, (9, 8), [9, 8, 1024], b"Holberton", "Betty"] 17 | lib.print_python_list(l) 18 | l = [] 19 | lib.print_python_list(l) 20 | l.append(0) 21 | lib.print_python_list(l) 22 | l.append(1) 23 | l.append(2) 24 | l.append(3) 25 | l.append(4) 26 | lib.print_python_list(l) 27 | l.pop() 28 | lib.print_python_list(l) 29 | l = ["Holberton"] 30 | lib.print_python_list(l) 31 | lib.print_python_bytes(l); 32 | -------------------------------------------------------------------------------- /0x0A_CPython/tests/3-tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 -u 2 | 3 | import ctypes 4 | 5 | lib = ctypes.CDLL('./libPython.so') 6 | lib.print_python_list.argtypes = [ctypes.py_object] 7 | lib.print_python_bytes.argtypes = [ctypes.py_object] 8 | lib.print_python_float.argtypes = [ctypes.py_object] 9 | s = b"Hello" 10 | lib.print_python_bytes(s); 11 | b = b'\xff\xf8\x00\x00\x00\x00\x00\x00'; 12 | lib.print_python_bytes(b); 13 | b = b'What does the \'b\' character do in front of a string literal?'; 14 | lib.print_python_bytes(b); 15 | l = [b'Hello', b'World'] 16 | lib.print_python_list(l) 17 | del l[1] 18 | lib.print_python_list(l) 19 | l = l + [4, 5, 6.0, (9, 8), [9, 8, 1024], b"Holberton", "Betty"] 20 | lib.print_python_list(l) 21 | l = [] 22 | lib.print_python_list(l) 23 | l.append(0) 24 | lib.print_python_list(l) 25 | l.append(1) 26 | l.append(2) 27 | l.append(3) 28 | l.append(4) 29 | lib.print_python_list(l) 30 | l.pop() 31 | lib.print_python_list(l) 32 | l = ["Holberton"] 33 | lib.print_python_list(l) 34 | lib.print_python_bytes(l); 35 | f = 3.14 36 | lib.print_python_float(f); 37 | l = [-1.0, -0.1, 0.0, 1.0, 3.14, 3.14159, 3.14159265, 3.141592653589793238462643383279502884197169399375105820974944592307816406286] 38 | print(l) 39 | lib.print_python_list(l); 40 | lib.print_python_float(l); 41 | lib.print_python_list(f); 42 | -------------------------------------------------------------------------------- /0x0A_CPython/tests/4-tests.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | 3 | lib = ctypes.CDLL('./libPython.so') 4 | lib.print_python_string.argtypes = [ctypes.py_object] 5 | s = "The spoon does not exist" 6 | lib.print_python_string(s) 7 | s = "ложка не существует" 8 | lib.print_python_string(s) 9 | s = "La cuillère n'existe pas" 10 | lib.print_python_string(s) 11 | s = "勺子不存在" 12 | lib.print_python_string(s) 13 | s = "숟가락은 존재하지 않는다." 14 | lib.print_python_string(s) 15 | s = "スプーンは存在しない" 16 | lib.print_python_string(s) 17 | s = b"The spoon does not exist" 18 | lib.print_python_string(s) 19 | -------------------------------------------------------------------------------- /0x0A_CPython/tests/5-tests.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | 3 | lib = ctypes.CDLL('./libPython.so') 4 | lib.print_python_int.argtypes = [ctypes.py_object] 5 | i = -1 6 | lib.print_python_int(i) 7 | i = 0 8 | lib.print_python_int(i) 9 | i = 1 10 | lib.print_python_int(i) 11 | i = 123456789 12 | lib.print_python_int(i) 13 | i = -123456789 14 | lib.print_python_int(i) 15 | i = 12345678901 16 | lib.print_python_int(i) 17 | i = 10304719833506056896 18 | lib.print_python_int(i) 19 | i = -9223372036854775808 20 | lib.print_python_int(i) 21 | i = 9223372036854775807 22 | lib.print_python_int(i) 23 | i = 18446744073709551615 24 | lib.print_python_int(i) 25 | i = -18446744073709551615 26 | lib.print_python_int(i) 27 | i = 18446744073709551616 28 | lib.print_python_int(i) 29 | i = "1" 30 | lib.print_python_int(i) 31 | -------------------------------------------------------------------------------- /0x0b-strace/EYNTK/ex_0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /** 7 | * main - Starts the program 8 | * @argc : no of command line arguments 9 | * @argv: command line arguments 10 | * Return: on success - 0, on failure - 1 11 | */ 12 | int main(int __attribute__ ((unused)) argc, char **argv) 13 | { 14 | pid_t child_pid; 15 | int status; 16 | 17 | child_pid = fork(); 18 | if (child_pid == 0) 19 | { 20 | ptrace(PTRACE_TRACEME, 0, 0, 0); 21 | execve(argv[1], argv + 1, NULL); 22 | } else 23 | { 24 | wait(&status); 25 | while (WIFSTOPPED(status)) 26 | { 27 | ptrace(PTRACE_SINGLESTEP, child_pid, 0, 0); 28 | printf("single step\n"); 29 | wait(&status); 30 | } 31 | printf("Exit status: %d\n", WEXITSTATUS(status)); 32 | } 33 | return (0); 34 | } 35 | -------------------------------------------------------------------------------- /0x0b-strace/EYNTK/ex_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /** 7 | * main - Starts the program 8 | * @argc : no of command line arguments 9 | * @argv: command line arguments 10 | * Return: on success - 0, on failure - 1 11 | */ 12 | int main(int __attribute__ ((unused)) argc, char **argv) 13 | { 14 | pid_t child_pid; 15 | int status; 16 | 17 | child_pid = fork(); 18 | if (child_pid == 0) 19 | { 20 | ptrace(PTRACE_TRACEME, 0, 0, 0); 21 | execve(argv[1], argv + 1, NULL); 22 | } else 23 | { 24 | wait(&status); 25 | while (WIFSTOPPED(status)) 26 | { 27 | printf("syscall "); 28 | ptrace(PTRACE_SYSCALL, child_pid, 0, 0); 29 | wait(&status); 30 | if (WIFEXITED(status)) 31 | printf("Exit status: %d\n", WEXITSTATUS(status)); 32 | else 33 | printf("return\n"); 34 | } 35 | 36 | } 37 | return (0); 38 | } 39 | -------------------------------------------------------------------------------- /0x0b-strace/EYNTK/ex_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /** 8 | * main - Starts the program 9 | * @argc : no of command line arguments 10 | * @argv: command line arguments 11 | * Return: on success - 0, on failure - 1 12 | */ 13 | int main(int __attribute__ ((unused)) argc, char **argv) 14 | { 15 | pid_t child_pid; 16 | int status; 17 | struct user_regs_struct regs; 18 | 19 | child_pid = fork(); 20 | if (child_pid == 0) 21 | { 22 | ptrace(PTRACE_TRACEME, 0, 0, 0); 23 | execve(argv[1], argv + 1, NULL); 24 | } else 25 | { 26 | while (wait(&status) && !WIFEXITED(status)) 27 | { 28 | ptrace(PTRACE_GETREGS, child_pid, 0, ®s); 29 | printf("%ld\n", (size_t)regs.orig_rax); 30 | ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL); 31 | } 32 | printf("Exit status: %d\n", WEXITSTATUS(status)); 33 | 34 | } 35 | return (0); 36 | } 37 | -------------------------------------------------------------------------------- /0x0b-strace/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc-4.8 2 | CFLAGS = -Wall -Werror -Wextra -pedantic -g 3 | 4 | _SRC = strace_0.c 5 | 6 | SRC = $(patsubst %,$(SDIR)/%,$(_SRC)) 7 | 8 | _OBJ = $(_SRC:.c=.o) 9 | OBJECTS = $(patsubst %,$(ODIR)/%,$(_OBJ)) 10 | 11 | _SRC1 = strace_1.c 12 | 13 | SRC1 = $(patsubst %,$(SDIR)/%,$(_SRC1)) 14 | 15 | _OBJ1 = $(_SRC1:.c=.o) 16 | OBJECTS1 = $(patsubst %,$(ODIR)/%,$(_OBJ1)) 17 | 18 | _SRC2 = strace_2.c \ 19 | utils.c 20 | 21 | SRC2 = $(patsubst %,$(SDIR)/%,$(_SRC2)) 22 | 23 | _OBJ2 = $(_SRC2:.c=.o) 24 | OBJECTS2 = $(patsubst %,$(ODIR)/%,$(_OBJ2)) 25 | 26 | _SRC3 = strace_3.c \ 27 | utils.c 28 | 29 | SRC3 = $(patsubst %,$(SDIR)/%,$(_SRC3)) 30 | 31 | _OBJ3 = $(_SRC3:.c=.o) 32 | OBJECTS3 = $(patsubst %,$(ODIR)/%,$(_OBJ3)) 33 | 34 | _SRC4 = strace_4.c \ 35 | utils.c 36 | 37 | SRC4 = $(patsubst %,$(SDIR)/%,$(_SRC4)) 38 | 39 | _OBJ4 = $(_SRC4:.c=.o) 40 | OBJECTS4 = $(patsubst %,$(ODIR)/%,$(_OBJ4)) 41 | 42 | _SRC5 = strace_5.c \ 43 | utils.c 44 | 45 | SRC5 = $(patsubst %,$(SDIR)/%,$(_SRC5)) 46 | 47 | _OBJ5 = $(_SRC5:.c=.o) 48 | OBJECTS5 = $(patsubst %,$(ODIR)/%,$(_OBJ5)) 49 | 50 | _SRC6 = strace_6.c \ 51 | utils.c \ 52 | handle_syscall_macros.c 53 | 54 | SRC6 = $(patsubst %,$(SDIR)/%,$(_SRC6)) 55 | 56 | _OBJ6 = $(_SRC6:.c=.o) 57 | OBJECTS6 = $(patsubst %,$(ODIR)/%,$(_OBJ6)) 58 | 59 | _DEPS = strace.h 60 | DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) 61 | 62 | IDIR = ./inc 63 | SDIR = ./src 64 | ODIR = . 65 | 66 | OUTPUT = strace_0 67 | OUTPUT1 = strace_1 68 | OUTPUT2 = strace_2 69 | OUTPUT3 = strace_3 70 | OUTPUT4 = strace_4 71 | OUTPUT5 = strace_5 72 | OUTPUT6 = strace_6 73 | 74 | $(ODIR)/%.o : $(SDIR)/%.c 75 | $(CC) $(CFLAGS) -c -o $@ $< -I$(IDIR) 76 | 77 | all : $(OUTPUT) $(OUTPUT1) $(OUTPUT2) $(OUTPUT3) $(OUTPUT4) $(OUTPUT5) $(OUTPUT6) 78 | 79 | $(OUTPUT) : $(OBJECTS) 80 | $(CC) -o $@ $^ $(LINKS) 81 | 82 | $(OUTPUT1) : $(OBJECTS1) 83 | $(CC) -o $@ $^ $(LINKS) 84 | 85 | $(OUTPUT2) : $(OBJECTS2) 86 | $(CC) -o $@ $^ $(LINKS) 87 | 88 | $(OUTPUT3) : $(OBJECTS3) 89 | $(CC) -o $@ $^ $(LINKS) 90 | 91 | $(OUTPUT4) : $(OBJECTS4) 92 | $(CC) -o $@ $^ $(LINKS) 93 | 94 | $(OUTPUT5) : $(OBJECTS5) 95 | $(CC) -o $@ $^ $(LINKS) 96 | 97 | $(OUTPUT6) : $(OBJECTS6) 98 | $(CC) -o $@ $^ $(LINKS) 99 | 100 | .PHONY : clean 101 | 102 | clean : 103 | rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT1) $(OBJECTS1) $(OUTPUT2) $(OBJECTS2) $(OUTPUT3) $(OBJECTS3) $(OUTPUT4) $(OBJECTS4) $(OUTPUT5) $(OBJECTS5) $(OUTPUT6) $(OBJECTS6) 104 | 105 | re: $(OBJ) $(OBJ1) $(OBJ2) $(OBJ3) $(OBJ4) $(OBJ5) $(OBJ6) 106 | -------------------------------------------------------------------------------- /0x0b-strace/inc/strace.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRACE_H 2 | #define _STRACE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "syscalls.h" 19 | 20 | typedef int bool; 21 | #define true 1 22 | #define false 0 23 | 24 | #define EXIT_SUCCESS 0 25 | #define EXIT_FAILURE 1 26 | 27 | #ifdef __amd64__ 28 | #define eax rax 29 | #define orig_eax orig_rax 30 | #else 31 | #endif 32 | 33 | bool is_machine_32(void); 34 | unsigned long get_syscall_arg(struct user_regs_struct regs, int n); 35 | char *read_string(pid_t child, unsigned long addr); 36 | void print_arg(unsigned long arg, type_t arg_type, bool deal_null); 37 | void handle_syscall_macros(const char *name, unsigned long arg, int arg_index); 38 | void handle_syscall_access(unsigned long arg); 39 | void handle_syscall_mmap(int arg_index, unsigned long arg); 40 | void handle_syscall_open(unsigned long arg); 41 | #endif 42 | -------------------------------------------------------------------------------- /0x0b-strace/src/strace_0.c: -------------------------------------------------------------------------------- 1 | #include "strace.h" 2 | 3 | /** 4 | * run_tracee - A function that runs a tracee 5 | * @argv: Has path and arguments to be executed 6 | * @envp: environment variables 7 | */ 8 | void run_tracee(char *const argv[], char *const envp[]) 9 | { 10 | if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) 11 | { 12 | perror("Error setting TRACEME"); 13 | exit(EXIT_FAILURE); 14 | } 15 | kill(getpid(), SIGSTOP); 16 | execve(argv[0], argv, envp); 17 | } 18 | 19 | /** 20 | * wait_for_syscall - A function that traps only syscalls 21 | * @child_pid: pid of the tracee to be traced 22 | * Return: 1 if syscall is trapped else 0 23 | */ 24 | int wait_for_syscall(pid_t child_pid) 25 | { 26 | int status; 27 | 28 | while (1) 29 | { 30 | ptrace(PTRACE_SYSCALL, child_pid, 0, 0); 31 | waitpid(child_pid, &status, 0); 32 | if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80) 33 | return (0); 34 | if (WIFEXITED(status)) 35 | return (1); 36 | } 37 | } 38 | 39 | /** 40 | * run_tracer - A function that runs a tracer 41 | * @child_pid: pid of the tracee to be traced 42 | */ 43 | void run_tracer(pid_t child_pid) 44 | { 45 | int status; 46 | struct user_regs_struct regs; 47 | 48 | waitpid(child_pid, &status, 0); 49 | ptrace(PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACESYSGOOD); 50 | while (1) 51 | { 52 | if (wait_for_syscall(child_pid) != 0) 53 | break; 54 | ptrace(PTRACE_GETREGS, child_pid, 0, ®s); 55 | printf("%ld\n", (size_t) regs.orig_rax); 56 | fflush(stdout); 57 | if (wait_for_syscall(child_pid) != 0) 58 | break; 59 | } 60 | } 61 | 62 | /** 63 | * main - Starts the program 64 | * @argc : no of command line arguments 65 | * @argv: command line arguments 66 | * @envp: environment variables 67 | * Return: on success - EXIT_SUCCESS, on failure - EXIT_FAILURE 68 | */ 69 | int main(int argc, char *const argv[], char *const envp[]) 70 | { 71 | pid_t child_pid; 72 | 73 | if (argc < 2) 74 | printf("Usage: %s command [args...]\n", argv[0]); 75 | else 76 | { 77 | child_pid = fork(); 78 | if (child_pid == 0) 79 | { 80 | run_tracee(argv + 1, envp); 81 | } else if (child_pid > 0) 82 | { 83 | run_tracer(child_pid); 84 | } else 85 | { 86 | perror("fork failed"); 87 | exit(EXIT_FAILURE); 88 | } 89 | } 90 | return (EXIT_SUCCESS); 91 | } 92 | -------------------------------------------------------------------------------- /0x0b-strace/src/strace_1.c: -------------------------------------------------------------------------------- 1 | #include "strace.h" 2 | 3 | /** 4 | * run_tracee - A function that runs a tracee 5 | * @argv: Has path and arguments to be executed 6 | * @envp: environment variables 7 | */ 8 | void run_tracee(char *const argv[], char *const envp[]) 9 | { 10 | if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) 11 | { 12 | perror("Error setting TRACEME"); 13 | exit(EXIT_FAILURE); 14 | } 15 | kill(getpid(), SIGSTOP); 16 | execve(argv[0], argv, envp); 17 | } 18 | 19 | /** 20 | * wait_for_syscall - A function that traps only syscalls 21 | * @child_pid: pid of the tracee to be traced 22 | * Return: 1 if syscall is trapped else 0 23 | */ 24 | int wait_for_syscall(pid_t child_pid) 25 | { 26 | int status; 27 | 28 | while (1) 29 | { 30 | ptrace(PTRACE_SYSCALL, child_pid, 0, 0); 31 | waitpid(child_pid, &status, 0); 32 | if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80) 33 | return (0); 34 | if (WIFEXITED(status)) 35 | return (1); 36 | } 37 | } 38 | 39 | /** 40 | * run_tracer - A function that runs a tracer 41 | * @child_pid: pid of the tracee to be traced 42 | */ 43 | void run_tracer(pid_t child_pid) 44 | { 45 | int status; 46 | struct user_regs_struct regs; 47 | 48 | waitpid(child_pid, &status, 0); 49 | ptrace(PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACESYSGOOD); 50 | while (1) 51 | { 52 | if (wait_for_syscall(child_pid) != 0) 53 | break; 54 | ptrace(PTRACE_GETREGS, child_pid, 0, ®s); 55 | printf("%s", syscalls_64_g[(size_t) regs.orig_rax].name); 56 | fflush(stdout); 57 | printf("\n"); 58 | if (wait_for_syscall(child_pid) != 0) 59 | break; 60 | } 61 | } 62 | 63 | /** 64 | * main - Starts the program 65 | * @argc : no of command line arguments 66 | * @argv: command line arguments 67 | * @envp: environment variables 68 | * Return: on success - EXIT_SUCCESS, on failure - EXIT_FAILURE 69 | */ 70 | int main(int argc, char *const argv[], char *const envp[]) 71 | { 72 | pid_t child_pid; 73 | 74 | if (argc < 2) 75 | printf("Usage: %s command [args...]\n", argv[0]); 76 | else 77 | { 78 | child_pid = fork(); 79 | if (child_pid == 0) 80 | { 81 | run_tracee(argv + 1, envp); 82 | } else if (child_pid > 0) 83 | { 84 | run_tracer(child_pid); 85 | } else 86 | { 87 | perror("fork failed"); 88 | exit(EXIT_FAILURE); 89 | } 90 | } 91 | return (EXIT_SUCCESS); 92 | } 93 | -------------------------------------------------------------------------------- /0x0b-strace/src/strace_2.c: -------------------------------------------------------------------------------- 1 | #include "strace.h" 2 | 3 | /** 4 | * run_tracee - A function that runs a tracee 5 | * @argv: Has path and arguments to be executed 6 | * @envp: environment variables 7 | */ 8 | void run_tracee(char *const argv[], char *const envp[]) 9 | { 10 | if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) 11 | { 12 | perror("Error setting TRACEME"); 13 | exit(EXIT_FAILURE); 14 | } 15 | kill(getpid(), SIGSTOP); 16 | execve(argv[0], argv, envp); 17 | } 18 | 19 | /** 20 | * wait_for_syscall - A function that traps only syscalls 21 | * @child_pid: pid of the tracee to be traced 22 | * Return: 1 if syscall is trapped else 0 23 | */ 24 | int wait_for_syscall(pid_t child_pid) 25 | { 26 | int status; 27 | 28 | while (1) 29 | { 30 | ptrace(PTRACE_SYSCALL, child_pid, 0, 0); 31 | waitpid(child_pid, &status, 0); 32 | if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80) 33 | return (0); 34 | if (WIFEXITED(status)) 35 | { 36 | printf(" = ?\n"); 37 | return (1); 38 | } 39 | } 40 | } 41 | 42 | /** 43 | * run_tracer - A function that runs a tracer 44 | * @child_pid: pid of the tracee to be traced 45 | */ 46 | void run_tracer(pid_t child_pid) 47 | { 48 | int status; 49 | struct user_regs_struct regs; 50 | bool arch_32; 51 | 52 | waitpid(child_pid, &status, 0); 53 | arch_32 = is_machine_32(); 54 | 55 | ptrace(PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACESYSGOOD); 56 | while (1) 57 | { 58 | if (wait_for_syscall(child_pid) != 0) 59 | break; 60 | ptrace(PTRACE_GETREGS, child_pid, 0, ®s); 61 | if (arch_32) 62 | printf("%s", 63 | syscalls_32_g[(size_t) regs.orig_rax].name); 64 | else 65 | printf("%s", 66 | syscalls_64_g[(size_t) regs.orig_rax].name); 67 | fflush(stdout); 68 | if (wait_for_syscall(child_pid) != 0) 69 | break; 70 | ptrace(PTRACE_GETREGS, child_pid, 0, ®s); 71 | printf(" = %#lx\n", (unsigned long)regs.rax); 72 | } 73 | } 74 | 75 | /** 76 | * main - Starts the program 77 | * @argc : no of command line arguments 78 | * @argv: command line arguments 79 | * @envp: environment variables 80 | * Return: on success - EXIT_SUCCESS, on failure - EXIT_FAILURE 81 | */ 82 | int main(int argc, char *const argv[], char *const envp[]) 83 | { 84 | pid_t child_pid; 85 | 86 | if (argc < 2) 87 | printf("Usage: %s command [args...]\n", argv[0]); 88 | else 89 | { 90 | child_pid = fork(); 91 | if (child_pid == 0) 92 | { 93 | run_tracee(argv + 1, envp); 94 | } else if (child_pid > 0) 95 | { 96 | run_tracer(child_pid); 97 | } else 98 | { 99 | perror("fork failed"); 100 | exit(EXIT_FAILURE); 101 | } 102 | } 103 | return (EXIT_SUCCESS); 104 | } 105 | -------------------------------------------------------------------------------- /0x0b-strace/src/strace_3.c: -------------------------------------------------------------------------------- 1 | #include "strace.h" 2 | 3 | /** 4 | * run_tracee - A function that runs a tracee 5 | * @argv: Has path and arguments to be executed 6 | * @envp: environment variables 7 | */ 8 | void run_tracee(char *const argv[], char *const envp[]) 9 | { 10 | if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) 11 | { 12 | perror("Error setting TRACEME"); 13 | exit(EXIT_FAILURE); 14 | } 15 | kill(getpid(), SIGSTOP); 16 | execve(argv[0], argv, envp); 17 | } 18 | 19 | /** 20 | * wait_for_syscall - A function that traps only syscalls 21 | * @child_pid: pid of the tracee to be traced 22 | * Return: 1 if syscall is trapped else 0 23 | */ 24 | int wait_for_syscall(pid_t child_pid) 25 | { 26 | int status; 27 | 28 | while (1) 29 | { 30 | ptrace(PTRACE_SYSCALL, child_pid, 0, 0); 31 | waitpid(child_pid, &status, 0); 32 | if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80) 33 | return (0); 34 | if (WIFEXITED(status)) 35 | { 36 | printf(") = ?\n"); 37 | return (1); 38 | } 39 | } 40 | } 41 | 42 | /** 43 | * print_syscall_args - prints values of parameters or arguments passed to 44 | * syscall in hexadecimal 45 | * @regs: structure containing registers info 46 | **/ 47 | void print_syscall_args(struct user_regs_struct regs) 48 | { 49 | int nargs = 0, i = 0; 50 | unsigned long arg; 51 | 52 | nargs = syscalls_64_g[(size_t) regs.orig_rax].nb_params; 53 | for (i = 0; i < nargs; i++) 54 | { 55 | arg = get_syscall_arg(regs, i); 56 | 57 | if (syscalls_64_g[(size_t) regs.orig_rax].params[i] == VARARGS) 58 | printf("..."); 59 | else 60 | printf("%#lx", arg); 61 | if (i < nargs - 1) 62 | printf(", "); 63 | } 64 | } 65 | 66 | /** 67 | * run_tracer - A function that runs a tracer 68 | * @child_pid: pid of the tracee to be traced 69 | */ 70 | void run_tracer(pid_t child_pid) 71 | { 72 | int status; 73 | struct user_regs_struct regs; 74 | bool arch_32; 75 | 76 | waitpid(child_pid, &status, 0); 77 | arch_32 = is_machine_32(); 78 | 79 | ptrace(PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACESYSGOOD); 80 | while (1) 81 | { 82 | if (wait_for_syscall(child_pid) != 0) 83 | break; 84 | ptrace(PTRACE_GETREGS, child_pid, 0, ®s); 85 | if (arch_32) 86 | printf("%s(", 87 | syscalls_32_g[(size_t) regs.orig_rax].name); 88 | else 89 | printf("%s(", 90 | syscalls_64_g[(size_t) regs.orig_rax].name); 91 | print_syscall_args(regs); 92 | fflush(stdout); 93 | if (wait_for_syscall(child_pid) != 0) 94 | break; 95 | ptrace(PTRACE_GETREGS, child_pid, 0, ®s); 96 | printf(") = %#lx\n", (unsigned long)regs.rax); 97 | } 98 | } 99 | 100 | /** 101 | * main - Starts the program 102 | * @argc : no of command line arguments 103 | * @argv: command line arguments 104 | * @envp: environment variables 105 | * Return: on success - EXIT_SUCCESS, on failure - EXIT_FAILURE 106 | */ 107 | int main(int argc, char *const argv[], char *const envp[]) 108 | { 109 | pid_t child_pid; 110 | 111 | if (argc < 2) 112 | printf("Usage: %s command [args...]\n", argv[0]); 113 | else 114 | { 115 | child_pid = fork(); 116 | if (child_pid == 0) 117 | { 118 | run_tracee(argv + 1, envp); 119 | } else if (child_pid > 0) 120 | { 121 | run_tracer(child_pid); 122 | } else 123 | { 124 | perror("fork failed"); 125 | exit(EXIT_FAILURE); 126 | } 127 | } 128 | return (EXIT_SUCCESS); 129 | } 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # System programming & Algorithm ― Linux programming 2 | 3 | This repository contains projects for training in the Linux programming track at [Holberton School](https://holbertonschool.com). All projects are in C and are designed to learn C from a beginners level to the advanced level. 4 | 5 | ## Styling and Specifications 6 | All C programs are complied with gcc 4.8 on Ubuntu 14.04 LTS. They comply with [schools formatting checker](https://github.com/holbertonschool/Betty), based on [Linux Kernel coding style]. All programs were written from the Bash, using Emacs. In most of the exercises, standard library functions were not used, excepts``printf``, ``malloc``, ``free`` and ``exit`` and was required to write the necessary/helper functions. 7 | 8 | ### Compilation 9 | All programs must compile with gcc, using with the flags below: 10 | ``` 11 | gcc -Wall -Werror -Wextra -pedantic main.##.c ##-name.c 12 | ``` 13 | All bash/python scripts require execution permissions: 14 | ``` 15 | chmod u+x file 16 | ``` 17 | All projects with Makefile: 18 | ``` 19 | make 20 | ``` 21 | ### Directories 22 | Each directory is named after a concept and contains ordered exercises from mandatory to advance level, and a README.md with a short description of its files. 23 | ## Author 24 | **Sravanthi Sinha** 25 | I have coded all of these exercises during my software engineering training at [Holberton School](https://holbertonschool.com) and are part of linux programming track curriculum. 26 | * [Linkedin](https://www.linkedin.com/in/sravanthisinha) 27 | --------------------------------------------------------------------------------