source: trunk/LMDZ.TITAN/libf/muphytitan/csystem.c @ 3094

Last change on this file since 3094 was 3090, checked in by slebonnois, 15 months ago

BdeBatz? : Cleans microphysics and makes few corrections for physics

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