Advertisement
Guest User

fsize

a guest
Jun 29th, 2017
31
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.49 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #include <sys/file.h>   //  FOR: read, write. IF NOT ON MACOS/BSD, TRY: <fcntl.h>
  6. #include <unistd.h>     //  FOR: read, write flags. IF NOT ON MACOS/BSD, TRY: <fcntl.h>
  7.  
  8. #include <sys/types.h>  //  FOR: types within struct stat
  9. #include <sys/dir.h>    //  FOR: struct direct
  10. #include <sys/stat.h>   //  FOR: stat, fstat
  11. #include <sys/dirent.h> //  FOR: Dirent
  12.  
  13.  
  14. /*************************** TYPEDEF & STRUCTURES ****************************/
  15.  
  16. #if defined(DO_NOT_DEFINE)
  17.  
  18. /* structure describing an open directory for macOS. */
  19. typedef struct {
  20.     int __dd_fd;    /* file descriptor associated with directory */
  21.     long    __dd_loc;   /* offset in current buffer */
  22.     long    __dd_size;  /* amount of data returned */
  23.     char    *__dd_buf;  /* data buffer */
  24.     int __dd_len;   /* size of data buffer */
  25.     long    __dd_seek;  /* magic cookie returned */
  26.     long    __dd_rewind;    /* magic cookie for rewinding */
  27.     int __dd_flags; /* flags for readdir */
  28.     __darwin_pthread_mutex_t __dd_lock; /* for thread locking */
  29.     struct _telldir *__dd_td; /* telldir position recording */
  30. } DIR;
  31.  
  32. /* structure describing dirent for freeBSD because fuck macOS */
  33. struct dirent {
  34.          __uint32_t d_fileno;        /* file number of entry */
  35.          __uint16_t d_reclen;        /* length of this record */
  36.          __uint8_t  d_type;          /* file type, see below */
  37.          __uint8_t  d_namlen;        /* length of string in d_name */
  38.      #ifdef _POSIX_SOURCE
  39.          char    d_name[255 + 1];        /* name must be no longer than this */
  40.      #else
  41.      #define MAXNAMLEN       255
  42.          char    d_name[MAXNAMLEN + 1];  /* name must be no longer than this */
  43.      #endif
  44. };
  45.  
  46. #endif
  47.  
  48. /**************************** SYMBOLIC CONSTANTS *****************************/
  49.  
  50. #define LOCAL_DIR           "."
  51. #define SUPER_DIR           ".."
  52. #define SKIP_NAME(n)        ((strcmp((n), LOCAL_DIR) == 0) || (strcmp((n), SUPER_DIR) == 0))
  53.  
  54. /* FILE NAMES */
  55. #define DIRENT_FNAME(ep)    ((ep)->d_name)    // FROM: Directory "Entry" structure
  56. #define DIRECT_FNAME(drp)   ((drp)->d_name) // FROM: 'struct direct' type (not DIR or DIRENT)
  57. #define DIR_FNAME(dp)       ((dp)->name)    // FROM: Directory structure
  58.  
  59. /* FILE DESCRIPTORS */
  60. #define DIR_FD(dp)          ((dp)->__dd_fd)      // FROM: Directory structure
  61.  
  62. /* FILE INODES */
  63. #define DIRENT_INODE(ep)    ((ep)->d_fileno)   // FROM: Directory "Entry" structure
  64. #define DIRECT_INODE(drp)   ((drp)->d_ino)  // FROM: 'struct direct' type (not DIR or dirent)
  65.  
  66.  
  67. /* CUSTOM DEFINITIONS */
  68. #define MAX_PATH            1024    // Maximum length for a filename within a directory
  69. #define Dirent              struct dirent
  70.  
  71. /**************************** OPEN / CLOSE / READ ****************************/
  72.  
  73. /* Allocates and returns an instance of DIR configured with the current directory inode information */
  74. DIR *openDirectory (const char *dirName) {
  75.     int fileDescriptor;
  76.     struct stat statBuffer;
  77.     DIR *dp = NULL;
  78.  
  79.     if ((fileDescriptor = open(dirName, O_RDONLY, 0)) == -1) {
  80.         fprintf(stderr, "openDirectory: Couldn't open %s\n", dirName);
  81.         return dp;
  82.     }
  83.  
  84.     if (fstat(fileDescriptor, &statBuffer) == -1) {
  85.         fprintf(stderr, "openDirectory: Couldn't get inode info on %s\n", dirName);
  86.         return dp;
  87.     }
  88.  
  89.     if ((statBuffer.st_mode & S_IFMT) != S_IFDIR) {
  90.         fprintf(stderr, "openDirectory: %s isn't a directory you twat\n", dirName);
  91.         return dp;
  92.     }
  93.  
  94.     if ((dp = malloc(sizeof(DIR))) == NULL) {
  95.         fprintf(stderr, "openDirectory: Couldn't allocate space for DIR\n");
  96.         return dp;
  97.     }
  98.  
  99.     DIR_FD(dp) = fileDescriptor;
  100.     return dp;
  101. }
  102.  
  103. /* Closes an open file, and frees the given DIR instance */
  104. void closeDirectory (DIR *dp) {
  105.     if (dp != NULL) {
  106.         close(DIR_FD(dp));
  107.         free(dp);
  108.     }
  109. }
  110.  
  111. /* Returns consecutive file entires in a DIR. Returns NULL when none remain */
  112. Dirent *readEntry (DIR *dp) {
  113.     struct direct directoryBuffer;
  114.     // DIRSIZ(dp) (((unsigned long)&((struct direct *)0)->d_name + (dp)->d_namlen+1 + 3) & ~3)
  115.     size_t dirSize = DIRSIZ(&directoryBuffer);
  116.     static Dirent e;    // Static, so it persists outside function stack
  117.     int code;
  118.  
  119.     while ((code = (read(DIR_FD(dp), (char *)&directoryBuffer, dirSize))) == dirSize) {
  120.  
  121.         /* If the inode is zero, the file slot is unused/removed */
  122.         if (DIRECT_INODE(&directoryBuffer) == 0) {
  123.             continue;
  124.         }
  125.  
  126.         /* Assign inode number, copy name, add terminating null char */
  127.         DIRENT_INODE(&e) = DIRECT_INODE(&directoryBuffer);
  128.         strncpy(DIRENT_FNAME(&e), DIRECT_FNAME(&directoryBuffer), dirSize);
  129.         DIRENT_FNAME(&e)[dirSize] = '\0';
  130.  
  131.         return &e; // &e -> ep
  132.     }
  133.  
  134.     if (code == -1) {
  135.         fprintf(stderr, "readEntry: Couldn't read at least one entry.\n");
  136.     }
  137.  
  138.     return NULL;
  139. }
  140.  
  141.  
  142. /**************************** MAIN / FSIZE / MAP *****************************/
  143.  
  144.  
  145. /* Maps the given function to a directory's contents. Ignores self, super directory */
  146. void dmap (void (*f)(const char *), const char *dirName) {
  147.     char path[MAX_PATH];
  148.     DIR *dp;        /* Directory pointer */
  149.     Dirent *ep;     /* Directory-ENTRY pointer */
  150.  
  151.     if ((dp = openDirectory(dirName)) == NULL) {
  152.         fprintf(stderr, "dmap: Couldn't open directory %s\n", dirName);
  153.         return;
  154.     }
  155.  
  156.     while ((ep = readEntry(dp)) != NULL) {
  157.         if (SKIP_NAME(DIRENT_FNAME(ep))) {
  158.             continue;
  159.         }
  160.         if (strlen(dirName) + strlen(DIRENT_FNAME(ep)) + 2 > sizeof(path)) {
  161.             fprintf(stderr, "dmap: Name %s/%s exceeds MAX_PATH (%d)\n", dirName, DIRENT_FNAME(ep), MAX_PATH);
  162.         } else {
  163.             sprintf(path, "%s/%s", dirName, DIRENT_FNAME(ep));
  164.             (*f)(path);
  165.         }
  166.     }
  167.     closeDirectory(dp);
  168. }
  169.  
  170. /* Output file size, or map self to contents if directory */
  171. void fsize (const char *fileName) {
  172.     struct stat statBuffer;
  173.  
  174.     if (stat(fileName, &statBuffer) == -1) {
  175.         fprintf(stderr, "fsize: Couldn't get inode info on %s\n", fileName);
  176.         return;
  177.     }
  178.  
  179.     if ((statBuffer.st_mode & S_IFMT) == S_IFDIR) {
  180.         dmap(fsize, fileName);
  181.     }
  182.  
  183.     fprintf(stdout, "%s: %8lld bytes", fileName, statBuffer.st_size);
  184. }
  185.  
  186. /* Output sizes of specified files, else of local directory */
  187. int main (int argc, const char *argv[]) {
  188.     if (argc == 1) {
  189.         fsize(LOCAL_DIR);
  190.     } else {
  191.         while (--argc > 0) {
  192.             fsize(*(++argv));
  193.         }
  194.     }
  195.     return 0;
  196. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement