source: trunk/LMDZ.PLUTO/libf/muphypluto/swift_csystem.c @ 3590

Last change on this file since 3590 was 3560, checked in by debatzbr, 5 weeks ago

Addition of the microphysics model in moments.

File size: 19.4 KB
Line 
1/*
2 * Copyright (c) Jeremie Burgalat (2013-2022)
3 * Contributor: Jeremie Burgalat (jeremie.burgalat@univ-reims.fr).
4 *
5 * This file is part of SWIFT
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 * this software and associated documentation files (the "Software"), to deal in
9 * the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 * the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include <errno.h>
26#include <string.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <limits.h>
30#include <string.h>
31#include <libgen.h>
32#include <sys/param.h>  // MAXPATHLEN
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/ioctl.h>
36#include <pwd.h>
37#include <grp.h>
38#include <dirent.h>
39#include <fcntl.h>
40#include <time.h>
41#include <unistd.h>
42#include "swift_csystem.h"
43
44// Hack to get MAXPATHLEN
45#ifndef MAXPATHLEN
46#define MAXPATHLEN 4096
47#endif
48
49/* Get errno */
50int c_get_errno(){
51  int ret = errno;
52  return ret;
53}
54
55/* Get the current working directory */
56char* c_getcwd(){
57  char *tmp;
58  tmp = (char *) malloc((MAXPATHLEN+1)*sizeof(char));
59  memset(tmp,'\0',MAXPATHLEN+1);
60  if (getcwd(tmp,MAXPATHLEN) == NULL) {
61    free(tmp);
62    tmp = NULL;
63  }
64  return tmp;
65}
66
67
68/* Get the realpath of input path and saves it in output path */
69char* c_realpath(const char *input){
70  if (!strlen(input)) {
71    return c_getcwd();
72  }
73  return realpath(input,NULL);
74}
75
76
77/* Get directory name of input path */
78char* c_dirname(const char *in){
79  char *tmp = strdup(in);
80  char *ou = strdup(dirname(tmp));
81  free(tmp);
82  return ou;
83}
84
85/* Get base name of input path */
86char* c_basename(const char *in){
87  char* tmp = strdup(in);
88  char *ou = strdup(basename(tmp));
89  free(tmp);
90  return ou;
91}
92
93/* Get the corresponding name of the given user id */
94char* c_uname(int uid){
95  struct passwd  *pwd;
96  char *name;
97  name = NULL;
98  if ((pwd = getpwuid(uid)) !=  NULL){
99    name = strdup(pwd->pw_name);
100  }
101  return name;
102}
103
104/* Get the corresponding name of the given group id */
105char* c_gname(int gid){
106  struct group *grp;
107  char *name;
108  name = NULL;
109  if ((grp = getgrgid(gid)) != NULL){
110    name = strdup(grp->gr_name);
111  }
112  return name;
113}
114
115/* Get the error message of the given error id */
116char* c_strerror(int err){
117  char *tmp = strdup(strerror(err));
118  if (errno != 0)
119    tmp = "Unknown error\0";
120  return tmp;
121}
122
123
124/* Remove a directory and its contents recursively */
125int c_rmdir_f(const char *path) {
126  DIR *d = opendir(path);
127  size_t path_len = strlen(path);
128  int r = -1;
129  if (d) {
130    struct dirent *p;
131    r = 0;
132    while (!r && (p=readdir(d))) {
133      int r2 = -1;
134      char *buf;
135      size_t len;
136      /* Skip the names "." and ".." as we don't want to recurse on them. */
137      if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) {
138        continue;
139      }
140      len = path_len + strlen(p->d_name) + 2;
141      buf = malloc(len);
142      if (buf) {
143        struct stat statbuf;
144        snprintf(buf, len, "%s/%s", path, p->d_name);
145        if (!stat(buf, &statbuf)) {
146          if (S_ISDIR(statbuf.st_mode)) {
147            r2 = c_rmdir_f(buf);
148          } else {
149            r2 = unlink(buf);
150          }
151        }
152        free(buf);
153      }
154      r = r2;
155    }
156    closedir(d);
157  }
158  if (!r) {
159    r = rmdir(path);
160  return r?errno:0;
161  }
162  return r;
163}
164
165/* Get some file informations */
166int c_fstat(const char *p, int *pe, int *nl, int *ty, int *ui, int *gi,
167            long *si, char a[20], char m[20], char c[20]){
168  struct stat stb;
169  struct tm *t;
170  int ret ;
171  //char *tmp;
172  char tmp[20];
173  *pe = *ty = *ui = *gi = *si = -1 ;
174  if (stat(p, &stb) != -1) {
175    *pe = (int)(stb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
176    *nl = (int)(stb.st_nlink);
177    if (S_ISREG(stb.st_mode)) *ty = 0 + S_ISLNK(stb.st_mode);
178    else if (S_ISDIR(stb.st_mode)) *ty = 2 + S_ISLNK(stb.st_mode) ;
179    else *ty = 4;
180    *ui = (int)stb.st_uid ; *gi = (int)stb.st_gid ; *si = (long)stb.st_size ;
181    t = localtime(&stb.st_atime) ; ret = strftime(tmp, 20, "%F,%T", t);
182    if(ret != 0) {strncpy(a,tmp,20); a[19] = '\0';}else{a[0] = '\0';}
183    t = localtime(&stb.st_mtime) ; ret = strftime(tmp, 20, "%F,%T", t);
184    if(ret != 0) {strncpy(m,tmp,20); m[19] = '\0';}else{m[0] = '\0';}
185    t = localtime(&stb.st_ctime) ; ret = strftime(tmp, 20, "%F,%T", t);
186    if(ret != 0) {strncpy(c,tmp,20); c[19] = '\0';}else{c[0] = '\0';}
187    return 0;
188  }
189  return errno;
190}
191
192/* Create a directory or a file in given path */
193int c_create(const char* path, mode_t mode, int astype, int forced){
194  char *p, *d;
195  mode_t perm, cmask;
196  int eval;
197  // we build a directory
198  if (!astype){
199    if(forced){eval=c_mkdirp(path,mode);}else{eval=c_mkdir(path,mode);}
200  }else{
201    // we build a file
202    if (forced){
203      p = strdup(path) ; if(p == NULL) {return errno;}
204      d = dirname(p) ; free(p) ;
205      if(d == NULL) {return -9;}
206      // we attempts to create parent directory first
207      cmask = umask(0);
208      perm =((S_IRWXU | S_IRWXG | S_IRWXO) & ~(cmask & ~(S_IWUSR | S_IXUSR)));
209      (void)umask(cmask) ;
210      eval = c_mkdirp(d,perm);
211      if(eval){return eval;}
212    }
213    eval = open(path,O_CREAT|O_EXCL,mode);
214    if (eval == -1) {eval=errno;}else{close(eval);eval=0;}
215  }
216  return eval ;
217}
218
219/* Change current working directory */
220int c_chdir(const char *path){
221  if (chdir(path) != 0) return errno ;
222  return 0;
223}
224
225/* Remove a directory */
226int c_rmdir(const char *path){
227 if ( rmdir(path) != 0) return errno;
228  return 0;
229}
230
231/* Check if path is accessible */
232int c_access(const char *path, int perm) {
233  int ret;
234  if (perm<0 && perm >7) perm=0;
235  ret = access(path,perm);
236  if (ret) return errno;
237  return 0;
238}
239
240/* Rename a path */
241int c_rename(const char *old, const char *new){
242  if (rename(old,new) != 0) return errno ;
243  return 0;
244}
245
246/* Change path permissions */
247int c_chmod(const char *path, mode_t mode){
248  if (chmod(path,mode) != 0) return errno ;
249  return 0;
250}
251
252/* Create directory */
253int c_mkdir(const char *path, mode_t mode){
254  if(mkdir(path,mode) == 0) {
255    if (chmod(path, mode) == -1) return errno ;
256    return 0;
257  }else{
258    return errno;
259  }
260}
261
262
263int c_copy(const char *to, const char *from) {
264  int fd_to, fd_from;
265  char buf[4096];
266  ssize_t nread;
267  int saved_errno;
268
269  fd_from = open(from, O_RDONLY);
270  if (fd_from < 0)
271    return -1;
272
273  fd_to = open(to, O_WRONLY | O_CREAT | O_EXCL, 0666);
274  if (fd_to < 0)
275    goto out_error;
276
277  while (nread = read(fd_from, buf, sizeof buf), nread > 0) {
278    char *out_ptr = buf;
279    ssize_t nwritten;
280
281    do {
282      nwritten = write(fd_to, out_ptr, nread);
283
284      if (nwritten >= 0) {
285        nread -= nwritten;
286        out_ptr += nwritten;
287      } else if (errno != EINTR) {
288        goto out_error;
289      }
290    } while (nread > 0);
291  }
292
293  if (nread == 0) {
294    if (close(fd_to) < 0) {
295      fd_to = -1;
296      goto out_error;
297    }
298    close(fd_from);
299    /* Success! */
300    return 0;
301  }
302
303out_error:
304  saved_errno = errno;
305
306  close(fd_from);
307  if (fd_to >= 0)
308    close(fd_to);
309
310  errno = saved_errno;
311  return 1;
312}
313
314/* Remove file from filesytem */
315int c_remove(const char *path){
316  if (remove(path) != 0) return errno ;
317  return 0;
318}
319
320/* Get terminal size */
321int c_termsize(int *rows,int *cols){
322  struct winsize max;
323  int retval ;
324  retval = ioctl(0, TIOCGWINSZ , &max);
325  if (retval != 0) {
326    retval = errno ;
327    *rows = 20 ; *cols = 80 ;
328  }else{
329    *rows = max.ws_row ;
330    *cols = max.ws_col ;
331  }
332  return retval;
333}
334
335/* Get the current umask (in decimal system) */
336int c_umask(){
337  mode_t mask ;
338  mask = umask(S_IRWXU | S_IRWXG | S_IRWXO); (void) umask(mask) ;
339  return (int)mask;
340}
341
342/* ------------------ THIRD PARTY ------------------ */
343
344/*
345 *  Copyright (c) 1983, 1992, 1993
346 *   The Regents of the University of California.  All rights reserved.
347 *
348 *  Redistribution and use in source and binary forms, with or without
349 *  modification, are permitted provided that the following conditions
350 *  are met:
351 *  1. Redistributions of source code must retain the above copyright
352 *     notice, this list of conditions and the following disclaimer.
353 *  2. Redistributions in binary form must reproduce the above copyright
354 *     notice, this list of conditions and the following disclaimer in the
355 *     documentation and/or other materials provided with the distribution.
356 *  3. All advertising materials mentioning features or use of this software
357 *     must display the following acknowledgement:
358 *   This product includes software developed by the University of
359 *  California, Berkeley and its contributors.
360 *  4. Neither the name of the University nor the names of its contributors
361 *     may be used to endorse or promote products derived from this software
362 *     without specific prior written permission.
363 *
364 *  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
365 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
366 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
367 *  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
368 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
369 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
370 *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
371 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
372 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
373 *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
374 *  SUCH DAMAGE.
375 */
376/* Creates directories recursively */
377int c_mkdirp(const char *path, mode_t mode) {
378  struct stat sb;
379  mode_t numask, oumask;
380  int first, last, retval;
381  char *cpath, *p;
382  cpath=strdup(path); if (cpath == NULL) return -1;
383  p = cpath; oumask = 0; retval = 0;
384  if (p[0] == '/') ++p;    /* Skip leading '/'. */
385  for (first = 1, last = 0; !last ; ++p) {
386    if (p[0] == '\0') last = 1;
387    else if (p[0] != '/') continue;
388    *p = '\0';
389    //if (! strlen(p) && p[1] == '\0') last = 1;
390    if (first) {
391      oumask = umask(0);
392      numask = oumask & ~(S_IWUSR | S_IXUSR);
393      (void)umask(numask);
394      first = 0;
395    }
396    if (last) (void)umask(oumask);
397    if (mkdir(cpath, last ? mode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
398      if (errno == EEXIST || errno == EISDIR) {
399        if (stat(cpath, &sb) < 0) {
400          retval = 1; break;
401        } else if (!S_ISDIR(sb.st_mode)) {
402          if (last) errno = EEXIST; else errno = ENOTDIR;
403          retval = 1; break;
404        }
405      } else {
406        retval = 1; break;
407      }
408    }
409    if (!last) *p = '/';
410  }
411  if (!first && !last) (void)umask(oumask);
412  if (!retval){
413    if (chmod(path, mode) == -1)  retval = errno ;
414  } else {
415   retval = errno;
416  }
417  free(cpath);
418  return retval ;
419}
420
421/*
422 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
423 *
424 * @APPLE_LICENSE_HEADER_START@
425 *
426 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
427 * Reserved.  This file contains Original Code and/or Modifications of
428 * Original Code as defined in and that are subject to the Apple Public
429 * Source License Version 1.0 (the 'License').  You may not use this file
430 * except in compliance with the License.  Please obtain a copy of the
431 * License at http://www.apple.com/publicsource and read it before using
432 * this file.
433 *
434 * The Original Code and all software distributed under the License are
435 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
436 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
437 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
438 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
439 * License for the specific language governing rights and limitations
440 * under the License."
441 *
442 * @APPLE_LICENSE_HEADER_END@
443 *
444 * Modified version: J. Burgalat (2015)
445 *
446 */
447
448char* c_relpath(const char *path, const char *reldir) {
449  char start_path[MAXPATHLEN+1];
450  char end_path[MAXPATHLEN+1];
451  char *buf;
452  struct stat st;
453  int i,mc;
454  int last_elem;
455  int prev_path;
456  char *tmp,*cur;
457  buf = NULL;
458
459  if (realpath(reldir,start_path) == NULL)
460    return buf;
461
462  if (realpath(path,end_path) == NULL)
463    return buf;
464
465  // stat the starting path
466  if (stat(start_path, &st) < 0)
467    return buf;
468
469  if ((st.st_mode & S_IFMT) != S_IFDIR) {
470    errno = ENOTDIR;
471    return buf;
472  }
473  if (start_path[strlen(start_path) - 1] != '/')
474    strcat(start_path, "/");
475
476  // stat the ending path path
477  if (stat(end_path, &st) < 0)
478    return buf;
479
480  if ((st.st_mode & S_IFMT) == S_IFDIR
481      && end_path[strlen(end_path) - 1] != '/')
482    strcat(end_path, "/");
483
484  tmp = (char *) malloc((2*MAXPATHLEN+1)*sizeof(char));
485  memset(tmp,'\0',2*MAXPATHLEN+1);
486  cur = tmp;
487  /* strip common prefix */
488  i = 0;
489  last_elem = 0;
490  while (start_path[i] && start_path[i] == end_path[i]) {
491    if (start_path[i] == '/')
492      last_elem = i + 1;
493    i += 1;
494  }
495  prev_path = 0;
496  for (i = last_elem; start_path[i]; i += 1) {
497    if (start_path[i] == '/') {
498      if (prev_path){
499        *cur = '/'; cur++;
500      }
501      strncpy(cur,"..",2) ; cur +=2;
502      prev_path = 1;
503    }
504  }
505  if (end_path[last_elem]) {
506    if (prev_path) {
507      *cur = '/'; cur++;
508    }
509    prev_path = 1;
510    while (end_path[strlen(end_path) - 1] == '/')
511      end_path[strlen(end_path) - 1] = '\0';
512    strcpy(cur,&end_path[last_elem]) ;
513    cur += strlen(&end_path[last_elem]);
514  }
515  if (! prev_path){
516    *cur = '.' ; cur++ ;
517  }
518  // Normally here tmp contains our path. We just need to copy it in buf
519  mc = strlen(tmp)+1;
520  buf = (char *)malloc(mc*sizeof(char));
521  memset(buf,'\0',mc);
522  strncpy(buf,tmp,strlen(tmp));
523  cur = buf;
524  i=0;
525  while (*cur != '\0' && i < mc){
526    cur++;
527    i++;
528  }
529  free(tmp);
530  errno = 0;
531  return buf;
532}
533
534/*
535 * Author:  David Robert Nadeau
536 * Site:    http://NadeauSoftware.com/
537 * License: Creative Commons Attribution 3.0 Unported License
538 *          http://creativecommons.org/licenses/by/3.0/deed.en_US
539 *
540 * Cross-plateform way to get memory usage at a given time in fucking bytes !!
541 *
542 * Usage:
543 *
544 * size_t currentSize = getCurrentRSS( );
545 * size_t peakSize    = getPeakRSS( );
546 */
547
548#if defined(_WIN32)
549#include <windows.h>
550#include <psapi.h>
551#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
552#include <sys/resource.h>
553#if defined(__APPLE__) && defined(__MACH__)
554#include <mach/mach.h>
555#elif(defined(_AIX) || defined(__TOS__AIX__)) ||                                                                               \
556    (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
557#include <procfs.h>
558#endif
559#endif
560
561/**
562 * Returns the peak (maximum so far) resident set size (physical
563 * memory use) measured in bytes, or zero if the value cannot be
564 * determined on this OS.
565 */
566size_t c_getPeakRSS() {
567#if defined(_WIN32)
568    /* Windows -------------------------------------------------- */
569    PROCESS_MEMORY_COUNTERS info;
570    GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
571    return (size_t)info.PeakWorkingSetSize;
572
573#elif(defined(_AIX) || defined(__TOS__AIX__)) ||                                                                               \
574    (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
575    /* AIX and Solaris ------------------------------------------ */
576    struct psinfo psinfo;
577    int fd = -1;
578    if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1)
579        return (size_t)0L; /* Can't open? */
580    if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) {
581        close(fd);
582        return (size_t)0L; /* Can't read? */
583    }
584    close(fd);
585    return (size_t)(psinfo.pr_rssize * 1024L);
586
587#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
588    /* BSD, Linux, and OSX -------------------------------------- */
589    struct rusage rusage;
590    getrusage(RUSAGE_SELF, &rusage);
591#if defined(__APPLE__) && defined(__MACH__)
592    return (size_t)rusage.ru_maxrss;
593#else
594    return (size_t)(rusage.ru_maxrss * 1024L);
595#endif
596
597#else
598    /* Unknown OS ----------------------------------------------- */
599    return (size_t)0L; /* Unsupported. */
600#endif
601}
602
603/**
604 * Returns the current resident set size (physical memory use) measured
605 * in bytes, or zero if the value cannot be determined on this OS.
606 */
607size_t c_getCurrentRSS() {
608#if defined(_WIN32)
609    /* Windows -------------------------------------------------- */
610    PROCESS_MEMORY_COUNTERS info;
611    GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
612    return (size_t)info.WorkingSetSize;
613
614#elif defined(__APPLE__) && defined(__MACH__)
615    /* OSX ------------------------------------------------------ */
616    struct task_basic_info info;
617    mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT;
618    if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &infoCount) != KERN_SUCCESS)
619        return (size_t)0L; /* Can't access? */
620    return (size_t)info.resident_size;
621
622#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
623    /* Linux ---------------------------------------------------- */
624    long rss = 0L;
625    FILE *fp = NULL;
626    if ((fp = fopen("/proc/self/statm", "r")) == NULL)
627        return (size_t)0L; /* Can't open? */
628    if (fscanf(fp, "%*s%ld", &rss) != 1) {
629        fclose(fp);
630        return (size_t)0L; /* Can't read? */
631    }
632    fclose(fp);
633    return (size_t)rss * (size_t)sysconf(_SC_PAGESIZE);
634
635#else
636    /* AIX, BSD, Solaris, and Unknown OS ------------------------ */
637    return (size_t)0L; /* Unsupported. */
638#endif
639}
640
641
642
643/* Get some informatiosn about the OS memory usage (from /proc/meminfo) */
644int c_getSystemMemory(long long int *m_total,long long int *m_available,long long int *m_free){
645    FILE* fp;
646    char buf[1024];
647    char *tmp,*p;
648    int ts;
649    long long int mem1 = 0L,mem2 = 0L,mem3 = 0L;
650    if (m_total) (*m_total) = mem1;
651    if (m_available) (*m_free) = mem2;
652    if (m_free) (*m_free) = mem3;
653    if ((fp = fopen("/proc/meminfo", "r")) == NULL)
654        return 1;
655    while (fgets(buf, sizeof(buf), fp) != NULL){
656        ts = strlen(buf) - 1; buf[ts] = '\0';
657        tmp = strdup(&buf[0]);
658        //tmp = strndup(&buf[0],ts); // GNU extension
659        // check our 3 cases
660        if (ts >= 9 && !strncmp(tmp,"MemTotal:",9)){
661            // extract the two first tokens.
662            p=strtok(tmp, " "); p=strtok(NULL, " ");
663            // convert the value.
664            mem1 = strtoll(p,NULL,10);
665        }
666        if (ts >= 13 && !strncmp(tmp,"MemAvailable:",13)){
667            p=strtok(tmp, " "); p=strtok(NULL, " ");
668            mem2 = strtoll(p,NULL,10);
669        }
670        if (ts >= 8 && !strncmp(tmp,"MemFree:",8)){
671            p=strtok(tmp, " "); p=strtok(NULL, " ");
672            mem3 = strtoll(p,NULL,10);
673        }
674        free(tmp);
675    }
676    fclose(fp);
677    if (m_total) (*m_total) = mem1;
678    if (m_available) (*m_available) = mem2;
679    if (m_free) (*m_free) = mem3;
680    return 0;
681}
Note: See TracBrowser for help on using the repository browser.