On 2017-07-12 14:38, [ext] Reichel Andreas wrote:
> If the user manually creates a loopback device node
> in /dev, for example /dev/NAME and uses it to setup a
> loopback device, the resulting base name of /sys/block/loop*
> does not match that of /dev/NAME. On some systems,
> /dev/loop* gets created automatically by using losetup, on
> others not.
> The solution is to read the major and minor revision
> out of /sys/block/NAME/dev and look for the same
> in /dev. Thus, the correct block device node in /dev
> can be found.
> 
> Signed-off-by: Andreas Reichel <[email protected]>
> ---
>  tools/ebgpart.c | 105 
> ++++++++++++++++++++++++++++++++++++++++++++++++--------
>  tools/ebgpart.h |   5 ++-
>  2 files changed, 95 insertions(+), 15 deletions(-)
> 
> diff --git a/tools/ebgpart.c b/tools/ebgpart.c
> index 07edb05..940652f 100644
> --- a/tools/ebgpart.c
> +++ b/tools/ebgpart.c
> @@ -353,27 +353,104 @@ bool check_partition_table(PedDevice *dev)
>       return true;
>  }
>  
> -void ped_device_probe_all()
> +int scan_devdir(unsigned int fmajor, unsigned int fminor, char *fullname,
> +              unsigned int maxlen)

static - the compiler should complain about lacking prototype, or didn't
we enable that check?

>  {
> -     struct dirent *devfile;
> -     char fullname[256];
> +     int result = -1;
>  
> -     DIR *devdir = opendir(DEVDIRNAME);
> +     DIR *devdir = opendir(DEVDIR);
>       if (!devdir) {
> -             VERBOSE(stderr, "Could not open %s\n", DEVDIRNAME);
> +             VERBOSE(stderr, "Failed to open %s\n", DEVDIR);
> +             return result;
> +     }
> +     struct dirent *devfile;
> +     do {
> +             devfile = readdir(devdir);
> +             if (!devfile) {
> +                     break;
> +             }
> +             snprintf(fullname, maxlen, "%s/%s", DEVDIR, devfile->d_name);
> +             struct stat fstat;
> +             if (stat(fullname, &fstat) == -1) {
> +                     VERBOSE(stderr, "stat failed on %s\n", fullname);
> +                     break;
> +             }
> +             if (major(fstat.st_rdev) == fmajor &&
> +                 minor(fstat.st_rdev) == fminor) {
> +                     VERBOSE(stdout, "Node found: %s\n", fullname);
> +                     result = 0;
> +                     break;
> +             }
> +     } while (devfile);
> +     closedir(devdir);
> +
> +     return result;
> +}
> +
> +int get_major_minor(char *filename, unsigned int *major, unsigned int *minor)

static

> +{
> +     if (!filename || !major || !minor) {

Really possible or just over-defensive programming? Specifically when
the caller is local, I'm reluctant to sprinkle such checks.

Looking at the caller, it's impossible. So drop these pointless checks.

> +             return -1;
> +     }
> +     FILE *fh = fopen(filename, "r");
> +     if (fh == 0) {
> +             VERBOSE(stderr, "Error opening %s for read", filename);
> +             return -1;
> +     }
> +     int res = fscanf(fh, "%u:%u", major, minor);
> +     fclose(fh);
> +     if (res < 2) {
> +             VERBOSE(stderr,
> +                     "Error reading major/minor of device entry. (%s)\n",
> +                     strerror(errno));
> +             return -1;
> +     };
> +     return 0;
> +}
> +
> +void ped_device_probe_all()
> +{
> +     struct dirent *sysblockfile;
> +     char fullname[DEV_FILENAME_LEN];
> +
> +     DIR *sysblockdir = opendir(SYSBLOCKDIR);
> +     if (!sysblockdir) {
> +             VERBOSE(stderr, "Could not open %s\n", SYSBLOCKDIR);
>               return;
>       }
>  
> -     /* get all files from devdir */
> +     /* get all files from sysblockdir */
>       do {
> -             devfile = readdir(devdir);
> -             if (!devfile)
> +             sysblockfile = readdir(sysblockdir);
> +             if (!sysblockfile) {
>                       break;
> -             if (strcmp(devfile->d_name, ".") == 0 ||
> -                 strcmp(devfile->d_name, "..") == 0)
> +             }
> +             if (strcmp(sysblockfile->d_name, ".") == 0 ||
> +                 strcmp(sysblockfile->d_name, "..") == 0) {
>                       continue;
> -
> -             snprintf(fullname, 255, "/dev/%s", devfile->d_name);
> +             }
> +             snprintf(fullname, DEV_FILENAME_LEN, "/sys/block/%s/dev",

sizeof(fullname) would be better, here and below.

> +                      sysblockfile->d_name);
> +             /* Get major and minor revision from /sys/block/sdX/dev */
> +             unsigned int fmajor, fminor;
> +             if (get_major_minor(fullname, &fmajor, &fminor) < 0) {
> +                     continue;
> +             }
> +             VERBOSE(stdout,
> +                     "Trying device with: Major = %d, Minor = %d, (%s)\n",
> +                     fmajor, fminor, fullname);
> +             /* Check if this file is really in the dev directory */
> +             snprintf(fullname, DEV_FILENAME_LEN, "%s/%s", DEVDIR,
> +                      sysblockfile->d_name);
> +             struct stat fstat;
> +             if (stat(fullname, &fstat) == -1) {
> +                     /* Node with same name not found in /dev, thus search
> +                     * for node with identical Major and Minor revision */
> +                     if (scan_devdir(fmajor, fminor, fullname,
> +                                     DEV_FILENAME_LEN) != 0) {
> +                             continue;
> +                     }
> +             }
>               /* This is a block device, so add it to the list*/
>               PedDevice *dev = calloc(sizeof(PedDevice), 1);
>               asprintf(&dev->model, "N/A");
> @@ -385,9 +462,9 @@ void ped_device_probe_all()
>                       free(dev->path);
>                       free(dev);
>               }
> -     } while (devfile);
> +     } while (sysblockfile);
>  
> -     closedir(devdir);
> +     closedir(sysblockdir);
>  }
>  
>  void ped_partition_destroy(PedPartition *p)
> diff --git a/tools/ebgpart.h b/tools/ebgpart.h
> index 76fee9d..fbaa77c 100644
> --- a/tools/ebgpart.h
> +++ b/tools/ebgpart.h
> @@ -25,6 +25,8 @@
>  #define _GNU_SOURCE
>  #endif
>  
> +#define DEV_FILENAME_LEN 256
> +
>  #ifndef VERBOSE
>  #define VERBOSE(o, ...)                                                      
>   \
>       if (verbosity) fprintf(o, __VA_ARGS__)
> @@ -41,7 +43,8 @@
>  #include <string.h>
>  #include <stdlib.h>
>  
> -#define DEVDIRNAME "/sys/block"
> +#define SYSBLOCKDIR "/sys/block"
> +#define DEVDIR "/dev"
>  
>  #define LB_SIZE 512
>  
> 

Jan

-- 
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux

-- 
You received this message because you are subscribed to the Google Groups "EFI 
Boot Guard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/efibootguard-dev/68387c4d-2085-15b7-a329-53e5eaea7c58%40siemens.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to