getmountlist.c revision 25fe0e0bea85f1d851ce03a90c0f1bf41ab431f2
19e035921494cb8f101c3bfc22956fa968c6ab41fBarry Warsaw/* getmountlist.c - Get a linked list of mount points, with stat information. 2ff6d8136574e9f4e1b11f75a945af5f8ab44a6fdBarry Warsaw * 3a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw * Copyright 2006 Rob Landley <rob@landley.net> 49e035921494cb8f101c3bfc22956fa968c6ab41fBarry Warsaw */ 5d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 6a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw#include "toys.h" 7ee8712cda46338d223509cc5751fd36509ad3860Benjamin Peterson#include <mntent.h> 8a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 9004d5e6880940ddbb38460986ac62ee0f1bae97dFred Drake// Realloc *old with oldstring,newstring 10d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 11d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwisvoid comma_collate(char **old, char *new) 12d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis{ 13d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis char *temp, *atold = *old; 14d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 1564dab4602e17878e816ae1d3f48b2f589ceebdfbBarry Warsaw // Only add a comma if old string didn't end with one 1639478e852827a4ca6955151bf004c7a15099a4b1Guido van Rossum if (atold && *atold) { 17d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis char *comma = ","; 18d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 19d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if (atold[strlen(atold)-1] == ',') comma = ""; 20d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis temp = xmprintf("%s%s%s", atold, comma, new); 21d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis } else temp = xstrdup(new); 22d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis free (atold); 23d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis *old = temp; 24d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis} 25d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 26d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis// iterate through strings in a comma separated list. 27d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis// returns start of next entry or NULL if none 28d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis// sets *len to length of entry (not including comma) 29d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis// advances *list to start of next entry 30d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwischar *comma_iterate(char **list, int *len) 31d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis{ 32d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis char *start = *list, *end; 33d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 34d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if (!*list || !**list) return 0; 35d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 3639478e852827a4ca6955151bf004c7a15099a4b1Guido van Rossum if (!(end = strchr(*list, ','))) { 37a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw *len = strlen(*list); 38a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw *list = 0; 39a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw } else *list += (*len = end-start)+1; 40a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 41a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw return start; 42a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw} 43a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 44a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsawstatic void deslash(char *s) 45d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis{ 4639478e852827a4ca6955151bf004c7a15099a4b1Guido van Rossum char *o = s; 47e960e22579838419541357712bbbc3317c219071Barry Warsaw 48e960e22579838419541357712bbbc3317c219071Barry Warsaw while (*s) { 49e960e22579838419541357712bbbc3317c219071Barry Warsaw if (*s == '\\') { 50e960e22579838419541357712bbbc3317c219071Barry Warsaw int i, oct = 0; 51e960e22579838419541357712bbbc3317c219071Barry Warsaw 52e960e22579838419541357712bbbc3317c219071Barry Warsaw for (i = 1; i < 4; i++) { 53e960e22579838419541357712bbbc3317c219071Barry Warsaw if (!isdigit(s[i])) break; 54e960e22579838419541357712bbbc3317c219071Barry Warsaw oct = (oct<<3)+s[i]-'0'; 55e960e22579838419541357712bbbc3317c219071Barry Warsaw } 56e960e22579838419541357712bbbc3317c219071Barry Warsaw if (i == 4) { 57d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis *o++ = oct; 58d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis s += i; 59a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw continue; 60e960e22579838419541357712bbbc3317c219071Barry Warsaw } 61d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis } 62d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis *o++ = *s++; 63a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw } 64a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 65a0e0cd3013840299a789f05be239d6ecb6387cdfNeal Norwitz *o = 0; 66a0e0cd3013840299a789f05be239d6ecb6387cdfNeal Norwitz} 677fa886df3622bbedbeb9c2486a8af5f05334a928Éric Araujo 687fa886df3622bbedbeb9c2486a8af5f05334a928Éric Araujo// check all instances of opt and "no"opt in optlist, return true if opt 697fa886df3622bbedbeb9c2486a8af5f05334a928Éric Araujo// found and last instance wasn't no. If clean, remove each instance from list. 707fa886df3622bbedbeb9c2486a8af5f05334a928Éric Araujoint comma_scan(char *optlist, char *opt, int clean) 717fa886df3622bbedbeb9c2486a8af5f05334a928Éric Araujo{ 727fa886df3622bbedbeb9c2486a8af5f05334a928Éric Araujo int optlen = strlen(opt), len, no, got = 0; 73155374d95d8ecd235d3a3edd92dd6f6a23d59f11Walter Dörwald 74155374d95d8ecd235d3a3edd92dd6f6a23d59f11Walter Dörwald if (optlist) for (;;) { 7537a89334da1fbe5b30f5a03a97b8f8c2a59adc1bÉric Araujo char *s = comma_iterate(&optlist, &len); 76a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 77a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw if (!s) break; 78155374d95d8ecd235d3a3edd92dd6f6a23d59f11Walter Dörwald no = 2*(*s == 'n' && s[1] == 'o'); 79155374d95d8ecd235d3a3edd92dd6f6a23d59f11Walter Dörwald if (optlen == len+no && !strcmp(opt, s+no)) { 804aebbb044942ad17d761491b46ff05b6ab8387c9Brett Cannon got = !no; 81d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if (clean) memmove(s, optlist, strlen(optlist)+1); 82ff6d8136574e9f4e1b11f75a945af5f8ab44a6fdBarry Warsaw } 83a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw } 84d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 85a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw return got; 86d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis} 87d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 88d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis// return true if all scanlist options enabled in optlist 89ff6d8136574e9f4e1b11f75a945af5f8ab44a6fdBarry Warsawint comma_scanall(char *optlist, char *scanlist) 90d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis{ 91a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw int i = 1; 92d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 93a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw for (;;) { 94ef87d6ed94780fe00250a551031023aeb2898365Guido van Rossum char *opt = comma_iterate(&scanlist, &i), *s = xstrndup(opt, i); 95a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 96ef87d6ed94780fe00250a551031023aeb2898365Guido van Rossum i = comma_scan(optlist, s, 0); 97d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis free(s); 98d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if (!i) break; 99a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw } 100d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 101a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw return i; 102ef87d6ed94780fe00250a551031023aeb2898365Guido van Rossum} 103a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 104ef87d6ed94780fe00250a551031023aeb2898365Guido van Rossum// Check if this type matches list. 105d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis// Odd syntax: typelist all yes = if any, typelist all no = if none. 106d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 107a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsawint mountlist_istype(struct mtab_list *ml, char *typelist) 108d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis{ 109a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw int len, skip; 110ef87d6ed94780fe00250a551031023aeb2898365Guido van Rossum char *t; 111a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 112ef87d6ed94780fe00250a551031023aeb2898365Guido van Rossum if (!typelist) return 1; 113d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 114d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis skip = strncmp(typelist, "no", 2); 115a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 116d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis for (;;) { 117a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw if (!(t = comma_iterate(&typelist, &len))) break; 118ef87d6ed94780fe00250a551031023aeb2898365Guido van Rossum if (!skip) { 119a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw // If one -t starts with "no", the rest must too 120ef87d6ed94780fe00250a551031023aeb2898365Guido van Rossum if (strncmp(t, "no", 2)) error_exit("bad typelist"); 121d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if (!strncmp(t+2, ml->type, len-2)) { 122d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis skip = 1; 123a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw break; 124d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis } 125a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw } else if (!strncmp(t, ml->type, len) && !ml->type[len]) { 1269e035921494cb8f101c3bfc22956fa968c6ab41fBarry Warsaw skip = 0; 127a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw break; 128a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw } 129d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis } 130a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 131ff6d8136574e9f4e1b11f75a945af5f8ab44a6fdBarry Warsaw return !skip; 132d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis} 133a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 134d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis// Get list of mounted filesystems, including stat and statvfs info. 1357fa886df3622bbedbeb9c2486a8af5f05334a928Éric Araujo// Returns a reversed list, which is good for finding overmounts and such. 1367fa886df3622bbedbeb9c2486a8af5f05334a928Éric Araujo 137a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsawstruct mtab_list *xgetmountlist(char *path) 138d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis{ 139a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw struct mtab_list *mtlist = 0, *mt; 140a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw struct mntent *me; 141801844d6fc8b48cfa969dd2573bd522a2b26f974Benjamin Peterson FILE *fp; 142a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw char *p = path ? path : "/proc/mounts"; 143602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl 1441a3284ed69d545e4ef59869998cb8c29233a45faGeorg Brandl if (!(fp = setmntent(p, "r"))) perror_exit("bad %s", p); 145801844d6fc8b48cfa969dd2573bd522a2b26f974Benjamin Peterson 146801844d6fc8b48cfa969dd2573bd522a2b26f974Benjamin Peterson // The "test" part of the loop is done before the first time through and 147801844d6fc8b48cfa969dd2573bd522a2b26f974Benjamin Peterson // again after each "increment", so putting the actual load there avoids 148602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl // duplicating it. If the load was NULL, the loop stops. 1491a3284ed69d545e4ef59869998cb8c29233a45faGeorg Brandl 1501a3284ed69d545e4ef59869998cb8c29233a45faGeorg Brandl while ((me = getmntent(fp))) { 151d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis mt = xzalloc(sizeof(struct mtab_list) + strlen(me->mnt_fsname) + 152ff6d8136574e9f4e1b11f75a945af5f8ab44a6fdBarry Warsaw strlen(me->mnt_dir) + strlen(me->mnt_type) + strlen(me->mnt_opts) + 4); 153a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw dlist_add_nomalloc((void *)&mtlist, (void *)mt); 154d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 155a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw // Collect details about mounted filesystem 156d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis // Don't report errors, just leave data zeroed 157a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw if (!path) { 158d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis stat(me->mnt_dir, &(mt->stat)); 159d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis statvfs(me->mnt_dir, &(mt->statvfs)); 160a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw } 161d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 16264dab4602e17878e816ae1d3f48b2f589ceebdfbBarry Warsaw // Remember information from /proc/mounts 163d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis mt->dir = stpcpy(mt->type, me->mnt_type)+1; 164a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw mt->device = stpcpy(mt->dir, me->mnt_dir)+1; 16564dab4602e17878e816ae1d3f48b2f589ceebdfbBarry Warsaw mt->opts = stpcpy(mt->device, me->mnt_fsname)+1; 166d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis strcpy(mt->opts, me->mnt_opts); 167a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 16864dab4602e17878e816ae1d3f48b2f589ceebdfbBarry Warsaw deslash(mt->dir); 169d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis deslash(mt->device); 170a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw } 171d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis endmntent(fp); 172a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 173ef87d6ed94780fe00250a551031023aeb2898365Guido van Rossum return mtlist; 174a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw} 175ef87d6ed94780fe00250a551031023aeb2898365Guido van Rossum