În alcătuirea temei, am construit structura SO_FILE care conține: -un file descriptor/handle pentru fisierul la care ne referim; -un șir de caractere pentru a memora modul de deschidere; -un buffer pentru operatiile de citire/scriere; -o pozitie in acel buffer pentru a continua operațiile de la poziția corectă; -o pozitie in file pentru a retine pozitia reala în fișier; -un flag pentru eroare care se va schimba pe 1 în cazul în care se întâmpină o eroare; -un flag pentru EndOfFile care se va schimba pe 1 când ajung la finalul fișierului; -un șir de caractere pentru a memora ultima operație realizată asupra fișierului astfel încât să putem schimba bufferul și să efectuăm so_fflush/so_fseek în functie de tranziție. Pentru so_fopen primesc ca parametrii calea fisierului și modul de deschidere al fisierului. Aloc spațiu pentru un pointer de tip SO_FILE. Setez flagurile necesare pentru fiecare mod de deschidere (O_TRUNC/O_WRONLY/O_RDONLY etc pentru Linux, respectiv GENERIC_WRITE/GENERIC_READ/ pentru Windows). În cazul în care se întâmpină vreo eroare, valoarea stream->_error este setată pe 1. Dacă nu, fiecare câmp este inițializat. Pentru so_fclose, dezaloc structurile care au necesitat alocare dinamică. Dacă nu există erori se va returna 0, altfel -1. Pentru so_fgetc, încep prin a verifica dacă modul de deschidere al fișierului îmi permite să realizez operația. Dacă mi se permite și constat că ultima operație a fost write, voi afișa bufferul în fișier și îl voi popula cu caractere pentru a citi caractere. Dacă am ajuns la finalul fișierului, setez flagul de EOF. Dacă am din read primesc valoarea -1 în Linux sau dacă din ReadFile se returnează 0, voi seta flagul de error. Pentru so_fputc, încep prin a verifica dacă modul de deschidere al fișierului îmi permite să realizez operația. Dacă mi se permite și constat că ultima operație a fost read, voi goli bufferul și voi realiza un so_fseek pentru a ajunge la poziția corectă în fișier. Dacă bufferul nu este plin, adăugăm caractere în el, altfel vom apela so_fflush pentru a afișa în fișier conținutul. Pentru so_fread, am folosit în mod repetat funcția so_fgetc și am returnat 0 în cazul în care întâmpinăm o eroare sau EOF. Altfel, se returnează numărul de elemente citite. Pentru so_fwrite, am folosit în mod repetat funcția so_fputc. Dacă numărul de caractere scrise este diferit față de cel așteptat, flagul error este setat pe 1. Întoarce numărul de elemente scrise. Pentru so_fseek, în cazul în care ultima operație a fost read, vom renunța la bufferul actual, iar dacă ultima operație a fost write, vom afișa bufferul. Ne folosim de apelul de sistem lseek în Linux și de wrapperul SetFilePointer din Windows pentru a modifica poziția. Pentru so_ftell, se returnează -1 în cazul unei erori. Dacă nu, se returnează poziția în fișier. Pentru so_fflush, se printează bufferul în fișier într-o buclă astfel încât să prevenim situațiile în care scrierea este întreruptă și nu sunt afișate toate caracterele. Pentru so_fileno se returnează file descriptorul/handle-ul corespunzător fișierului. Funcția so_feof returnează valoarea actuală a flagului de EOF. Funcția so_ferror returnează valoarea actuală a flagului de error. Funcția so_popen deschide un pipe materializat printr-un fișier între procesul părinte și cel copil. Am detaliat implementarea prin comentarii în so_stdio.c pentru Linux. Funcția so_pclose închide fișierul folosit ca pipe. *** Linux În functia so_ferror am comentat acea structura pentru că în verificarea cu checkerul execuția nu se mai oprește. De asemenea, testul test_popen_write nu se mai oprește din execuție, iar valgrind --leak-check=full îmi indică o încheiere cu SIGPIPE.