mountlist.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. /* mountlist.c -- return a list of mounted filesystems
  2. Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
  14. #include <config.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <sys/types.h>
  18. /* This header needs to be included before sys/mount.h on *BSD */
  19. #ifdef HAVE_SYS_PARAM_H
  20. #include <sys/param.h>
  21. #endif
  22. #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
  23. #include <sys/mount.h>
  24. #include <sys/fs_types.h>
  25. #endif /* MOUNTED_GETFSSTAT */
  26. #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
  27. #include <mntent.h>
  28. #if !defined(MOUNTED)
  29. #if defined(MNT_MNTTAB) /* HP-UX. */
  30. #define MOUNTED MNT_MNTTAB
  31. #endif
  32. #if defined(MNTTABNAME) /* Dynix. */
  33. #define MOUNTED MNTTABNAME
  34. #endif
  35. #endif
  36. #endif
  37. #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
  38. #include <sys/mount.h>
  39. #endif
  40. #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
  41. #include <sys/statvfs.h>
  42. #endif
  43. #ifdef MOUNTED_GETMNT /* Ultrix. */
  44. #include <sys/mount.h>
  45. #include <sys/fs_types.h>
  46. #endif
  47. #ifdef MOUNTED_FREAD /* SVR2. */
  48. #include <mnttab.h>
  49. #endif
  50. #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
  51. #include <mnttab.h>
  52. #include <sys/fstyp.h>
  53. #include <sys/statfs.h>
  54. #endif
  55. #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
  56. #include <sys/mnttab.h>
  57. #endif
  58. #ifdef MOUNTED_VMOUNT /* AIX. */
  59. #include <fshelp.h>
  60. #include <sys/vfs.h>
  61. #endif
  62. #ifdef HAVE_SYS_STATFS_H
  63. #include <sys/statfs.h>
  64. #endif
  65. #ifdef HAVE_INFOMOUNT_QNX
  66. #include <sys/disk.h>
  67. #include <sys/fsys.h>
  68. #endif
  69. #ifdef HAVE_SYS_MOUNT_H
  70. #include <sys/mount.h>
  71. #endif
  72. #ifdef HAVE_SYS_VFS_H
  73. #include <sys/vfs.h>
  74. #endif
  75. #ifdef HAVE_SYS_FILSYS_H
  76. #include <sys/filsys.h> /* SVR2. */
  77. #endif
  78. #ifdef HAVE_DUSTAT_H /* AIX PS/2. */
  79. #include <sys/dustat.h>
  80. #endif
  81. #ifdef HAVE_SYS_STATVFS_H /* SVR4. */
  82. #include <sys/statvfs.h>
  83. #endif
  84. #include "global.h"
  85. #include "mountlist.h"
  86. #include "util.h"
  87. #ifdef DOLPHIN
  88. /* So special that it's not worth putting this in autoconf. */
  89. #undef MOUNTED_FREAD_FSTYP
  90. #define MOUNTED_GETMNTTBL
  91. #endif
  92. #if defined (__QNX__) && !defined(__QNXNTO__) && !defined (HAVE_INFOMOUNT_LIST)
  93. # define HAVE_INFOMOUNT_QNX
  94. #endif
  95. #if defined(HAVE_INFOMOUNT_LIST) || defined(HAVE_INFOMOUNT_QNX)
  96. # define HAVE_INFOMOUNT
  97. #endif
  98. /* A mount table entry. */
  99. struct mount_entry
  100. {
  101. char *me_devname; /* Device node pathname, including "/dev/". */
  102. char *me_mountdir; /* Mount point directory pathname. */
  103. char *me_type; /* "nfs", "4.2", etc. */
  104. dev_t me_dev; /* Device number of me_mountdir. */
  105. struct mount_entry *me_next;
  106. };
  107. struct fs_usage
  108. {
  109. fsblkcnt_t fsu_blocks; /* Total blocks. */
  110. fsblkcnt_t fsu_bfree; /* Free blocks available to superuser. */
  111. fsblkcnt_t fsu_bavail; /* Free blocks available to non-superuser. */
  112. fsfilcnt_t fsu_files; /* Total file nodes. */
  113. fsfilcnt_t fsu_ffree; /* Free file nodes. */
  114. };
  115. static int get_fs_usage (char *path, struct fs_usage *fsp);
  116. #ifdef HAVE_INFOMOUNT_LIST
  117. static struct mount_entry *mount_list = NULL;
  118. #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
  119. /* Return the value of the hexadecimal number represented by CP.
  120. No prefix (like '0x') or suffix (like 'h') is expected to be
  121. part of CP. */
  122. static int xatoi (const char *cp)
  123. {
  124. int val;
  125. val = 0;
  126. while (*cp) {
  127. if (*cp >= 'a' && *cp <= 'f')
  128. val = val * 16 + *cp - 'a' + 10;
  129. else if (*cp >= 'A' && *cp <= 'F')
  130. val = val * 16 + *cp - 'A' + 10;
  131. else if (*cp >= '0' && *cp <= '9')
  132. val = val * 16 + *cp - '0';
  133. else
  134. break;
  135. cp++;
  136. }
  137. return val;
  138. }
  139. #endif /* MOUNTED_GETMNTENT1 */
  140. #ifdef MOUNTED_GETMNTINFO
  141. #ifndef HAVE_STRUCT_STATFS_F_FSTYPENAME
  142. static char *fstype_to_string (short t)
  143. {
  144. switch (t) {
  145. #ifdef MOUNT_PC
  146. case MOUNT_PC:
  147. return "pc";
  148. #endif
  149. #ifdef MOUNT_MFS
  150. case MOUNT_MFS:
  151. return "mfs";
  152. #endif
  153. #ifdef MOUNT_LO
  154. case MOUNT_LO:
  155. return "lo";
  156. #endif
  157. #ifdef MOUNT_TFS
  158. case MOUNT_TFS:
  159. return "tfs";
  160. #endif
  161. #ifdef MOUNT_TMP
  162. case MOUNT_TMP:
  163. return "tmp";
  164. #endif
  165. #ifdef MOUNT_UFS
  166. case MOUNT_UFS:
  167. return "ufs" ;
  168. #endif
  169. #ifdef MOUNT_NFS
  170. case MOUNT_NFS:
  171. return "nfs" ;
  172. #endif
  173. #ifdef MOUNT_MSDOS
  174. case MOUNT_MSDOS:
  175. return "msdos" ;
  176. #endif
  177. #ifdef MOUNT_LFS
  178. case MOUNT_LFS:
  179. return "lfs" ;
  180. #endif
  181. #ifdef MOUNT_LOFS
  182. case MOUNT_LOFS:
  183. return "lofs" ;
  184. #endif
  185. #ifdef MOUNT_FDESC
  186. case MOUNT_FDESC:
  187. return "fdesc" ;
  188. #endif
  189. #ifdef MOUNT_PORTAL
  190. case MOUNT_PORTAL:
  191. return "portal" ;
  192. #endif
  193. #ifdef MOUNT_NULL
  194. case MOUNT_NULL:
  195. return "null" ;
  196. #endif
  197. #ifdef MOUNT_UMAP
  198. case MOUNT_UMAP:
  199. return "umap" ;
  200. #endif
  201. #ifdef MOUNT_KERNFS
  202. case MOUNT_KERNFS:
  203. return "kernfs" ;
  204. #endif
  205. #ifdef MOUNT_PROCFS
  206. case MOUNT_PROCFS:
  207. return "procfs" ;
  208. #endif
  209. #ifdef MOUNT_AFS
  210. case MOUNT_AFS:
  211. return "afs" ;
  212. #endif
  213. #ifdef MOUNT_CD9660
  214. case MOUNT_CD9660:
  215. return "cd9660" ;
  216. #endif
  217. #ifdef MOUNT_UNION
  218. case MOUNT_UNION:
  219. return "union" ;
  220. #endif
  221. #ifdef MOUNT_DEVFS
  222. case MOUNT_DEVFS:
  223. return "devfs" ;
  224. #endif
  225. #ifdef MOUNT_EXT2FS
  226. case MOUNT_EXT2FS:
  227. return "ext2fs" ;
  228. #endif
  229. default:
  230. return "?";
  231. }
  232. }
  233. #endif /* ! HAVE_STRUCT_STATFS_F_FSTYPENAME */
  234. #endif /* MOUNTED_GETMNTINFO */
  235. #ifdef MOUNTED_VMOUNT /* AIX. */
  236. static char *
  237. fstype_to_string (int t)
  238. {
  239. struct vfs_ent *e;
  240. e = getvfsbytype (t);
  241. if (!e || !e->vfsent_name)
  242. return "none";
  243. else
  244. return e->vfsent_name;
  245. }
  246. #endif /* MOUNTED_VMOUNT */
  247. /* Return a list of the currently mounted filesystems, or NULL on error.
  248. Add each entry to the tail of the list so that they stay in order.
  249. If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in
  250. the returned list are valid. Otherwise, they might not be.
  251. If ALL_FS is zero, do not return entries for filesystems that
  252. are automounter (dummy) entries. */
  253. static struct mount_entry *
  254. read_filesystem_list (int need_fs_type, int all_fs)
  255. {
  256. struct mount_entry *mlist;
  257. struct mount_entry *me;
  258. struct mount_entry *mtail;
  259. (void) need_fs_type;
  260. (void) all_fs;
  261. /* Start the list off with a dummy entry. */
  262. me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
  263. me->me_next = NULL;
  264. mlist = mtail = me;
  265. #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
  266. #ifdef MOUNTED
  267. {
  268. struct mntent *mnt;
  269. FILE *fp;
  270. const char *devopt;
  271. fp = setmntent (MOUNTED, "r");
  272. if (fp == NULL)
  273. return NULL;
  274. while ((mnt = getmntent (fp))) {
  275. if (!all_fs && (!strcmp (mnt->mnt_type, "ignore")
  276. || !strcmp (mnt->mnt_type, "auto")))
  277. continue;
  278. me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
  279. me->me_devname = strdup (mnt->mnt_fsname);
  280. me->me_mountdir = strdup (mnt->mnt_dir);
  281. me->me_type = strdup (mnt->mnt_type);
  282. devopt = strstr (mnt->mnt_opts, "dev=");
  283. if (devopt) {
  284. if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
  285. me->me_dev = xatoi (devopt + 6);
  286. else
  287. me->me_dev = xatoi (devopt + 4);
  288. } else
  289. me->me_dev = -1; /* Magic; means not known yet. */
  290. me->me_next = NULL;
  291. /* Add to the linked list. */
  292. mtail->me_next = me;
  293. mtail = me;
  294. }
  295. if (endmntent (fp) == 0)
  296. return NULL;
  297. }
  298. #endif /* MOUNTED */
  299. #endif /* MOUNTED_GETMNTENT1 */
  300. #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
  301. {
  302. struct statfs *fsp;
  303. int entries;
  304. entries = getmntinfo (&fsp, MNT_NOWAIT);
  305. if (entries < 0)
  306. return NULL;
  307. while (entries-- > 0) {
  308. me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
  309. me->me_devname = strdup (fsp->f_mntfromname);
  310. me->me_mountdir = strdup (fsp->f_mntonname);
  311. #ifdef HAVE_STRUCT_STATFS_F_FSTYPENAME
  312. me->me_type = strdup (fsp->f_fstypename);
  313. #else
  314. me->me_type = fstype_to_string (fsp->f_type);
  315. #endif
  316. me->me_dev = -1; /* Magic; means not known yet. */
  317. me->me_next = NULL;
  318. /* Add to the linked list. */
  319. mtail->me_next = me;
  320. mtail = me;
  321. fsp++;
  322. }
  323. }
  324. #endif /* MOUNTED_GETMNTINFO */
  325. #ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */
  326. {
  327. struct statvfs *fsp;
  328. int entries;
  329. entries = getmntinfo (&fsp, MNT_NOWAIT);
  330. if (entries < 0)
  331. return NULL;
  332. for (; entries-- > 0; fsp++) {
  333. me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
  334. me->me_devname = strdup (fsp->f_mntfromname);
  335. me->me_mountdir = strdup (fsp->f_mntonname);
  336. me->me_type = strdup (fsp->f_fstypename);
  337. me->me_dev = (dev_t) -1; /* Magic; means not known yet. */
  338. /* Add to the linked list. */
  339. mtail->me_next = me;
  340. mtail = me;
  341. }
  342. }
  343. #endif /* MOUNTED_GETMNTINFO2 */
  344. #ifdef MOUNTED_GETMNT /* Ultrix. */
  345. {
  346. int offset = 0;
  347. int val;
  348. struct fs_data fsd;
  349. while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY,
  350. NULL)) > 0) {
  351. me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
  352. me->me_devname = strdup (fsd.fd_req.devname);
  353. me->me_mountdir = strdup (fsd.fd_req.path);
  354. me->me_type = gt_names[fsd.fd_req.fstype];
  355. me->me_dev = fsd.fd_req.dev;
  356. me->me_next = NULL;
  357. /* Add to the linked list. */
  358. mtail->me_next = me;
  359. mtail = me;
  360. }
  361. if (val < 0)
  362. return NULL;
  363. }
  364. #endif /* MOUNTED_GETMNT */
  365. #ifdef MOUNTED_GETFSSTAT /* __alpha running OSF_1 */
  366. {
  367. int numsys, counter, bufsize;
  368. struct statfs *stats;
  369. numsys = getfsstat ((struct statfs *) 0, 0L, MNT_WAIT);
  370. if (numsys < 0)
  371. return (NULL);
  372. bufsize = (1 + numsys) * sizeof (struct statfs);
  373. stats = (struct statfs *) malloc (bufsize);
  374. numsys = getfsstat (stats, bufsize, MNT_WAIT);
  375. if (numsys < 0) {
  376. free (stats);
  377. return (NULL);
  378. }
  379. for (counter = 0; counter < numsys; counter++) {
  380. me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
  381. me->me_devname = strdup (stats[counter].f_mntfromname);
  382. me->me_mountdir = strdup (stats[counter].f_mntonname);
  383. me->me_type = mnt_names[stats[counter].f_type];
  384. me->me_dev = -1; /* Magic; means not known yet. */
  385. me->me_next = NULL;
  386. /* Add to the linked list. */
  387. mtail->me_next = me;
  388. mtail = me;
  389. }
  390. free (stats);
  391. }
  392. #endif /* MOUNTED_GETFSSTAT */
  393. #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */
  394. {
  395. struct mnttab mnt;
  396. char *table = "/etc/mnttab";
  397. FILE *fp;
  398. fp = fopen (table, "r");
  399. if (fp == NULL)
  400. return NULL;
  401. while (fread (&mnt, sizeof mnt, 1, fp) > 0) {
  402. me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
  403. #ifdef GETFSTYP /* SVR3. */
  404. me->me_devname = strdup (mnt.mt_dev);
  405. #else
  406. me->me_devname = malloc (strlen (mnt.mt_dev) + 6);
  407. strcpy (me->me_devname, "/dev/");
  408. strcpy (me->me_devname + 5, mnt.mt_dev);
  409. #endif
  410. me->me_mountdir = strdup (mnt.mt_filsys);
  411. me->me_dev = -1; /* Magic; means not known yet. */
  412. me->me_type = "";
  413. #ifdef GETFSTYP /* SVR3. */
  414. if (need_fs_type) {
  415. struct statfs fsd;
  416. char typebuf[FSTYPSZ];
  417. if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1
  418. && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1)
  419. me->me_type = strdup (typebuf);
  420. }
  421. #endif
  422. me->me_next = NULL;
  423. /* Add to the linked list. */
  424. mtail->me_next = me;
  425. mtail = me;
  426. }
  427. if (fclose (fp) == EOF)
  428. return NULL;
  429. }
  430. #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP */
  431. #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */
  432. {
  433. struct mntent **mnttbl = getmnttbl (), **ent;
  434. for (ent = mnttbl; *ent; ent++) {
  435. me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
  436. me->me_devname = strdup ((*ent)->mt_resource);
  437. me->me_mountdir = strdup ((*ent)->mt_directory);
  438. me->me_type = strdup ((*ent)->mt_fstype);
  439. me->me_dev = -1; /* Magic; means not known yet. */
  440. me->me_next = NULL;
  441. /* Add to the linked list. */
  442. mtail->me_next = me;
  443. mtail = me;
  444. }
  445. endmnttbl ();
  446. }
  447. #endif /* MOUNTED_GETMNTTBL */
  448. #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
  449. {
  450. struct mnttab mnt;
  451. char *table = MNTTAB;
  452. FILE *fp;
  453. int ret;
  454. fp = fopen (table, "r");
  455. if (fp == NULL)
  456. return NULL;
  457. while ((ret = getmntent (fp, &mnt)) == 0) {
  458. me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
  459. me->me_devname = strdup (mnt.mnt_special);
  460. me->me_mountdir = strdup (mnt.mnt_mountp);
  461. me->me_type = strdup (mnt.mnt_fstype);
  462. me->me_dev = -1; /* Magic; means not known yet. */
  463. me->me_next = NULL;
  464. /* Add to the linked list. */
  465. mtail->me_next = me;
  466. mtail = me;
  467. }
  468. if (ret > 0)
  469. return NULL;
  470. if (fclose (fp) == EOF)
  471. return NULL;
  472. }
  473. #endif /* MOUNTED_GETMNTENT2 */
  474. #ifdef MOUNTED_VMOUNT /* AIX. */
  475. {
  476. int bufsize;
  477. char *entries, *thisent;
  478. struct vmount *vmp;
  479. /* Ask how many bytes to allocate for the mounted filesystem info. */
  480. mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize);
  481. entries = malloc (bufsize);
  482. /* Get the list of mounted filesystems. */
  483. mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries);
  484. for (thisent = entries; thisent < entries + bufsize;
  485. thisent += vmp->vmt_length) {
  486. vmp = (struct vmount *) thisent;
  487. me = (struct mount_entry *) malloc (sizeof (struct mount_entry));
  488. if (vmp->vmt_flags & MNT_REMOTE) {
  489. char *host, *path;
  490. /* Prepend the remote pathname. */
  491. host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off;
  492. path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off;
  493. me->me_devname = malloc (strlen (host) + strlen (path) + 2);
  494. strcpy (me->me_devname, host);
  495. strcat (me->me_devname, ":");
  496. strcat (me->me_devname, path);
  497. } else {
  498. me->me_devname = strdup (thisent +
  499. vmp->vmt_data[VMT_OBJECT].vmt_off);
  500. }
  501. me->me_mountdir = strdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off);
  502. me->me_type = strdup (fstype_to_string (vmp->vmt_gfstype));
  503. me->me_dev = -1; /* vmt_fsid might be the info we want. */
  504. me->me_next = NULL;
  505. /* Add to the linked list. */
  506. mtail->me_next = me;
  507. mtail = me;
  508. }
  509. free (entries);
  510. }
  511. #endif /* MOUNTED_VMOUNT */
  512. /* Free the dummy head. */
  513. me = mlist;
  514. mlist = mlist->me_next;
  515. free (me);
  516. return mlist;
  517. }
  518. #endif /* HAVE_INFOMOUNT_LIST */
  519. #ifdef HAVE_INFOMOUNT_QNX
  520. /*
  521. ** QNX has no [gs]etmnt*(), [gs]etfs*(), or /etc/mnttab, but can do
  522. ** this via the following code.
  523. ** Note that, as this is based on CWD, it only fills one mount_entry
  524. ** structure. See my_statfs() in utilunix.c for the "other side" of
  525. ** this hack.
  526. */
  527. static struct mount_entry *
  528. read_filesystem_list(int need_fs_type, int all_fs)
  529. {
  530. struct _disk_entry de;
  531. struct statfs fs;
  532. int i, fd;
  533. char *tp, dev[_POSIX_NAME_MAX], dir[_POSIX_PATH_MAX];
  534. static struct mount_entry *me = NULL;
  535. if (me)
  536. {
  537. if (me->me_devname) free(me->me_devname);
  538. if (me->me_mountdir) free(me->me_mountdir);
  539. if (me->me_type) free(me->me_type);
  540. }
  541. else
  542. me = (struct mount_entry *)malloc(sizeof(struct mount_entry));
  543. if (!getcwd(dir, _POSIX_PATH_MAX)) return (NULL);
  544. if ((fd = open(dir, O_RDONLY)) == -1) return (NULL);
  545. i = disk_get_entry(fd, &de);
  546. close(fd);
  547. if (i == -1) return (NULL);
  548. switch (de.disk_type)
  549. {
  550. case _UNMOUNTED: tp = "unmounted"; break;
  551. case _FLOPPY: tp = "Floppy"; break;
  552. case _HARD: tp = "Hard"; break;
  553. case _RAMDISK: tp = "Ram"; break;
  554. case _REMOVABLE: tp = "Removable"; break;
  555. case _TAPE: tp = "Tape"; break;
  556. case _CDROM: tp = "CDROM"; break;
  557. default: tp = "unknown";
  558. }
  559. if (fsys_get_mount_dev(dir, &dev) == -1) return (NULL);
  560. if (fsys_get_mount_pt(dev, &dir) == -1) return (NULL);
  561. me->me_devname = strdup(dev);
  562. me->me_mountdir = strdup(dir);
  563. me->me_type = strdup(tp);
  564. me->me_dev = de.disk_type;
  565. #ifdef DEBUG
  566. fprintf(stderr, "disk_get_entry():\n\tdisk_type=%d (%s)\n\tdriver_name='%-*.*s'\n\tdisk_drv=%d\n",
  567. de.disk_type, tp, _DRIVER_NAME_LEN, _DRIVER_NAME_LEN, de.driver_name, de.disk_drv);
  568. fprintf(stderr, "fsys_get_mount_dev():\n\tdevice='%s'\n", dev);
  569. fprintf(stderr, "fsys_get_mount_pt():\n\tmount point='%s'\n", dir);
  570. #endif /* DEBUG */
  571. return (me);
  572. }
  573. #endif /* HAVE_INFOMOUNT_QNX */
  574. void
  575. init_my_statfs (void)
  576. {
  577. #ifdef HAVE_INFOMOUNT_LIST
  578. mount_list = read_filesystem_list (1, 1);
  579. #endif /* HAVE_INFOMOUNT_LIST */
  580. }
  581. void
  582. my_statfs (struct my_statfs *myfs_stats, const char *path)
  583. {
  584. #ifdef HAVE_INFOMOUNT_LIST
  585. int i, len = 0;
  586. struct mount_entry *entry = NULL;
  587. struct mount_entry *temp = mount_list;
  588. struct fs_usage fs_use;
  589. while (temp){
  590. i = strlen (temp->me_mountdir);
  591. if (i > len && (strncmp (path, temp->me_mountdir, i) == 0))
  592. if (!entry || (path [i] == PATH_SEP || path [i] == 0)){
  593. len = i;
  594. entry = temp;
  595. }
  596. temp = temp->me_next;
  597. }
  598. if (entry){
  599. memset (&fs_use, 0, sizeof (struct fs_usage));
  600. get_fs_usage (entry->me_mountdir, &fs_use);
  601. myfs_stats->type = entry->me_dev;
  602. myfs_stats->typename = entry->me_type;
  603. myfs_stats->mpoint = entry->me_mountdir;
  604. myfs_stats->device = entry->me_devname;
  605. myfs_stats->avail = getuid () ? fs_use.fsu_bavail/2 : fs_use.fsu_bfree/2;
  606. myfs_stats->total = fs_use.fsu_blocks/2;
  607. myfs_stats->nfree = fs_use.fsu_ffree;
  608. myfs_stats->nodes = fs_use.fsu_files;
  609. } else
  610. #endif /* HAVE_INFOMOUNT_LIST */
  611. #ifdef HAVE_INFOMOUNT_QNX
  612. /*
  613. ** This is the "other side" of the hack to read_filesystem_list() in
  614. ** mountlist.c.
  615. ** It's not the most efficient approach, but consumes less memory. It
  616. ** also accomodates QNX's ability to mount filesystems on the fly.
  617. */
  618. struct mount_entry *entry;
  619. struct fs_usage fs_use;
  620. if ((entry = read_filesystem_list(0, 0)) != NULL)
  621. {
  622. get_fs_usage(entry->me_mountdir, &fs_use);
  623. myfs_stats->type = entry->me_dev;
  624. myfs_stats->typename = entry->me_type;
  625. myfs_stats->mpoint = entry->me_mountdir;
  626. myfs_stats->device = entry->me_devname;
  627. myfs_stats->avail = fs_use.fsu_bfree / 2;
  628. myfs_stats->total = fs_use.fsu_blocks / 2;
  629. myfs_stats->nfree = fs_use.fsu_ffree;
  630. myfs_stats->nodes = fs_use.fsu_files;
  631. }
  632. else
  633. #endif /* HAVE_INFOMOUNT_QNX */
  634. {
  635. myfs_stats->type = 0;
  636. myfs_stats->mpoint = "unknown";
  637. myfs_stats->device = "unknown";
  638. myfs_stats->avail = 0;
  639. myfs_stats->total = 0;
  640. myfs_stats->nfree = 0;
  641. myfs_stats->nodes = 0;
  642. }
  643. }
  644. #ifdef HAVE_INFOMOUNT
  645. /* Return the number of TOSIZE-byte blocks used by
  646. BLOCKS FROMSIZE-byte blocks, rounding away from zero.
  647. TOSIZE must be positive. Return -1 if FROMSIZE is not positive. */
  648. static fsblkcnt_t
  649. fs_adjust_blocks (fsblkcnt_t blocks, int fromsize, int tosize)
  650. {
  651. if (tosize <= 0)
  652. abort ();
  653. if (fromsize <= 0)
  654. return -1;
  655. if (fromsize == tosize) /* E.g., from 512 to 512. */
  656. return blocks;
  657. else if (fromsize > tosize) /* E.g., from 2048 to 512. */
  658. return blocks * (fromsize / tosize);
  659. else /* E.g., from 256 to 512. */
  660. return blocks / (tosize / fromsize);
  661. }
  662. #if defined(_AIX) && defined(_I386)
  663. /* AIX PS/2 does not supply statfs. */
  664. static int aix_statfs (char *path, struct statfs *fsb)
  665. {
  666. struct stat stats;
  667. struct dustat fsd;
  668. if (stat (path, &stats))
  669. return -1;
  670. if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd)))
  671. return -1;
  672. fsb->f_type = 0;
  673. fsb->f_bsize = fsd.du_bsize;
  674. fsb->f_blocks = fsd.du_fsize - fsd.du_isize;
  675. fsb->f_bfree = fsd.du_tfree;
  676. fsb->f_bavail = fsd.du_tfree;
  677. fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb;
  678. fsb->f_ffree = fsd.du_tinode;
  679. fsb->f_fsid.val[0] = fsd.du_site;
  680. fsb->f_fsid.val[1] = fsd.du_pckno;
  681. return 0;
  682. }
  683. #define statfs(path,fsb) aix_statfs(path,fsb)
  684. #endif /* _AIX && _I386 */
  685. /* Fill in the fields of FSP with information about space usage for
  686. the filesystem on which PATH resides.
  687. Return 0 if successful, -1 if not. */
  688. static int
  689. get_fs_usage (char *path, struct fs_usage *fsp)
  690. {
  691. #ifdef STAT_STATFS3_OSF1
  692. struct statfs fsd;
  693. if (statfs (path, &fsd, sizeof (struct statfs)) != 0)
  694. return -1;
  695. #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512)
  696. #endif /* STAT_STATFS3_OSF1 */
  697. #ifdef STAT_STATFS2_FS_DATA /* Ultrix. */
  698. struct fs_data fsd;
  699. if (statfs (path, &fsd) != 1)
  700. return -1;
  701. #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), 1024, 512)
  702. fsp->fsu_blocks = CONVERT_BLOCKS (fsd.fd_req.btot);
  703. fsp->fsu_bfree = CONVERT_BLOCKS (fsd.fd_req.bfree);
  704. fsp->fsu_bavail = CONVERT_BLOCKS (fsd.fd_req.bfreen);
  705. fsp->fsu_files = fsd.fd_req.gtot;
  706. fsp->fsu_ffree = fsd.fd_req.gfree;
  707. #endif
  708. #ifdef STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX. */
  709. struct statfs fsd;
  710. if (statfs (path, &fsd) < 0)
  711. return -1;
  712. #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512)
  713. #endif
  714. #ifdef STAT_STATFS2_FSIZE /* 4.4BSD. */
  715. struct statfs fsd;
  716. if (statfs (path, &fsd) < 0)
  717. return -1;
  718. #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_fsize, 512)
  719. #endif
  720. #ifdef STAT_STATFS4 /* SVR3, Dynix, Irix, AIX. */
  721. struct statfs fsd;
  722. if (statfs (path, &fsd, sizeof fsd, 0) < 0)
  723. return -1;
  724. /* Empirically, the block counts on most SVR3 and SVR3-derived
  725. systems seem to always be in terms of 512-byte blocks,
  726. no matter what value f_bsize has. */
  727. #if _AIX
  728. #define CONVERT_BLOCKS(b) fs_adjust_blocks ((b), fsd.f_bsize, 512)
  729. #else
  730. #define CONVERT_BLOCKS(b) (b)
  731. #ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx. */
  732. #ifndef DOLPHIN /* DOLPHIN 3.8.alfa/7.18 has f_bavail */
  733. #define f_bavail f_bfree
  734. #endif
  735. #endif
  736. #endif
  737. #endif
  738. #ifdef STAT_STATVFS /* SVR4. */
  739. struct statvfs fsd;
  740. if (statvfs (path, &fsd) < 0)
  741. return -1;
  742. /* f_frsize isn't guaranteed to be supported. */
  743. #define CONVERT_BLOCKS(b) \
  744. fs_adjust_blocks ((b), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
  745. #endif
  746. #if defined(CONVERT_BLOCKS) && !defined(STAT_STATFS2_FS_DATA) && !defined(STAT_READ_FILSYS) /* !Ultrix && !SVR2. */
  747. fsp->fsu_blocks = CONVERT_BLOCKS (fsd.f_blocks);
  748. fsp->fsu_bfree = CONVERT_BLOCKS (fsd.f_bfree);
  749. fsp->fsu_bavail = CONVERT_BLOCKS (fsd.f_bavail);
  750. fsp->fsu_files = fsd.f_files;
  751. fsp->fsu_ffree = fsd.f_ffree;
  752. #endif
  753. return 0;
  754. }
  755. #endif /* HAVE_INFOMOUNT */