Advertisement
Guest User

Untitled

a guest
Mar 29th, 2012
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.60 KB | None | 0 0
  1. /**
  2.  * @file myfind.c
  3.  * Betriebssysteme MyFind File.
  4.  * Beispiel 1
  5.  *
  6.  * @author
  7.  * @author
  8.  * @author
  9.  *
  10.  * @date 2012/03/01
  11.  *
  12.  * @version $Revision: 11 $
  13.  *
  14.  * @todo action-handling
  15.  *
  16.  * URL: $HeadURL$
  17.  *
  18.  * Last Modified: $Author: markus $
  19.  */
  20.  
  21. /*
  22.  * -------------------------------------------------------------- includes --
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <sys/types.h>
  27. #include <dirent.h>
  28. #include <string.h>
  29. #include <sys/stat.h>
  30. #include <stdlib.h>
  31. #include <time.h>
  32. #include <pwd.h>
  33. #include <grp.h>
  34. #include <unistd.h>
  35. #include <fnmatch.h>
  36. #include <stdlib.h>
  37.  
  38.  
  39.  
  40.  
  41. /*
  42.  * --------------------------------------------------------------- defines --
  43.  */
  44.  
  45. #define PATHLEN 256
  46. enum BOOLEAN {FALSE, TRUE};
  47.  
  48. enum Type
  49. {
  50.   b,  /**< block */
  51.   c,  /**< character */
  52.   d,  /**< directory */
  53.   p,  /**< named pipe (FIFO) */
  54.   f,  /**< regular file */
  55.   l,  /**< symbolic link; */
  56.   s   /**<  socket */
  57. };
  58.  
  59.  
  60. /*
  61.  * -------------------------------------------------------------- typedefs --
  62.  */
  63.  
  64. typedef struct Options {
  65.         char * dirname;
  66.         char * name;
  67.         char * user;
  68.         char * path;
  69.         char * type;
  70.         int ls;
  71.         int nouser;
  72.         int print;
  73. }Options;
  74.  
  75. /*
  76.  * --------------------------------------------------------------- globals --
  77.  */
  78.  
  79. /*
  80.  * ------------------------------------------------------------- functions --
  81.  */
  82.  
  83. int do_dir(const char * dir_name, Options * params);
  84.  
  85. void do_file(const char * file_name, Options * params, const struct stat * file_stats, const char * current_file);
  86.  
  87. void usage();
  88.  
  89. Options init_options();
  90.  
  91. Options get_options (int num, char * params[]);
  92.  
  93. void input_check(int num, char * params[], char * prog);
  94.  
  95. int getpermissionstring(char * str, const int mode);
  96.  
  97. void print_ls(const char * file_name, const struct stat * file_stats);
  98.  
  99.  
  100. /**
  101.  *
  102.  * \brief The most minimalistic C program
  103.  *
  104.  * This is the main entry point for any C program.
  105.  *
  106.  * \param argc the number of arguments
  107.  * \param argv the arguments itselves (including the program name in argv[0])
  108.  *
  109.  * \return always "success"
  110.  * \retval 0 always
  111.  *
  112.  */
  113. int main(int argc, char* argv[])
  114. {
  115.     Options action;
  116.  
  117.     action = get_options(argc, argv);
  118.    
  119.     switch(do_dir(action.dirname,&action))
  120.     {
  121.         case 0: exit(EXIT_FAILURE);
  122.                 break;
  123.         case 1: exit(EXIT_SUCCESS);
  124.                 break;
  125.     }
  126.     return 0;
  127. }
  128.  
  129. /**
  130.  *
  131.  * \brief walk through directories/subdirectories
  132.  *
  133.  * walk through directories/subdirectories and calls for each entry
  134.  * function do_file
  135.  *
  136.  * \param dir_name directory-name
  137.  * \param parms used parameter
  138.  *
  139.  * \return unable to open or close directory
  140.  * \return success
  141.  * \retval EXIT_SUCCESS
  142.  * \retval EXIT_FAILURE
  143.  */
  144. int do_dir(const char * dir_name, Options * params){
  145.  
  146.     DIR *dir=NULL;
  147.     struct dirent *dirent=NULL;
  148.     char fpath[1024]="";
  149.     struct stat st;
  150.  
  151.     /* open directory */
  152.     if((dir=opendir(dir_name)) == NULL)
  153.     {
  154.      if (lstat(dir_name, &st) == -1)
  155.      {
  156.         perror("stat");
  157.         return 0;
  158.      }
  159.      
  160.      if (S_ISDIR(st.st_mode))
  161.      {
  162.         fprintf(stderr,"myfind: unable to open directory %s \n", dir_name);
  163.         return 0;
  164.      }       
  165.      else
  166.      { 
  167.         do_file(dir_name,params,&st,dir_name);
  168.         return 1;
  169.      }     
  170.     }
  171.  
  172.     /* walk through the directory */
  173.     while((dirent=readdir(dir)) != NULL)
  174.     {
  175.          /* ignore current and parent directory */
  176.          if ( (strcmp(dirent->d_name, ".") == 0) || (strcmp(dirent->d_name, "..") == 0) )
  177.             continue;
  178.          
  179.          /* necessary because readdir returns relative Path, to the entry before */
  180.          memset(fpath, 0, sizeof(fpath));
  181.          snprintf(fpath,sizeof(fpath),"%s/%s", dir_name, dirent->d_name);
  182.        
  183.          if (lstat(fpath, &st) == -1)
  184.          {
  185.             perror("stat");
  186.             return 0;
  187.          }
  188.  
  189.          do_file(fpath,params,&st, dirent->d_name);
  190.          
  191.          if (S_ISDIR(st.st_mode))
  192.             do_dir(fpath,params);
  193.     }
  194.  
  195.     /* close directory */
  196.     if(closedir(dir) == -1)
  197.     {
  198.         fprintf(stderr,"myfind: unable to close directory %s\n", dir_name);
  199.         return 0;
  200.        
  201.     }
  202.     return 1;
  203. }
  204.  
  205. /**
  206.  *
  207.  * \brief analyzes each directory-entry
  208.  *
  209.  * analyzes each directory-entry on the basis of the given parameters
  210.  * if all parameters matches the entry is printed out
  211.  *
  212.  * \param file_name file/directory name
  213.  * \param parms used parameter
  214.  * \param file_stats file stats
  215.  *
  216.  * \return void
  217.  */
  218. void do_file(const char * file_name, Options * params, const struct stat * file_stats, const char * current_file){
  219.  
  220.     int name_flag = TRUE;
  221.     int user_flag = TRUE;
  222.     int path_flag = TRUE;
  223.     int type_flag = TRUE;
  224.     int nouser_flag = TRUE;
  225.    
  226.     if(params->name != NULL){
  227.         if(fnmatch(params->name, current_file, FNM_NOESCAPE| FNM_PERIOD))
  228.         {
  229.             name_flag = FALSE;
  230.         }
  231.     }
  232.    
  233.     if(params->path != NULL){
  234.         if(fnmatch(params->path, file_name, FNM_PATHNAME))
  235.         {
  236.             path_flag = FALSE;
  237.         }
  238.     }
  239.  
  240.     if(params->user != NULL)
  241.     {
  242.         long int uid;
  243.  
  244.         /* is parameter user a uid or name */
  245.         if((uid=strtol(params->user,NULL,0)))
  246.         {
  247.             if(uid!=file_stats->st_uid)
  248.                 user_flag = FALSE;
  249.         }
  250.         else
  251.         {
  252.             if(strcmp(params->user,getpwuid(file_stats->st_uid)->pw_name))
  253.                 user_flag = FALSE;
  254.         }
  255.     }
  256.  
  257.     if(params->type != NULL)
  258.     {
  259.         int searchtype = f;
  260.         int filetype = f;
  261.  
  262.         switch (params->type[0])
  263.         {
  264.                 case 'p': searchtype = p; break; /* named pipe (FIFO) */
  265.                 case 'c': searchtype = c; break; /* character special */
  266.                 case 'd': searchtype = d; break; /* directory */
  267.                 case 'b': searchtype = b; break; /* block special */
  268.                 case 'f': searchtype = f; break; /* regular file */
  269.                 case 'l': searchtype = l; break; /* symbolic link */
  270.                 case 's': searchtype = s; break; /* socket */
  271.  
  272.                 default: fprintf(stderr,"myfind: invalid argument '%s' to `-type' \n", params->type);
  273.                          usage();
  274.                          break;
  275.         }
  276.  
  277.         switch (file_stats->st_mode & 0xffffc00)
  278.         {
  279.                 case 0x1000: filetype = p; break; /* named pipe (FIFO) */
  280.                 case 0x2000: filetype = c; break; /* character special */
  281.                 case 0x4000: filetype = d; break; /* directory */
  282.                 case 0x6000: filetype = b; break; /* block special */
  283.                 case 0x8000: filetype = f; break; /* regular file */
  284.                 case 0xa000: filetype = l; break; /* symbolic link */
  285.                 case 0xc000: filetype = s; break; /* socket */
  286.  
  287.                 default: fprintf(stderr,"myfind: unknown type !!! %x", file_stats->st_mode & 0xffffc00);
  288.                          usage();
  289.                          break;
  290.         }
  291.  
  292.         if(searchtype != filetype)
  293.                 type_flag = FALSE;
  294.     }
  295.    
  296.     if(params->nouser == TRUE)
  297.     {
  298.         /* is user in /etc/passwd file */
  299.         if (getpwuid(file_stats->st_uid))
  300.             nouser_flag = FALSE;
  301.         else
  302.             nouser_flag = TRUE;
  303.     }
  304.  
  305.     if (name_flag == TRUE && user_flag == TRUE && path_flag == TRUE && type_flag == TRUE && nouser_flag == TRUE)
  306.     {
  307.         if(params->ls == TRUE){
  308.             print_ls(file_name,file_stats);
  309.         }
  310.        
  311.         if(params->print == TRUE){
  312.             printf("%s\n",file_name);
  313.         }
  314.     }
  315. }
  316.  
  317. /**
  318.  *
  319.  * \brief print usage informations and exit programm
  320.  *
  321.  * \return void
  322.  */
  323. void usage()
  324. {
  325.         fprintf(stderr, "usage: myfind <directory> [ <action> ] ...\n");
  326.         exit(1);
  327. }
  328.  
  329.  
  330. /**
  331.  *
  332.  * \brief initialisation of the option structure
  333.  * \return Options
  334.  */
  335. Options init_options(){
  336.         Options init;
  337.         init.dirname = NULL;
  338.         init.name = NULL;
  339.         init.path = NULL;
  340.         init.type = NULL;
  341.         init.user = NULL;
  342.         init.nouser = FALSE;
  343.         init.ls = FALSE;
  344.         init.print = TRUE;
  345.  
  346.         return init;
  347. }
  348. /**
  349.  *
  350.  * \brief fill the option structur with the params of the command-line
  351.  *
  352.  * checks if all given params from the command-line are correct
  353.  * an return the filled option structure
  354.  * \param num number of the given params (from the command-line)
  355.  * \param params array with all params (from the command-line)
  356.  *
  357.  * \return Options
  358.  */
  359. Options get_options (int num, char * params[]){
  360.         Options action = init_options();
  361.         int i = 0;
  362.         int count = 0;
  363.         char * prog;
  364.  
  365.         if (num < 2)
  366.          usage();
  367.        
  368.         prog=params[0];
  369.         action.dirname = *(++params);
  370.        
  371.         if (num==2)
  372.             action.print = TRUE;
  373.            
  374.         num--;
  375.        
  376.         input_check(num, params, prog);
  377.    
  378.         for(i=1;i<num;i++){
  379.             if (0 == strcmp("-name", params[i])){
  380.                 i++;
  381.                 if(action.name == NULL)    
  382.                     action.name = params[i];
  383.                 else
  384.                     count++;
  385.                 continue;
  386.             }
  387.             else if(0 == strcmp("-user", params[i])){
  388.                 i++;
  389.                 if(action.user == NULL)
  390.                     action.user = params[i];
  391.                 else
  392.                     count++;
  393.                 continue;
  394.             }
  395.             else if(0 == strcmp("-path", params[i])){
  396.                 i++;
  397.                 if(action.path == NULL)
  398.                     action.path = params[i];
  399.                 else
  400.                     count++;
  401.                 continue;
  402.             }
  403.             else if(0 == strcmp("-type", params[i])){
  404.                 i++;
  405.                 if(action.type == NULL)
  406.                     action.type = params[i];
  407.                 else
  408.                     count++;
  409.                 continue;
  410.             }
  411.             else if(0 == strcmp("-ls", params[i])){
  412.                 action.ls = TRUE;
  413.                 action.print = FALSE;
  414.                 if(count == 0)
  415.                     do_dir(action.dirname,&action);
  416.                 /* unset LS */
  417.                 action.ls = FALSE;
  418.                 count = 0;
  419.                 continue;
  420.             }
  421.             else if(0 == strcmp("-nouser", params[i])){
  422.                 action.nouser = TRUE;
  423.                 continue;
  424.             }
  425.             else if(0 == strcmp("-print", params[i])){
  426.                 action.print = TRUE;
  427.                 if(count == 0)
  428.                     do_dir(action.dirname,&action);
  429.                 /* unset Print */
  430.                 action.print = FALSE;
  431.                 count = 0;
  432.                 continue;
  433.             }
  434.             else {
  435.                 continue;
  436.             }
  437.  
  438.         }
  439.         return action;
  440. }
  441.  
  442. /**
  443.  *
  444.  * \brief checks if myfind has the correct syntax
  445.  *
  446.  * checks if all given params from the command-line are correct
  447.  * \param num number of the given params (from the command-line)
  448.  * \param params array with all params (from the command-line)
  449.  *
  450.  */
  451.  
  452. void input_check(int num, char * params[], char * prog){
  453.     int i = 0;
  454.    
  455.     for(i=1;i<num;i++){
  456.         if (0 == strcmp("-name", params[i])){
  457.             i++;
  458.             if (num == i){
  459.                 fprintf(stderr,"%s: missing argument to `-name'\n", prog);
  460.                 usage();
  461.             }
  462.             continue;
  463.         }
  464.         else if(0 == strcmp("-user", params[i])){
  465.             i++;
  466.             if (num == i){
  467.                 fprintf(stderr,"%s: missing argument to `-user'\n", prog);
  468.                 usage();
  469.             }
  470.             continue;
  471.         }
  472.         else if(0 == strcmp("-path", params[i])){
  473.             i++;
  474.             if (num == i){
  475.                 fprintf(stderr,"%s: missing argument to `-path'\n", prog);
  476.                 usage();
  477.             }
  478.             continue;
  479.         }
  480.         else if(0 == strcmp("-type", params[i])){
  481.             i++;
  482.             if (num == i){
  483.                 fprintf(stderr,"%s: missing argument to `-type'\n", prog);
  484.                 usage();
  485.             }
  486.             if (params[i][1] != '\0'){
  487.                 printf("myfind: invalid argument '%s' to `-type' \n",params[i]);
  488.                 usage();
  489.             }
  490.  
  491.             switch (params[i][0])
  492.             {
  493.                 case 'p': break; /* named pipe (FIFO) */
  494.                 case 'c': break; /* character special */
  495.                 case 'd': break; /* directory */
  496.                 case 'b': break; /* block special */
  497.                 case 'f': break; /* regular file */
  498.                 case 'l': break; /* symbolic link */
  499.                 case 's': break; /* socket */
  500.  
  501.                 default: printf("myfind: invalid argument '%s' to `-type' \n", params[i]);
  502.                          usage();
  503.                          break;
  504.             }  
  505.             continue;
  506.         }
  507.         else if(0 == strcmp("-ls", params[i])){
  508.             continue;
  509.         }
  510.         else if(0 == strcmp("-nouser", params[i])){
  511.             continue;
  512.         }
  513.         else if(0 == strcmp("-print", params[i])){
  514.             continue;
  515.         }
  516.         else {
  517.             fprintf(stderr,"%s: %s: unknown action\n", prog, params[i]);
  518.                 usage();
  519.             }
  520.         }
  521. }
  522.  
  523.  
  524.  
  525. /* ----------------------------------------------------------------------- */
  526. /**
  527. \brief writes the permission-string
  528. \param str the string in which should be written
  529. \param mode the mode of the file (lstat-type)
  530. \return the type of the file (int)
  531.  ----------------------------------------------------------------------- */
  532. int getpermissionstring(char * str, const int mode)
  533. {
  534.   char type = '-'; int ret = f;
  535.    
  536.   switch (mode & 0xffffc00)
  537.   {
  538.     case 0x1000: type = 'p'; ret = p; break; /* named pipe (FIFO) */
  539.     case 0x2000: type = 'c'; ret = c; break; /* character special */
  540.     case 0x4000: type = 'd'; ret = d; break; /* directory */
  541.     case 0x6000: type = 'b'; ret = b; break; /* block special */
  542.     case 0x8000: type = '-'; ret = f; break; /* regular file */
  543.     case 0xa000: type = 'l'; ret = l; break; /* symbolic link */
  544.     case 0xc000: type = 's'; ret = s; break; /* socket */
  545.  
  546.     default: printf("myfind: getpermissionstring: unknown type %x", mode & 0xffffc00); break;
  547.   }
  548.  
  549.   snprintf(str, 11, "%c%c%c%c%c%c%c%c%c%c",
  550.             type,
  551.             (mode & 0x0100) ? 'r' : '-',
  552.             (mode & 0x0080) ? 'w' : '-',
  553.             (mode & 0x0040) ? 'x' : '-',
  554.            
  555.             (mode & 0x0020) ? 'r' : '-',
  556.             (mode & 0x0010) ? 'w' : '-',
  557.             (mode & 0x0008) ? 'x' : '-',
  558.  
  559.             (mode & 0x0004) ? 'r' : '-',
  560.             (mode & 0x0002) ? 'w' : '-',
  561.             (mode & 0x0200) ? 't' : (mode & 0x0001) ? 'x' : '-' /* sticky b */
  562.           );
  563.          
  564.   return (ret);
  565. }
  566.  
  567.  
  568. void print_ls(const char * file_name, const struct stat * file_stats)
  569. {
  570.   char timestr[13];  char perm[11];
  571.   struct tm brtm = *(localtime(&file_stats->st_mtime));
  572.   int type = f;
  573.   int linklen;
  574.   char link_location[PATHLEN];
  575.   char link[PATHLEN];
  576.  
  577.   strftime(timestr, 13, "%b %d %H:%M", &brtm);
  578.   type = getpermissionstring(perm, file_stats->st_mode);
  579.  
  580.   if(type == l)
  581.   {
  582.         linklen = readlink(file_name, link_location, sizeof(link_location) - 1);
  583.         if (linklen == -1){
  584.             fprintf(stderr,"myfind: unable to read link of file: %s \n", file_name);
  585.             link[0] = '\0';
  586.         }
  587.         else{
  588.             link_location[linklen] = '\0';
  589.             snprintf(link,sizeof(link),"-> %s",link_location);
  590.         }
  591.   }
  592.  
  593.   printf("%6ld %4ld %s %3d %-8s %-8s %8ld %s %s %s\n",
  594.         file_stats->st_ino,
  595.         file_stats->st_blocks,
  596.         perm,
  597.         (int) file_stats->st_nlink,
  598.         getpwuid(file_stats->st_uid)->pw_name,
  599.         getgrgid(file_stats->st_gid)->gr_name,
  600.         file_stats->st_size,
  601.         timestr,
  602.         file_name,
  603.         (type==l) ? link : " ");
  604. }
  605.  
  606. /*
  607.  * =================================================================== eof ==
  608.  */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement