~mirabilos/klibc/master

« back to all changes in this revision

Viewing changes to usr/utils/losetup.c

  • Committer: Ben Hutchings
  • Date: 2019-11-05 20:03:26 UTC
  • Revision ID: git-v1:333ef3af1dcef61a6bc5dba531453e5e0cb27da1
[klibc] losetup: Use LOOP_CTL_GET_FREE to find free device

Since Linux 3.1, the loop driver creates a /dev/loop-control device
node which supports ioctls to allocate and free devices.

When the loop driver is modular, udev creates this in advance, and
opening it causes the driver to be loaded.  (The same is not true for
/dev/loop*.)

Using the LOOP_CTL_GET_FREE ioctl also allows creating more than the
default number of loop devices, and is more efficient than checking
a range of possible device names.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>

Show diffs side-by-side

added added

removed removed

Lines of Context:
95
95
 
96
96
char * find_unused_loop_device (void)
97
97
{
98
 
        /* Just creating a device, say in /tmp, is probably a bad idea -
99
 
           people might have problems with backup or so.
100
 
           So, we just try /dev/loop[0-7]. */
101
98
        char dev[20];
102
 
        char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
103
 
        int i, j, fd, somedev = 0, someloop = 0, permission = 0;
104
 
        struct stat statbuf;
105
 
        struct loop_info loopinfo;
106
 
 
107
 
        for (j = 0; j < SIZE(loop_formats); j++) {
108
 
                for(i = 0; i < 256; i++) {
109
 
                        sprintf(dev, loop_formats[j], i);
110
 
                        if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
111
 
                                somedev++;
112
 
                                fd = open (dev, O_RDONLY);
113
 
                                if (fd >= 0) {
114
 
                                        if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
115
 
                                                someloop++;             /* in use */
116
 
                                        else if (errno == ENXIO) {
117
 
                                                close (fd);
118
 
                                                return xstrdup(dev);/* probably free */
119
 
                                        }
120
 
                                        close (fd);
121
 
                                } else if (errno == EACCES)
122
 
                                        permission++;
123
 
 
124
 
                                continue;/* continue trying as long as devices exist */
125
 
                        }
126
 
                        break;
127
 
                }
 
99
        int fd, rc;
 
100
 
 
101
        fd = open("/dev/loop-control", O_RDWR);
 
102
        if (fd < 0) {
 
103
                error("%s: could not open /dev/loop-control. Maybe this kernel "
 
104
                      "does not know\n"
 
105
                      "       about the loop device? (If so, recompile or "
 
106
                      "`modprobe loop'.)", progname);
 
107
                return NULL;
128
108
        }
129
 
 
130
 
        if (!somedev)
131
 
                error("%s: could not find any device /dev/loop#", progname);
132
 
        else if (!someloop && permission)
133
 
                error("%s: no permission to look at /dev/loop#", progname);
134
 
        else if (!someloop)
135
 
                error(
136
 
                    "%s: Could not find any loop device. Maybe this kernel "
137
 
                    "does not know\n"
138
 
                    "       about the loop device? (If so, recompile or "
139
 
                    "`modprobe loop'.)", progname);
140
 
        else
 
109
        rc = ioctl(fd, LOOP_CTL_GET_FREE, 0);
 
110
        close(fd);
 
111
        if (rc < 0) {
141
112
                error("%s: could not find any free loop device", progname);
142
 
        return 0;
 
113
                return NULL;
 
114
        }
 
115
 
 
116
        sprintf(dev, "/dev/loop%d", rc);
 
117
        return xstrdup(dev);
143
118
}
144
119
 
145
120
/*