Advertisement
Guest User

Untitled

a guest
Nov 17th, 2017
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.42 KB | None | 0 0
  1. //------------------------------------------------------------------------
  2. // NAME: Stefan Grozev
  3. // CLASS: XIa
  4. // NUMBER: 25
  5. // PROBLEM: #1
  6. // FILE NAME: tail.c (unix file name)
  7. // FILE PURPOSE: this is the file containing the main() function
  8. // няколко реда, които описват накратко
  9. // предназначението на файла
  10. // ...
  11. // Този файл съдържа main() фукнцията, в която са дефинирани променливите
  12. // и извиква дефинираните и инициализирани функции, които четат броя на
  13. // аргументите(имената на файловете), отварят ги, принтират в тандартния
  14. // изход (stdout), разделени със заглавна секция.
  15. //------------------------------------------------------------------------
  16.  
  17. #include <stdio.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <fcntl.h>
  21. #include <unistd.h>
  22. #include <string.h>
  23. #include <errno.h>
  24.  
  25. // printing the last 10 lines of a file
  26. void print_last_lines(int file, const char *filename);
  27.  
  28. // printing the last 10 lines of a standard input
  29. void st_input(int fd);
  30.  
  31. // checks if the arguement is a directory
  32. int is_regular_file(const char *path);
  33.  
  34. int main(int argc, char const *argv[]) {
  35.  
  36.     // стринг в който се записва грешката от perror
  37.     char str[500];
  38.     ssize_t written = 0;
  39.  
  40.     // sets a file descriptor for every file
  41.     if(argc == 1){
  42.         int fd = open("temporaryfile.txt", O_CREAT | O_RDWR);
  43.         st_input(fd);
  44.         print_last_lines(fd, argv[1]);
  45.  
  46.     }
  47.     for(int i = 1; i < argc; i++){
  48.        
  49.         // проверява дали подаденият аргумент е '-' и ако е true създава
  50.         // файлов дескриптор сочещ към нов празен файл "temporary.txt"
  51.         // и извиква функциите st_input и print_last_lines (на долу са описани)
  52.         if(!strcmp(argv[i], "-")){
  53.             int fd = open("temporaryfile.txt", O_CREAT | O_RDWR);
  54.             st_input(fd);
  55.             print_last_lines(fd, argv[i]);
  56.         }else{
  57.  
  58.             // създава файлов дескриптор сочещ към текущият аргумент(файл)
  59.             int file = open(argv[i], O_RDONLY);
  60.  
  61.             // създава променлива съдържаща резултата от функцията is_regular_file
  62.             // с аргумент текущия файл
  63.             int is_regular = is_regular_file(argv[i]);
  64.            
  65.             // изписва заглавие с името на файла, ако са подадени повече от 1 файл
  66.             // и open() е върнала положителен резултат
  67.             if(argc > 2 && file > 0){
  68.            
  69.             write(STDOUT_FILENO, "==> ", 4);
  70.             write(STDOUT_FILENO, argv[i], strlen(argv[i]));
  71.             write(STDOUT_FILENO, " <==\n", 5);
  72.  
  73.         }
  74.             // съобщение за грешка при проблем с отварянето на файла
  75.             if(file <= 0){
  76.  
  77.                 //проверява дали подаденият аргумент е директория
  78.                 if(is_regular < 0){
  79.                     sprintf(str, "tail: error reading '%s'", argv[i]);
  80.                     perror(str);
  81.                 }else{
  82.                     sprintf(str, "tail: cannot open '%s' for reading", argv[i]);
  83.                     perror(str);
  84.                 }
  85.             // ако няма грешка чете файла и изписва съдържанието му в стандартния изход
  86.             }else{
  87.        
  88.                 print_last_lines(file, argv[i]);
  89.  
  90.                 // Принтира нов пред след последния байт от текущия файл и преди заглавието
  91.                 // на следващият
  92.                 if(argc > 2 && i < argc - 1){
  93.                 write(STDOUT_FILENO, "\n", 1);
  94.                 }
  95.                 close(file);
  96.             }
  97.         }
  98.     }
  99.  
  100.  
  101.     return 0;
  102. }
  103.  
  104. //------------------------------------------------------------------------
  105. // FUNCTION: void print_last_lines (име на функцията)
  106. // предназначение на функцията : принтира последните 10 реда от файл
  107. // PARAMETERS: int argc(брой подадени файлове), files[argc], масив съдържащ
  108. // файловите дескриптори за всеки файл.
  109. // списък с параметрите на функцията
  110. // и тяхното значение: buff: буфер в който се записва информацията от
  111. // подадения файл и я записва във стандартният изход, written: съдържа
  112. // резултата колко символа функцията write() е успяла да запише успешно,
  113. // len: съдържа резултата колко символа функцията read() е успяла да прочете
  114. // от подадения файл, pos: contains the offset of the pointer ( in bytes)
  115. // from the beginning of the file, total_lines: брояч, който се увеличава
  116. // всеки път когато char C е получила стойността '\n' и при достигане на 10
  117. // прекратява цикъла, c: read() функцията записва прочетения байт в нея и
  118. // ако е нов ред увеличава total_lines с 1
  119. //------------------------------------------------------------------------
  120.  
  121. void print_last_lines(int file, const char *filename){
  122.  
  123.   char buff[255];
  124.   ssize_t written;
  125.   int len = 1;
  126.   int reading = 1;
  127.  
  128.   off_t pos = lseek(file, 0, SEEK_END);
  129.   size_t total_lines = 0;
  130.   char c;
  131.  
  132. //отмества offset-a от края на файла към началото докато не стигне 10-я ред
  133.   while(pos){
  134.     lseek(file, --pos, SEEK_SET);
  135.     reading = read(file, &c, 1);
  136.     if(reading > 0){
  137.       if(c == '\n'){
  138.         if(total_lines == 10) {
  139.           break;
  140.         } else {
  141.           total_lines++;
  142.         }
  143.       }
  144.     }
  145.  
  146.  // проверка дали функцията read() се е изпълнила успешно
  147.     else if(reading < 0){
  148.         sprintf(buff, "tail: error reading '%s'", filename);
  149.         perror(buff);
  150.     }
  151.  
  152.   }
  153.  // short files handling
  154.   if(c != '\n'){
  155.     write(STDOUT_FILENO, &c, 1);
  156.   }
  157.  
  158.   // изписва съдържанието на подадения файл в стандартният изход
  159.   // докато read() връща стойност различна от 0
  160.   while(len != 0){
  161.     len = read(file, buff, 255);
  162.     if(len == 0){
  163.       break;
  164.     }
  165.  
  166.    //проверка дали read() функцията се е изпълнила успешно
  167.     else if(len < 0){
  168.         sprintf(buff, "tail: error reading '%s'", filename);
  169.         perror(buff);
  170.     }
  171.  
  172.     //записва байт по байт прочетената от файла и записана в
  173.     //буфера информация докато write() не върне 0 (не е записала
  174.     // нищо) или броя на записаните байтове (i) стане равен на
  175.     // броя прочетени байтове (len)
  176.     for(size_t i = 0; i < len; i++){
  177.       written = write(STDOUT_FILENO, buff + i, 1);
  178.       if(written == 0){
  179.         break;
  180.       }
  181.     }
  182.   }
  183. }
  184.  
  185. //------------------------------------------------------------------------
  186. // FUNCTION: st_input (име на функцията)
  187. // предназначение на функцията: чете от стандартния вход и записва данните
  188. // във нов файл озаглавен temporary.txt
  189. // PARAMETERS: fd(file descriptor-a на новосъздаденият файл temporary.txt)
  190. // списък с параметрите на функцията
  191. // и тяхното значение: data: буфер в който се записва информацията от
  192. // стандартният вход и я записва във temporary.txt, written: съдържа
  193. // резултата колко символа функцията write() е успяла да запише успешно,
  194. // len: съдържа резултата колко символа функцията read() е успяла да прочете
  195. // от стандартният вход
  196. //------------------------------------------------------------------------
  197. void st_input(int fd){
  198.     char data[128];
  199.     ssize_t written;
  200.     int len = 1;
  201.     while(len != 0){
  202.         len = read(0, data, 128);
  203.         if(len == 0){
  204.             break;
  205.         }
  206.         for(size_t i = 0; i < len; i++){
  207.             written = write(fd, data + i, 1);
  208.             if(written == 0){
  209.                 break;
  210.             }
  211.         }
  212.     }
  213. }
  214.  
  215. //------------------------------------------------------------------------
  216. // FUNCTION: is_regular_file (име на функцията)
  217. // предназначение на функцията: Проверява дали подадения аргумент е директория
  218. // PARAMETERS: подадения аргумент през стандартния вход
  219. // списък с параметрите на функцията
  220. // и тяхното значение
  221. //------------------------------------------------------------------------
  222. int is_regular_file(const char *path)
  223. {
  224.     struct stat path_stat;
  225.     stat(path, &path_stat);
  226.     return S_ISREG(path_stat.st_mode);
  227. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement