Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

major() and minor() give different numbers from ls

Tags:

c

linux

Part of my C program is to output whether two device files are equal (i.e., same kind of device file and same major and minor numbers). It outputted that tty and tty2 are the same device files while I think they are not.

I added code to print out the retrieved major and minor numbers for each file and it printed out different numbers from what I got when I did ls -l /dev/tty and ls -l /dev/tty2. The major and minor numbers printed out for both tty and tty2 are 0 and 6, while using ls, they are 5 and 0 for tty and 4 and 2 for tty2.

I'm new to Linux and C. I have double-checked the manpage for major() and minor() and it seemed that I used these functions correctly. So, I don't know what went wrong.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>

#define report_error(x) puts("error") 

#define BUFFER_SIZE 1<<16    

int main(int argc, char *argv[])
{
    struct stat statbuf1;
    struct stat statbuf2;
    char *fn1;
    char *fn2;

    if (argc < 3) {
            if (argc < 1) {
                    report_error("no command line");
            } else {
                    report_error("Not enough arguments");
            }
    }

    fn1 = argv[1];
    fn2 = argv[2];

    if (lstat(fn1, &statbuf1)) {
            report_error(strerror(errno));
    }
    if (lstat(fn2, &statbuf2)) {
            report_error(strerror(errno));
    }

    if (S_ISCHR(statbuf1.st_mode) && S_ISCHR(statbuf2.st_mode)) {
            unsigned int major1 = major(statbuf1.st_dev);
            unsigned int major2 = major(statbuf2.st_dev);
            unsigned int minor1 = minor(statbuf1.st_dev);
            unsigned int minor2 = minor(statbuf2.st_dev);

            printf("%d  %d\n%d  %d\n", major1, major2, minor1, minor2);

            if (major1 == major2 && minor1 == minor2) {
                    printf("the two device files are equal\n");
                    exit(0);
            }
    }

    return 0;
}
like image 417
Tom Nguyen Avatar asked Oct 22 '25 06:10

Tom Nguyen


1 Answers

st_dev is the ID of device containing file, according to the man page. In other words, the device where the file's name resides. So it's the same as for your /dev directory, as you'll see if you use the stat command from your shell.

You're interested in st_rdev, which is Device ID (if special file) (again, from the man page).

The stat command shows both:

stat /dev/tty /dev/tty1

  File: /dev/tty
  Size: 0               Blocks: 0          IO Block: 4096   character special file
Device: 6h/6d   Inode: 1035        Links: 1     Device type: 5,0
Access: (0620/crw--w----)  Uid: (    0/    root)   Gid: (    5/     tty)

....

  File: /dev/tty1
  Size: 0               Blocks: 0          IO Block: 4096   character special file
Device: 6h/6d   Inode: 1044        Links: 1     Device type: 4,1
Access: (0620/crw--w----)  Uid: (    0/    root)   Gid: (    5/     tty)

Fixed code

#include <stdio.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h>

int get_char_device(const char *name,
                    unsigned *dev_major, unsigned *dev_minor)
{
    struct stat buf;
    if (stat(name, &buf)) {
        perror(name);
        return 1;
    }
    if (!S_ISCHR(buf.st_mode)) {
        fprintf(stderr, "%s: not a char device\n", name);
        return 1;
    }
    *dev_major = major(buf.st_rdev);
    *dev_minor = minor(buf.st_rdev);
    return 0;
}

int main(void)
{
    unsigned int major1, minor1, major2, minor2;
    if (get_char_device("/dev/tty1", &major1, &minor1) ||
        get_char_device("/dev/tty2", &major2, &minor2)) {
        return 1;
    }

    printf("%d  %d\n%d  %d\n", major1, major2, minor1, minor2);
    if (major1 == major2 && minor1 == minor2) {
        puts("the two device files are equal");
        return 1;
    }
}
like image 97
Toby Speight Avatar answered Oct 23 '25 21:10

Toby Speight



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!