Coverity: Core module errors fixed
[scilab.git] / scilab / modules / core / src / c / getmemory.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2005 - INRIA - Allan CORNET
4  * Copyright (C) 2009 - Dan McMahill (Fix of bug 4299 and 4312)
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 /* References
18 @sa http://nixdoc.net/man-pages/Tru64/man2/getsysinfo.2.html
19 @sa http://www.opensource.apple.com/darwinsource/projects/other/gccfast-1621.1/libiberty/physmem.c
20 @sa http://lists.gnu.org/archive/html/bug-gnulib/2003-08/msg00102.html
21 @sa http://netbsd.gw.com/cgi-bin/man-cgi?sysctl+3+NetBSD-4.0
22 @sa http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/math/scilab/patches/patch-aj?annotate=1.9
23 */
24
25 #if defined(__linux__)
26 #define _GNU_SOURCE /* Bug 5673 fix: avoid dependency on GLIBC_2.7 */
27 #endif
28
29 #include "getmemory.h"
30
31 #ifdef _MSC_VER
32 #include <windows.h>
33 #endif
34
35 #if defined(__NetBSD__) || defined(__DragonFly__)
36 #include <sys/param.h>
37 #include <sys/sysctl.h>
38 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
39 #define PAGESHIFT_UNDEF -100
40 #elif defined(__FreeBSD__)
41 #include <sys/param.h>
42 #include <sys/sysctl.h>
43 #endif
44
45
46 #include <string.h>
47 #include <stdio.h>
48 #define kooctet 1024
49 int getfreememory(void)
50 {
51
52 #if defined(_MSC_VER)
53     {
54         MEMORYSTATUS stat;
55         GlobalMemoryStatus (&stat);
56         return (int)(stat.dwAvailPhys / kooctet);
57     }
58 #elif defined(hpux)
59     {
60         struct pst_static pst;
61         /*        pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0);
62               memorysizeKO=(pst.psd_free)/kooctet;*/
63         return 0;
64     }
65 #elif defined(__APPLE__)
66     {
67         vm_statistics_data_t page_info;
68         vm_size_t pagesize;
69         mach_msg_type_number_t count;
70         kern_return_t kret;
71
72         pagesize = 0;
73         kret = host_page_size (mach_host_self(), &pagesize);
74         count = HOST_VM_INFO_COUNT;
75
76         kret = host_statistics (mach_host_self(), HOST_VM_INFO, (host_info_t)&page_info, &count);
77         return page_info.free_count * pagesize / 1024;
78     }
79 #elif HAVE_TABLE && defined TBL_VMSTATS
80     {
81         /* This works on Tru64 UNIX V4/5.  */
82         struct tbl_vmstats vmstats;
83
84         if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
85         {
86             double pages = vmstats.free_count;
87             double pagesize = vmstats.pagesize;
88
89             if (0 <= pages && 0 <= pagesize)
90             {
91                 return pages * pagesize;
92             }
93             else
94             {
95                 return 0;
96             }
97         }
98     }
99 #elif defined(__linux__)
100     {
101         char field[9]  = {0};
102         long long data =  0;
103         char unit[4]   = {0};
104
105         long long free    = -1,
106                   buffers = -1,
107                   cached  = -1;
108
109         FILE *fp = fopen("/proc/meminfo", "r");
110         if (fp != NULL)
111         {
112             /* Read Cached, Buffers and MemFree from /proc/meminfo */
113             while (fscanf(fp, "%8s %lld %3s\n", field, &data, unit) != EOF)
114             {
115                 if (!strncmp("MemFree:", field, 8))
116                 {
117                     free = data;
118                 }
119                 else if (!strncmp("Buffers:", field, 8))
120                 {
121                     buffers = data;
122                 }
123                 else if (!strncmp("Cached:", field, 8))
124                 {
125                     cached = data;
126                 }
127             }
128             fclose(fp);
129
130             /* Read successful, convert unit and return the result */
131             if (buffers >= 0 && cached >= 0 && free >= 0)
132             {
133                 free += cached + buffers;
134                 switch (unit[0])
135                 {
136                     case 'g':
137                     case 'G':
138                         free *= kooctet*kooctet;
139                         break;
140                     case 'm':
141                     case 'M':
142                         free *= kooctet;
143                         break;
144                     case 'o':
145                     case 'O':
146                         free /= kooctet;
147                         break;
148                 }
149                 return (int)free;
150             }
151         }
152
153         /* Strange, /proc not mounted ? new and unknown format ?
154            fall back to inaccurate sysconf() */
155         return (sysconf(_SC_AVPHYS_PAGES) * sysconf(_SC_PAGESIZE)) / kooctet;
156     }
157 #elif defined(__NetBSD__) || defined(__DragonFly__)
158     {
159         /* This works on *bsd.  */
160         int mib[2];
161         struct uvmexp_sysctl uvmexp;
162         long freemem;
163         size_t lenu = sizeof uvmexp;
164         unsigned int pagesize;
165         static int pageshift = PAGESHIFT_UNDEF;
166         size_t lenp = sizeof pagesize;
167
168         mib[0] = CTL_HW;
169         if (pageshift == PAGESHIFT_UNDEF)
170         {
171             /* Figure out the page size */
172             mib[1] = HW_PAGESIZE;
173             if (sysctl (mib, ARRAY_SIZE (mib), &pagesize, &lenp, NULL, 0) != 0 || lenp != sizeof (pagesize) )
174             {
175                 /* sysctl failed -- what to do?? */
176                 return 0;
177             }
178             pageshift = 0;
179             while (pagesize > 1)
180             {
181                 pageshift++;
182                 pagesize >>= 1;
183             }
184
185             /* convert to kB */
186             pageshift -= 10;
187         }
188
189         mib[0] = CTL_VM;
190         mib[1] = VM_UVMEXP2;
191         if ( (sysctl (mib, ARRAY_SIZE (mib), &uvmexp, &lenu, NULL, 0) == 0) && (lenu == sizeof (uvmexp)) )
192         {
193             return  (uvmexp.free << pageshift);
194         }
195
196         return 0;
197     }
198 #elif defined(__FreeBSD__)
199     int avphys_pages;
200     size_t oldlenp = sizeof (avphys_pages);
201     sysctlbyname("vm.stats.vm.v_free_count", &avphys_pages, &oldlenp, NULL, NULL);
202     return (avphys_pages / kooctet) * sysconf(_SC_PAGESIZE);
203
204 #else
205     /* Solaris and others assumed*/
206     return (sysconf(_SC_AVPHYS_PAGES) / kooctet) * sysconf(_SC_PAGESIZE);
207 #endif
208 }
209 /*--------------------------------------------------------------------------*/
210 int getmemorysize()
211 {
212 #if defined(_MSC_VER)
213     {
214         MEMORYSTATUS stat;
215         GlobalMemoryStatus (&stat);
216         return (int)(stat.dwTotalPhys / kooctet);
217     }
218 #elif defined(hpux)
219     {
220         struct pst_static pst;
221         pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0);
222         return (int)((pst.physical_memory) / kooctet);
223     }
224 #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__DragonFly__)
225     {
226         /* this works on *bsd and darwin */
227         size_t len;
228         int total;
229         int mib[2];
230
231         mib[0] = CTL_HW;
232         mib[1] = HW_PHYSMEM;
233         len = sizeof (total);
234
235         sysctl(mib, 2, &total, &len, NULL, 0);
236         return  total / 1024;
237     }
238 #elif HAVE_GETSYSINFO && defined GSI_PHYSMEM
239     {
240         /* This works on Tru64 UNIX V4/5.  */
241         int physmem;
242
243         if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
244         NULL, NULL, NULL) == 1)
245         {
246             double kbytes = physmem;
247
248             if (0 <= kbytes)
249             {
250                 return kbytes * 1024.0;
251             }
252             else
253             {
254                 return 0;
255             }
256         }
257     }
258 #else
259     /* Linux ,Solaris and others */
260     return (sysconf(_SC_PHYS_PAGES) / kooctet) * sysconf(_SC_PAGESIZE);
261 #endif
262 }
263 /*--------------------------------------------------------------------------*/