summaryrefslogtreecommitdiff
path: root/src/fdleak.c
blob: 726417097b1f767528a7b7c7375c74262455ae27 (plain)
    1 /**
    2  * FDleak leaks dead file descriptors (and cleans them up)
    3  * Copyright (C) 2022  Aaron Ball, nullspoon@oper.io
    4  *
    5  * This program is free software: you can redistribute it and/or modify
    6  * it under the terms of the GNU General Public License as published by
    7  * the Free Software Foundation, either version 3 of the License, or
    8  * (at your option) any later version.
    9  *
   10  * This program is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  * GNU General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU General Public License
   16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   17  */
   18 #include <stdio.h>
   19 #include <stdlib.h>
   20 #include <unistd.h> // Provides unlink
   21 #include <signal.h>
   22 #include <string.h>
   23 #include <errno.h>
   24 
   25 #include <sys/resource.h>
   26 
   27 FILE** FDS;
   28 
   29 void cleanup() {
   30   long i = 0;
   31   printf("Freeing leaked files\n");
   32   while(FDS[i] != NULL) {
   33     printf("Closing leaked file %ld\n", i);
   34     fclose(FDS[i]);
   35     i++;
   36   }
   37   free(FDS);
   38 }
   39 
   40 void handler(int sig) {
   41   cleanup();
   42   exit(128);
   43 }
   44 
   45 FILE* leakfd(char* path) {
   46   FILE* fd = NULL;
   47   fd = fopen(path, "w");
   48   if(!fd)
   49     return NULL;
   50   fprintf(fd, "Ohhai!\n");
   51   fflush(fd);
   52   unlink(path); // Ahhhhhh
   53   return fd;    // Much logic, very sense
   54 }
   55 
   56 int main(int argc, char* argv[]) {
   57   long count = 0;
   58   long i = 0;
   59   char fdpath[256];
   60   signal(SIGINT, handler);
   61   struct rlimit rl;
   62 
   63   // Set soft limit to max
   64   getrlimit(RLIMIT_NOFILE, &rl);
   65   rl.rlim_cur = rl.rlim_max;
   66 
   67   if(setrlimit(RLIMIT_NOFILE, &rl) != 0) {
   68     printf("Error setting soft limit on open files\n");
   69     printf("%s\n", strerror(errno));
   70     return 1;
   71   }
   72 
   73   if(argc == 1) {
   74     printf("Desccriptor leak count required\n");
   75     return 1;
   76   }
   77   count = strtol(argv[1], NULL, 10);
   78 
   79   // Block at 3 less than max because stdin, stdout, and stderr
   80   if(count > (rl.rlim_cur) - 3) {
   81     printf("ERROR: Requested FD leaks exceeds allowed maximum of %ld\n",
   82       rl.rlim_cur - 3);
   83     return 1;
   84   }
   85 
   86   // Allocate memory for descriptor array
   87   FDS = malloc((sizeof(FILE*) * count) + 1);
   88   memset(FDS, 0, count + 1);
   89 
   90   while(i < count) {
   91     sprintf(fdpath, "/tmp/fdleak-%ld.txt", i);
   92     printf("Leaking file %s\n", fdpath);
   93     FDS[i] = leakfd(fdpath);
   94     if(FDS[i] == NULL) {
   95       cleanup();
   96       printf("ERROR opening file descriptor %ld, %s\n", i, fdpath);
   97       printf("%s\n", strerror(errno));
   98       return 1;
   99     }
  100     i++;
  101   }
  102 
  103   printf("Done. Press Enter to free memory.\n");
  104   fgetc(stdin);
  105   cleanup();
  106 
  107   return 0;
  108 }

Generated by cgit