Advertisement
Guest User

fsize

a guest
Jun 29th, 2017
28
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.53 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 MAXNAMELEN          255
  70. #define Dirent              struct dirent
  71.  
  72. /**************************** OPEN / CLOSE / READ ****************************/
  73.  
  74. /* Allocates and returns an instance of DIR configured with the current directory inode information */
  75. DIR *openDirectory (const char *dirName) {
  76.     int fileDescriptor;
  77.     struct stat statBuffer;
  78.     DIR *dp = NULL;
  79.  
  80.     if ((fileDescriptor = open(dirName, O_RDONLY, 0)) == -1) {
  81.         fprintf(stderr, "openDirectory: Couldn't open %s\n", dirName);
  82.         return dp;
  83.     }
  84.  
  85.     if (fstat(fileDescriptor, &statBuffer) == -1) {
  86.         fprintf(stderr, "openDirectory: Couldn't get inode info on %s\n", dirName);
  87.         return dp;
  88.     }
  89.  
  90.     if ((statBuffer.st_mode & S_IFMT) != S_IFDIR) {
  91.         fprintf(stderr, "openDirectory: %s isn't a directory you twat\n", dirName);
  92.         return dp;
  93.     }
  94.  
  95.     if ((dp = malloc(sizeof(DIR))) == NULL) {
  96.         fprintf(stderr, "openDirectory: Couldn't allocate space for DIR\n");
  97.         return dp;
  98.     }
  99.  
  100.     DIR_FD(dp) = fileDescriptor;
  101.     return dp;
  102. }
  103.  
  104. /* Closes an open file, and frees the given DIR instance */
  105. void closeDirectory (DIR *dp) {
  106.     if (dp != NULL) {
  107.         close(DIR_FD(dp));
  108.         free(dp);
  109.     }
  110. }
  111.  
  112. /* Returns consecutive file entires in a DIR. Returns NULL when none remain */
  113. Dirent *readEntry (DIR *dp) {
  114.     struct direct directoryBuffer;
  115.     // DIRSIZ(dp) (((unsigned long)&((struct direct *)0)->d_name + (dp)->d_namlen+1 + 3) & ~3)
  116.     size_t dirSize = DIRSIZ(&directoryBuffer);
  117.     static Dirent e;    // Static, so it persists outside function stack
  118.     int code;
  119.  
  120.     while ((code = (read(DIR_FD(dp), (char *)&directoryBuffer, dirSize))) == dirSize) {
  121.  
  122.         /* If the inode is zero, the file slot is unused/removed */
  123.         if (DIRECT_INODE(&directoryBuffer) == 0) {
  124.             continue;
  125.         }
  126.  
  127.         /* Assign inode number, copy name, add terminating null char */
  128.         DIRENT_INODE(&e) = DIRECT_INODE(&directoryBuffer);
  129.         strncpy(DIRENT_FNAME(&e), DIRECT_FNAME(&directoryBuffer), MAXNAMELEN);
  130.         DIRENT_FNAME(&e)[MAXNAMELEN - 1] = '\0';
  131.  
  132.         return &e; // &e -> ep
  133.     }
  134.  
  135.     if (code == -1) {
  136.         fprintf(stderr, "readEntry: Couldn't read at least one entry.\n");
  137.     }
  138.  
  139.     return NULL;
  140. }
  141.  
  142.  
  143. /**************************** MAIN / FSIZE / MAP *****************************/
  144.  
  145.  
  146. /* Maps the given function to a directory's contents. Ignores self, super directory */
  147. void dmap (void (*f)(const char *), const char *dirName) {
  148.     char path[MAX_PATH];
  149.     DIR *dp;        /* Directory pointer */
  150.     Dirent *ep;     /* Directory-ENTRY pointer */
  151.  
  152.     if ((dp = openDirectory(dirName)) == NULL) {
  153.         fprintf(stderr, "dmap: Couldn't open directory %s\n", dirName);
  154.         return;
  155.     }
  156.  
  157.     while ((ep = readEntry(dp)) != NULL) {
  158.         if (SKIP_NAME(DIRENT_FNAME(ep))) {
  159.             continue;
  160.         }
  161.         if (strlen(dirName) + strlen(DIRENT_FNAME(ep)) + 2 > sizeof(path)) {
  162.             fprintf(stderr, "dmap: Name %s/%s exceeds MAX_PATH (%d)\n", dirName, DIRENT_FNAME(ep), MAX_PATH);
  163.         } else {
  164.             sprintf(path, "%s/%s", dirName, DIRENT_FNAME(ep));
  165.             (*f)(path);
  166.         }
  167.     }
  168.     closeDirectory(dp);
  169. }
  170.  
  171. /* Output file size, or map self to contents if directory */
  172. void fsize (const char *fileName) {
  173.     struct stat statBuffer;
  174.  
  175.     if (stat(fileName, &statBuffer) == -1) {
  176.         fprintf(stderr, "fsize: Couldn't get inode info on %s\n", fileName);
  177.         return;
  178.     }
  179.  
  180.     if ((statBuffer.st_mode & S_IFMT) == S_IFDIR) {
  181.         dmap(fsize, fileName);
  182.     }
  183.  
  184.     fprintf(stdout, "%s\t %8lld bytes\n", fileName, statBuffer.st_size);
  185. }
  186.  
  187. /* Output sizes of specified files, else of local directory */
  188. int main (int argc, const char *argv[]) {
  189.     if (argc == 1) {
  190.         fsize(LOCAL_DIR);
  191.     } else {
  192.         while (--argc > 0) {
  193.             fsize(*(++argv));
  194.         }
  195.     }
  196.     return 0;
  197. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement