summaryrefslogtreecommitdiffstats
path: root/sysinfo.c
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-12-13 14:57:51 +0100
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-12-13 14:57:51 +0100
commita77e7147c1814b4ed19d6abce417c8d8c627cc32 (patch)
tree0827dabe5bea4a5bb26199675e3a4fa52c2905fd /sysinfo.c
downloadfastwriter-a77e7147c1814b4ed19d6abce417c8d8c627cc32.tar.gz
fastwriter-a77e7147c1814b4ed19d6abce417c8d8c627cc32.tar.bz2
fastwriter-a77e7147c1814b4ed19d6abce417c8d8c627cc32.tar.xz
fastwriter-a77e7147c1814b4ed19d6abce417c8d8c627cc32.zip
Initial release
Diffstat (limited to 'sysinfo.c')
-rw-r--r--sysinfo.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/sysinfo.c b/sysinfo.c
new file mode 100644
index 0000000..3805dcc
--- /dev/null
+++ b/sysinfo.c
@@ -0,0 +1,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); \
+ _exit(102); \
+ } \
+ lseek(fd, 0L, SEEK_SET); \
+ if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) { \
+ perror(filename); \
+ fflush(NULL); \
+ _exit(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 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 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_ISBLK(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;
+}