diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/find_mount_point.c | 2 | ||||
-rw-r--r-- | libbb/find_root_device.c | 70 | ||||
-rw-r--r-- | libbb/loop.c | 163 | ||||
-rw-r--r-- | libbb/mtab.c | 45 |
4 files changed, 89 insertions, 191 deletions
diff --git a/libbb/find_mount_point.c b/libbb/find_mount_point.c index 83824de9e..eec738aea 100644 --- a/libbb/find_mount_point.c +++ b/libbb/find_mount_point.c | |||
@@ -48,7 +48,7 @@ extern struct mntent *find_mount_point(const char *name, const char *table) | |||
48 | mountDevice = s.st_dev; | 48 | mountDevice = s.st_dev; |
49 | 49 | ||
50 | 50 | ||
51 | if ((mountTable = setmntent(table, "r")) == 0) | 51 | if ((mountTable = setmntent(table ? : bb_path_mtab_file, "r")) == 0) |
52 | return 0; | 52 | return 0; |
53 | 53 | ||
54 | while ((mountEntry = getmntent(mountTable)) != 0) { | 54 | while ((mountEntry = getmntent(mountTable)) != 0) { |
diff --git a/libbb/find_root_device.c b/libbb/find_root_device.c index 2600ce5e0..7ff65bb57 100644 --- a/libbb/find_root_device.c +++ b/libbb/find_root_device.c | |||
@@ -25,65 +25,25 @@ | |||
25 | #include <stdlib.h> | 25 | #include <stdlib.h> |
26 | #include "libbb.h" | 26 | #include "libbb.h" |
27 | 27 | ||
28 | 28 | extern char *find_block_device(char *path) | |
29 | |||
30 | extern char *find_real_root_device_name(void) | ||
31 | { | 29 | { |
32 | DIR *dir; | 30 | DIR *dir; |
33 | struct dirent *entry; | 31 | struct dirent *entry; |
34 | struct stat statBuf, rootStat; | 32 | struct stat st; |
35 | char *fileName = NULL; | ||
36 | dev_t dev; | 33 | dev_t dev; |
37 | 34 | char *retpath=NULL; | |
38 | if (stat("/", &rootStat) != 0) | 35 | |
39 | bb_perror_msg("could not stat '/'"); | 36 | if(stat(path, &st) || !(dir = opendir("/dev"))) return NULL; |
40 | else { | 37 | dev = (st.st_mode & S_IFMT) == S_IFBLK ? st.st_rdev : st.st_dev; |
41 | /* This check is here in case they pass in /dev name */ | 38 | while((entry = readdir(dir)) != NULL) { |
42 | if ((rootStat.st_mode & S_IFMT) == S_IFBLK) | 39 | char devpath[PATH_MAX]; |
43 | dev = rootStat.st_rdev; | 40 | sprintf(devpath,"/dev/%s", entry->d_name); |
44 | else | 41 | if(!stat(devpath, &st) && S_ISBLK(st.st_mode) && st.st_rdev == dev) { |
45 | dev = rootStat.st_dev; | 42 | retpath = bb_xstrdup(devpath); |
46 | 43 | break; | |
47 | dir = opendir("/dev"); | ||
48 | if (!dir) | ||
49 | bb_perror_msg("could not open '/dev'"); | ||
50 | else { | ||
51 | while((entry = readdir(dir)) != NULL) { | ||
52 | const char *myname = entry->d_name; | ||
53 | /* Must skip ".." since that is "/", and so we | ||
54 | * would get a false positive on ".." */ | ||
55 | if (myname[0] == '.' && myname[1] == '.' && !myname[2]) | ||
56 | continue; | ||
57 | #ifdef CONFIG_FEATURE_DEVFS | ||
58 | /* if there is a link named /dev/root skip that too */ | ||
59 | if (strcmp(myname, "root")==0) | ||
60 | continue; | ||
61 | #endif | ||
62 | fileName = concat_path_file("/dev", myname); | ||
63 | |||
64 | /* Some char devices have the same dev_t as block | ||
65 | * devices, so make sure this is a block device */ | ||
66 | if (stat(fileName, &statBuf) == 0 && | ||
67 | S_ISBLK(statBuf.st_mode)!=0 && | ||
68 | statBuf.st_rdev == dev) | ||
69 | break; | ||
70 | free(fileName); | ||
71 | fileName=NULL; | ||
72 | } | ||
73 | closedir(dir); | ||
74 | } | 44 | } |
75 | } | 45 | } |
76 | if(fileName==NULL) | 46 | closedir(dir); |
77 | fileName = bb_xstrdup("/dev/root"); | ||
78 | return fileName; | ||
79 | } | ||
80 | |||
81 | 47 | ||
82 | /* END CODE */ | 48 | return retpath; |
83 | /* | 49 | } |
84 | Local Variables: | ||
85 | c-file-style: "linux" | ||
86 | c-basic-offset: 4 | ||
87 | tab-width: 4 | ||
88 | End: | ||
89 | */ | ||
diff --git a/libbb/loop.c b/libbb/loop.c index c4c3da4b1..25f66fcea 100644 --- a/libbb/loop.c +++ b/libbb/loop.c | |||
@@ -19,10 +19,8 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | |||
22 | #include <features.h> | 23 | #include <features.h> |
23 | #if defined (__GLIBC__) && !defined(__UCLIBC__) | ||
24 | #include <linux/posix_types.h> | ||
25 | #endif | ||
26 | #include <stdio.h> | 24 | #include <stdio.h> |
27 | #include <errno.h> | 25 | #include <errno.h> |
28 | #include <fcntl.h> | 26 | #include <fcntl.h> |
@@ -30,127 +28,108 @@ | |||
30 | #include <unistd.h> | 28 | #include <unistd.h> |
31 | #include <sys/ioctl.h> | 29 | #include <sys/ioctl.h> |
32 | #include "libbb.h" | 30 | #include "libbb.h" |
33 | #ifdef CONFIG_FEATURE_MOUNT_LOOP | ||
34 | 31 | ||
35 | /* Grumble... The 2.6.x kernel breaks asm/posix_types.h | 32 | /* For 2.6, use the cleaned up header to get the 64 bit API. */ |
36 | * so we get to try and cope as best we can... */ | ||
37 | #include <linux/version.h> | 33 | #include <linux/version.h> |
38 | |||
39 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) | 34 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) |
40 | #define __bb_kernel_dev_t __kernel_old_dev_t | 35 | #include <linux/loop.h> |
41 | #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) | 36 | typedef struct loop_info64 bb_loop_info; |
42 | #define __bb_kernel_dev_t __kernel_dev_t | 37 | #define BB_LOOP_SET_STATUS LOOP_SET_STATUS64 |
43 | #else | 38 | #define BB_LOOP_GET_STATUS LOOP_GET_STATUS64 |
44 | #define __bb_kernel_dev_t unsigned short | ||
45 | #endif | ||
46 | 39 | ||
47 | /* Stuff stolen from linux/loop.h */ | 40 | /* For 2.4 and earlier, use the 32 bit API (and don't trust the headers) */ |
41 | #else | ||
42 | /* Stuff stolen from linux/loop.h for 2.4 and earlier kernels*/ | ||
43 | #include <linux/posix_types.h> | ||
48 | #define LO_NAME_SIZE 64 | 44 | #define LO_NAME_SIZE 64 |
49 | #define LO_KEY_SIZE 32 | 45 | #define LO_KEY_SIZE 32 |
50 | #define LOOP_SET_FD 0x4C00 | 46 | #define LOOP_SET_FD 0x4C00 |
51 | #define LOOP_CLR_FD 0x4C01 | 47 | #define LOOP_CLR_FD 0x4C01 |
52 | #define LOOP_SET_STATUS 0x4C02 | 48 | #define BB_LOOP_SET_STATUS 0x4C02 |
53 | #define LOOP_GET_STATUS 0x4C03 | 49 | #define BB_LOOP_GET_STATUS 0x4C03 |
54 | struct loop_info { | 50 | typedef struct { |
55 | int lo_number; | 51 | int lo_number; |
56 | __bb_kernel_dev_t lo_device; | 52 | __kernel_dev_t lo_device; |
57 | unsigned long lo_inode; | 53 | unsigned long lo_inode; |
58 | __bb_kernel_dev_t lo_rdevice; | 54 | __kernel_dev_t lo_rdevice; |
59 | int lo_offset; | 55 | int lo_offset; |
60 | int lo_encrypt_type; | 56 | int lo_encrypt_type; |
61 | int lo_encrypt_key_size; | 57 | int lo_encrypt_key_size; |
62 | int lo_flags; | 58 | int lo_flags; |
63 | char lo_name[LO_NAME_SIZE]; | 59 | char lo_file_name[LO_NAME_SIZE]; |
64 | unsigned char lo_encrypt_key[LO_KEY_SIZE]; | 60 | unsigned char lo_encrypt_key[LO_KEY_SIZE]; |
65 | unsigned long lo_init[2]; | 61 | unsigned long lo_init[2]; |
66 | char reserved[4]; | 62 | char reserved[4]; |
67 | }; | 63 | } bb_loop_info; |
64 | #endif | ||
68 | 65 | ||
69 | extern int del_loop(const char *device) | 66 | extern int del_loop(const char *device) |
70 | { | 67 | { |
71 | int fd; | 68 | int fd,rc=0; |
72 | 69 | ||
73 | if ((fd = open(device, O_RDONLY)) < 0) { | 70 | if ((fd = open(device, O_RDONLY)) < 0) rc=1; |
74 | bb_perror_msg("%s", device); | 71 | else { |
75 | return (FALSE); | 72 | if (ioctl(fd, LOOP_CLR_FD, 0) < 0) rc=1; |
76 | } | ||
77 | if (ioctl(fd, LOOP_CLR_FD, 0) < 0) { | ||
78 | close(fd); | 73 | close(fd); |
79 | bb_perror_msg("ioctl: LOOP_CLR_FD"); | ||
80 | return (FALSE); | ||
81 | } | 74 | } |
82 | close(fd); | 75 | return rc; |
83 | return (TRUE); | ||
84 | } | 76 | } |
85 | 77 | ||
86 | extern int set_loop(const char *device, const char *file, int offset, | 78 | // Returns 0 if mounted RW, 1 if mounted read-only, <0 for error. |
87 | int *loopro) | 79 | // *device is loop device to use, or if *device==NULL finds a loop device to |
88 | { | 80 | // mount it on and sets *device to a strdup of that loop device name. This |
89 | struct loop_info loopinfo; | 81 | // search will re-use an existing loop device already bound to that |
90 | int fd, ffd, mode; | 82 | // file/offset if it finds one. |
91 | 83 | extern int set_loop(char **device, const char *file, int offset) | |
92 | mode = *loopro ? O_RDONLY : O_RDWR; | ||
93 | if ((ffd = open(file, mode)) < 0 && !*loopro | ||
94 | && (errno != EROFS || (ffd = open(file, mode = O_RDONLY)) < 0)) { | ||
95 | bb_perror_msg("%s", file); | ||
96 | return 1; | ||
97 | } | ||
98 | if ((fd = open(device, mode)) < 0) { | ||
99 | close(ffd); | ||
100 | bb_perror_msg("%s", device); | ||
101 | return 1; | ||
102 | } | ||
103 | *loopro = (mode == O_RDONLY); | ||
104 | |||
105 | memset(&loopinfo, 0, sizeof(loopinfo)); | ||
106 | safe_strncpy(loopinfo.lo_name, file, LO_NAME_SIZE); | ||
107 | |||
108 | loopinfo.lo_offset = offset; | ||
109 | |||
110 | loopinfo.lo_encrypt_key_size = 0; | ||
111 | if (ioctl(fd, LOOP_SET_FD, ffd) < 0) { | ||
112 | bb_perror_msg("ioctl: LOOP_SET_FD"); | ||
113 | close(fd); | ||
114 | close(ffd); | ||
115 | return 1; | ||
116 | } | ||
117 | if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) { | ||
118 | (void) ioctl(fd, LOOP_CLR_FD, 0); | ||
119 | bb_perror_msg("ioctl: LOOP_SET_STATUS"); | ||
120 | close(fd); | ||
121 | close(ffd); | ||
122 | return 1; | ||
123 | } | ||
124 | close(fd); | ||
125 | close(ffd); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | extern char *find_unused_loop_device(void) | ||
130 | { | 84 | { |
131 | char dev[20]; | 85 | char dev[20]; |
132 | int i, fd; | 86 | bb_loop_info loopinfo; |
133 | struct stat statbuf; | 87 | struct stat statbuf; |
134 | struct loop_info loopinfo; | 88 | int i, dfd, ffd, mode, rc=1; |
135 | 89 | ||
136 | for (i = 0; i <= CONFIG_FEATURE_MOUNT_LOOP_MAX; i++) { | 90 | // Open the file. Barf if this doesn't work. |
137 | sprintf(dev, LOOP_FORMAT, i); | 91 | if((ffd = open(file, mode=O_RDWR))<0) |
138 | if (stat(dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) { | 92 | if(errno!=EROFS || (ffd=open(file,mode=O_RDONLY))<0) |
139 | if ((fd = open(dev, O_RDONLY)) >= 0) { | 93 | return errno; |
140 | if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) != 0) { | 94 | |
141 | if (errno == ENXIO) { /* probably free */ | 95 | // Find a loop device |
142 | close(fd); | 96 | for(i=0;rc;i++) { |
143 | return strdup(dev); | 97 | sprintf(dev, LOOP_FORMAT, i++); |
144 | } | 98 | // Ran out of block devices, return failure. |
145 | } | 99 | if(stat(*device ? : dev, &statbuf) || !S_ISBLK(statbuf.st_mode)) { |
146 | close(fd); | 100 | rc=ENOENT; |
147 | } | 101 | break; |
148 | } | 102 | } |
103 | // Open the sucker and check its loopiness. | ||
104 | if((dfd=open(dev, mode))<0 && errno==EROFS) | ||
105 | dfd=open(dev,mode=O_RDONLY); | ||
106 | if(dfd<0) continue; | ||
107 | |||
108 | rc=ioctl(dfd, BB_LOOP_GET_STATUS, &loopinfo); | ||
109 | // If device free, claim it. | ||
110 | if(rc && errno==ENXIO) { | ||
111 | memset(&loopinfo, 0, sizeof(loopinfo)); | ||
112 | safe_strncpy(loopinfo.lo_file_name, file, LO_NAME_SIZE); | ||
113 | loopinfo.lo_offset = offset; | ||
114 | // Associate free loop device with file | ||
115 | if(!ioctl(dfd, LOOP_SET_FD, ffd) && | ||
116 | !ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo)) rc=0; | ||
117 | else ioctl(dfd, LOOP_CLR_FD, 0); | ||
118 | // If this block device already set up right, re-use it. | ||
119 | // (Yes this is racy, but associating two loop devices with the same | ||
120 | // file isn't pretty either. In general, mounting the same file twice | ||
121 | // without using losetup manually is problematic.) | ||
122 | } else if(strcmp(file,loopinfo.lo_file_name) | ||
123 | || offset!=loopinfo.lo_offset) rc=1; | ||
124 | close(dfd); | ||
125 | if(*device) break; | ||
149 | } | 126 | } |
150 | return NULL; | 127 | close(ffd); |
128 | if(!rc) { | ||
129 | if(!*device) *device=strdup(dev); | ||
130 | return mode==O_RDONLY ? 1 : 0; | ||
131 | } else return rc; | ||
151 | } | 132 | } |
152 | #endif | ||
153 | |||
154 | 133 | ||
155 | /* END CODE */ | 134 | /* END CODE */ |
156 | /* | 135 | /* |
diff --git a/libbb/mtab.c b/libbb/mtab.c index b1f74c476..fa4958c26 100644 --- a/libbb/mtab.c +++ b/libbb/mtab.c | |||
@@ -28,8 +28,8 @@ | |||
28 | #include "libbb.h" | 28 | #include "libbb.h" |
29 | 29 | ||
30 | #define MTAB_MAX_ENTRIES 40 | 30 | #define MTAB_MAX_ENTRIES 40 |
31 | static const int MS_RDONLY = 1; /* Mount read-only. */ | ||
32 | 31 | ||
32 | #ifdef CONFIG_FEATURE_MTAB_SUPPORT | ||
33 | void erase_mtab(const char *name) | 33 | void erase_mtab(const char *name) |
34 | { | 34 | { |
35 | struct mntent entries[MTAB_MAX_ENTRIES]; | 35 | struct mntent entries[MTAB_MAX_ENTRIES]; |
@@ -72,45 +72,4 @@ void erase_mtab(const char *name) | |||
72 | } else if (errno != EROFS) | 72 | } else if (errno != EROFS) |
73 | bb_perror_msg(bb_path_mtab_file); | 73 | bb_perror_msg(bb_path_mtab_file); |
74 | } | 74 | } |
75 | 75 | #endif | |
76 | void write_mtab(char *blockDevice, char *directory, | ||
77 | char *filesystemType, long flags, char *string_flags) | ||
78 | { | ||
79 | FILE *mountTable = setmntent(bb_path_mtab_file, "a+"); | ||
80 | struct mntent m; | ||
81 | |||
82 | if (mountTable == 0) { | ||
83 | bb_perror_msg(bb_path_mtab_file); | ||
84 | return; | ||
85 | } | ||
86 | if (mountTable) { | ||
87 | int length = strlen(directory); | ||
88 | |||
89 | if (length > 1 && directory[length - 1] == '/') | ||
90 | directory[length - 1] = '\0'; | ||
91 | |||
92 | if (filesystemType == 0) { | ||
93 | struct mntent *p = find_mount_point(blockDevice, "/proc/mounts"); | ||
94 | |||
95 | if (p && p->mnt_type) | ||
96 | filesystemType = p->mnt_type; | ||
97 | } | ||
98 | m.mnt_fsname = blockDevice; | ||
99 | m.mnt_dir = directory; | ||
100 | m.mnt_type = filesystemType ? filesystemType : "default"; | ||
101 | |||
102 | if (*string_flags) { | ||
103 | m.mnt_opts = string_flags; | ||
104 | } else { | ||
105 | if ((flags | MS_RDONLY) == flags) | ||
106 | m.mnt_opts = "ro"; | ||
107 | else | ||
108 | m.mnt_opts = "rw"; | ||
109 | } | ||
110 | |||
111 | m.mnt_freq = 0; | ||
112 | m.mnt_passno = 0; | ||
113 | addmntent(mountTable, &m); | ||
114 | endmntent(mountTable); | ||
115 | } | ||
116 | } | ||