/alps/fastwriter

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/fastwriter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <errno.h>

#define MEMINFO_FILE "/proc/meminfo"
#define MTAB_FILE "/etc/mtab"

#define BAD_OPEN_MESSAGE					\
"Error: /proc must be mounted\n"				\
"  To mount /proc at boot you need an /etc/fstab line like:\n"	\
"      /proc   /proc   proc    defaults\n"			\
"  In the meantime, run \"mount /proc /proc -t proc\"\n"

/* This macro opens filename only if necessary and seeks to 0 so
 * that successive calls to the functions are more efficient.
 * It also reads the current contents of the file into the global buf.
 */
#define FILE_TO_BUF(filename) do{				\
    static int fd, local_n;					\
    if ((fd = open(filename, O_RDONLY)) == -1) {		\
	fputs(BAD_OPEN_MESSAGE, stderr);			\
	fflush(NULL);						\
	return -102;						\
    }								\
    lseek(fd, 0L, SEEK_SET);					\
    if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) {	\
	perror(filename);					\
	fflush(NULL);						\
	return -103;						\
    }								\
    buf[local_n] = '\0';					\
    close(fd);							\
}while(0)


typedef struct mem_table_struct {
  const char *name;     /* memory type name */
  unsigned long *slot; /* slot in return struct */
} mem_table_struct;

static int compare_mem_table_structs(const void *a, const void *b){
  return strcmp(((const mem_table_struct*)a)->name,((const mem_table_struct*)b)->name);
}

size_t fastwriter_get_free_memory(void){
  char buf[4096];
  unsigned long kb_main_buffers, kb_main_cached, kb_main_free;
  char namebuf[16]; /* big enough to hold any row name */
  mem_table_struct findme = { namebuf, NULL};
  mem_table_struct *found;
  char *head;
  char *tail;

  const mem_table_struct mem_table[] = {
    {"Buffers",      &kb_main_buffers}, // important
    {"Cached",       &kb_main_cached},  // important
    {"MemFree",      &kb_main_free},    // important
  };
  const int mem_table_count = sizeof(mem_table)/sizeof(mem_table_struct);

  FILE_TO_BUF(MEMINFO_FILE);

  head = buf;
  for(;;){
    tail = strchr(head, ':');
    if(!tail) break;
    *tail = '\0';
    if(strlen(head) >= sizeof(namebuf)){
      head = tail+1;
      goto nextline;
    }
    strcpy(namebuf,head);
    found = bsearch(&findme, mem_table, mem_table_count,
        sizeof(mem_table_struct), compare_mem_table_structs
    );
    head = tail+1;
    if(!found) goto nextline;
    *(found->slot) = strtoul(head,&tail,10);
nextline:
    tail = strchr(head, '\n');
    if(!tail) break;
    head = tail+1;
  }
  
  return (kb_main_buffers + kb_main_cached + kb_main_free) * 1024;
}


int fastwriter_get_file_fs(const char *fname, size_t size, char *fs) {
  int err = 0;
  char buf[4096];
  char *fn;

  char *head;
  char *tail;

  size_t len, max = 0;
  struct stat st;
  
  if ((!fname)||(!fs)||(size < 3)) return EINVAL;
  
  if (*fname == '/') {
    fn = (char*)fname;
  } else {
    if (!getcwd(buf, 4095)) return errno;
    fn = malloc(strlen(fname) + strlen(buf) + 2);
    if (!fn) return ENOMEM;
    sprintf(fn, "%s/%s", buf, fname);
  }
  
  if (!stat(fn, &st)) {
    if (!S_ISREG(st.st_mode)) {
	strcpy(fs, "raw");
	goto clean;
    }
  }
  
  FILE_TO_BUF(MTAB_FILE);

  head = buf;
  for(;;){
    head = strchr(head, ' ');
    if(!head) break;

    head += 1;
    tail = strchr(head, ' ');
    if(!tail) break;
    
    *tail = '\0';

    len = strlen(head);
    if((len <= max)||(strncmp(head, fn, len))) {
      head = tail+1;
      goto nextline;
    }
    
    head = tail + 1;
    tail = strchr(head, ' ');
    if(!tail) break;

    *tail = '\0';

    if (!strncasecmp(head,"root",4)) {
	head = tail+1;
	goto nextline;
    }
    
    max = len;

    if (strlen(head) >= size) err = EFAULT;
    else {
	err = 0;
	strcpy(fs, head);
    }
    
    head = tail+1;
nextline:
    tail = strchr(head, '\n');
    if(!tail) break;
    head = tail+1;
  }

clean:  
  if (fn != fname) free(fn);

  return err;
}