svn_error_t * svn_stream_readline(svn_stream_t *stream, svn_stringbuf_t **stringbuf, const char *eol, svn_boolean_t *eof, apr_pool_t *pool) { return svn_error_trace(stream_readline(stringbuf, eof, eol, stream, pool)); }
int get_partlist(struct s_devinfo *blkdev, int maxblkdev, int *diskcount, int *partcount) { struct s_devinfo blkdev1[FSA_MAX_BLKDEVICES]; struct s_devinfo tmpdev; int best; // index of the best item found in old array int pos=0; // pos of latest item in new array char devname[1024]; char longname[1024]; char delims[]=" \t\n"; char line[1024]; char *saveptr; char *result; char major[256]; char minor[256]; FILE *fpart; int count=0; int i, j; // init *diskcount=0; *partcount=0; // browse list in "/proc/partitions" if ((fpart=fopen("/proc/partitions","rb"))==NULL) return -1; while(!feof(fpart) && (count < FSA_MAX_BLKDEVICES) && (count < maxblkdev)) { if (stream_readline(fpart, line, sizeof(line))>1) { minor[0]=major[0]=0; devname[0]=0; result=strtok_r(line, delims, &saveptr); for(i=0; result != NULL && i<=4; i++) { switch(i) { case 0: // col0 = major snprintf(major, sizeof(major), "%s", result); break; case 1: // col1 = minor snprintf(minor, sizeof(minor), "%s", result); break; case 3: // col3 = devname snprintf(devname, sizeof(devname), "%s", result); break; } result = strtok_r(NULL, delims, &saveptr); } // ignore invalid entries if ((strlen(devname)==0) || (atoi(major)==0 && atoi(minor)==0)) continue; snprintf(longname, sizeof(longname), "/dev/%s", devname); if (get_devinfo(&tmpdev, longname, atoi(minor), atoi(major))!=0) continue; // to to the next part // check that this device is not already in the list for (i=0; i < count; i++) if (blkdev1[i].rdev==tmpdev.rdev) continue; // to to the next part // add the device to list if it is a real device and it's not already in the list blkdev1[count++]=tmpdev; } } fclose(fpart); // ---- 2. sort the devices for (pos=0, i=0; i<count; i++) { // set best to the first available item in the old array for (j=0, best=-1; (j<count) && (best==-1); j++) if (blkdev1[j].rdev!=0) best=j; // find the index of the best item in the old array for (j=0; j<count; j++) if ((blkdev1[j].rdev > 0) && (blkdev1[j].rdev < blkdev1[best].rdev)) best=j; // update counters switch (blkdev1[best].devtype) { case BLKDEV_FILESYSDEV: (*partcount)++; break; case BLKDEV_PHYSDISK: (*diskcount)++; break; } // move item to the new array blkdev[pos++]=blkdev1[best]; blkdev1[best].rdev=0; } return count; }
int generic_get_mntinfo(char *devname, int *readwrite, char *mntbuf, int maxmntbuf, char *optbuf, int maxoptbuf, char *fsbuf, int maxfsbuf) { char col_fs[FSA_MAX_FSNAMELEN]; int devisroot=false; struct stat64 devstat; struct stat64 rootstat; long major, minor; char delims[]=" \t\n:"; struct utsname suname; char col_dev[128]; char col_mnt[128]; char col_opt[128]; char line[1024]; char temp[2048]; char *saveptr; char *result; FILE *f; int sep; int i; // init uname(&suname); *readwrite=-1; // unknown memset(mntbuf, 0, maxmntbuf); memset(optbuf, 0, maxoptbuf); // ---- 1. attempt to find device in "/proc/self/mountinfo" if ((stat64(devname, &devstat)==0) && ((f=fopen("/proc/self/mountinfo","rb"))!=NULL)) { msgprintf(MSG_DEBUG1, "device=[%s] has major=[%ld] and minor=[%ld]\n", devname, (long)major(devstat.st_rdev), (long)minor(devstat.st_rdev)); while(!feof(f)) { if (stream_readline(f, line, 1024)>1) { result=strtok_r(line, delims, &saveptr); major = -1; minor = -1; sep = -1; col_dev[0]=col_mnt[0]=col_fs[0]=col_opt[0]=0; for(i=0; result != NULL; i++) { if (strcmp(result, "-") == 0) // found separator sep = i; switch (i) { case 2: major = atol(result); break; case 3: minor = atol(result); break; case 5: snprintf(col_mnt, sizeof(col_mnt), "%s", result); break; } if ((sep != -1) && (i == sep + 1)) snprintf(col_fs, sizeof(col_fs), "%s", result); if ((sep != -1) && (i == sep + 3)) snprintf(col_opt, sizeof(col_opt), "%s", result); result = strtok_r(NULL, delims, &saveptr); } msgprintf(MSG_DEBUG1, "mountinfo entry: major=[%ld] minor=[%ld] filesys=[%s] col_opt=[%s] col_mnt=[%s]\n", major, minor, col_fs, col_opt, col_mnt); if ((major==major(devstat.st_rdev)) && (minor==minor(devstat.st_rdev))) { if (generic_get_spacestats(devname, col_mnt, temp, sizeof(temp))==0) { msgprintf(MSG_DEBUG1, "found mountinfo entry for device=[%s]: mnt=[%s] fs=[%s] opt=[%s]\n", devname, col_mnt, col_fs, col_opt); *readwrite=generic_get_fsrwstatus(col_opt); snprintf(mntbuf, maxmntbuf, "%s", col_mnt); snprintf(optbuf, maxoptbuf, "%s", col_opt); snprintf(fsbuf, maxfsbuf, "%s", col_fs); fclose(f); return 0; } } } } fclose(f); } // ---- 2. if there is no /proc/self/mountinfo then use "/proc/mounts" instead // workaround for systems not having the "/dev/root" node entry. // There are systems showing "/dev/root" in "/proc/mounts" instead // of the actual root partition such as "/dev/sda1". // The consequence is that fsarchiver won't be able to realize // that the device it is archiving (such as "/dev/sda1") is the // same as "/dev/root" and that it is actually mounted. This // function would then say that the "/dev/sda1" device is not mounted // and fsarchiver would try to mount it and mount() fails with EBUSY if (stat64(devname, &devstat)==0 && stat64("/", &rootstat)==0 && (devstat.st_rdev==rootstat.st_dev)) { devisroot=true; msgprintf(MSG_VERB1, "device [%s] is the root device\n", devname); } // 2. check device in "/proc/mounts" (typical case) if ((f=fopen("/proc/mounts","rb"))==NULL) { sysprintf("Cannot open /proc/mounts\n"); return 1; } while(!feof(f)) { if (stream_readline(f, line, 1024)>1) { result=strtok_r(line, delims, &saveptr); col_dev[0]=col_mnt[0]=col_fs[0]=col_opt[0]=0; for(i=0; result != NULL && i<=3; i++) { switch (i) // only the second word is a mount-point { case 0: snprintf(col_dev, sizeof(col_dev), "%s", result); break; case 1: snprintf(col_mnt, sizeof(col_mnt), "%s", result); break; case 2: snprintf(col_fs, sizeof(col_fs), "%s", result); break; case 3: snprintf(col_opt, sizeof(col_opt), "%s", result); break; } result = strtok_r(NULL, delims, &saveptr); } if ((devisroot==true) && (strcmp(col_mnt, "/")==0) && (strcmp(col_fs, "rootfs")!=0)) snprintf(col_dev, sizeof(col_dev), "%s", devname); msgprintf(MSG_DEBUG1, "mount entry: col_dev=[%s] col_mnt=[%s] col_fs=[%s] col_opt=[%s]\n", col_dev, col_mnt, col_fs, col_opt); if (devcmp(col_dev, devname)==0) { if (generic_get_spacestats(col_dev, col_mnt, temp, sizeof(temp))==0) { msgprintf(MSG_DEBUG1, "found mount entry for device=[%s]: mnt=[%s] fs=[%s] opt=[%s]\n", devname, col_mnt, col_fs, col_opt); *readwrite=generic_get_fsrwstatus(col_opt); snprintf(mntbuf, maxmntbuf, "%s", col_mnt); snprintf(optbuf, maxoptbuf, "%s", col_opt); snprintf(fsbuf, maxfsbuf, "%s", col_fs); fclose(f); return 0; } } } } fclose(f); return -1; }