diff options
| author | Richard Purdie <richard@openedhand.com> | 2006-07-21 10:10:31 +0000 |
|---|---|---|
| committer | Richard Purdie <richard@openedhand.com> | 2006-07-21 10:10:31 +0000 |
| commit | b2f192faabe412adce79534e22efe9fb69ee40e2 (patch) | |
| tree | 7076c49d4286f8a1733650bd8fbc7161af200d57 /meta/packages/makedevs | |
| parent | 2cf0eadf9f730027833af802d7e6c90b44248f80 (diff) | |
| download | poky-b2f192faabe412adce79534e22efe9fb69ee40e2.tar.gz | |
Rename /openembedded/ -> /meta/
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@530 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'meta/packages/makedevs')
| -rw-r--r-- | meta/packages/makedevs/makedevs-1.0.0/makedevs.c | 338 | ||||
| -rw-r--r-- | meta/packages/makedevs/makedevs-native_1.0.0.bb | 10 | ||||
| -rw-r--r-- | meta/packages/makedevs/makedevs_1.0.0.bb | 20 |
3 files changed, 368 insertions, 0 deletions
diff --git a/meta/packages/makedevs/makedevs-1.0.0/makedevs.c b/meta/packages/makedevs/makedevs-1.0.0/makedevs.c new file mode 100644 index 0000000000..a9bf8e782a --- /dev/null +++ b/meta/packages/makedevs/makedevs-1.0.0/makedevs.c | |||
| @@ -0,0 +1,338 @@ | |||
| 1 | #define _GNU_SOURCE | ||
| 2 | #include <stdio.h> | ||
| 3 | #include <errno.h> | ||
| 4 | #include <string.h> | ||
| 5 | #include <stdarg.h> | ||
| 6 | #include <stdlib.h> | ||
| 7 | #include <ctype.h> | ||
| 8 | #include <fcntl.h> | ||
| 9 | #include <dirent.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <time.h> | ||
| 12 | #include <getopt.h> | ||
| 13 | #include <libgen.h> | ||
| 14 | #include <sys/types.h> | ||
| 15 | #include <sys/stat.h> | ||
| 16 | |||
| 17 | #define MINORBITS 8 | ||
| 18 | #define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) | ||
| 19 | |||
| 20 | /* These are all stolen from busybox's libbb to make | ||
| 21 | * error handling simpler (and since I maintain busybox, | ||
| 22 | * I'm rather partial to these for error handling). | ||
| 23 | * -Erik | ||
| 24 | */ | ||
| 25 | static const char *const app_name = "makedevs"; | ||
| 26 | static const char *const memory_exhausted = "memory exhausted"; | ||
| 27 | static char default_rootdir[]="."; | ||
| 28 | static char *rootdir = default_rootdir; | ||
| 29 | |||
| 30 | static void verror_msg(const char *s, va_list p) | ||
| 31 | { | ||
| 32 | fflush(stdout); | ||
| 33 | fprintf(stderr, "%s: ", app_name); | ||
| 34 | vfprintf(stderr, s, p); | ||
| 35 | } | ||
| 36 | |||
| 37 | static void error_msg_and_die(const char *s, ...) | ||
| 38 | { | ||
| 39 | va_list p; | ||
| 40 | |||
| 41 | va_start(p, s); | ||
| 42 | verror_msg(s, p); | ||
| 43 | va_end(p); | ||
| 44 | putc('\n', stderr); | ||
| 45 | exit(EXIT_FAILURE); | ||
| 46 | } | ||
| 47 | |||
| 48 | static void vperror_msg(const char *s, va_list p) | ||
| 49 | { | ||
| 50 | int err = errno; | ||
| 51 | |||
| 52 | if (s == 0) | ||
| 53 | s = ""; | ||
| 54 | verror_msg(s, p); | ||
| 55 | if (*s) | ||
| 56 | s = ": "; | ||
| 57 | fprintf(stderr, "%s%s\n", s, strerror(err)); | ||
| 58 | } | ||
| 59 | |||
| 60 | #if 0 | ||
| 61 | static void perror_msg(const char *s, ...) | ||
| 62 | { | ||
| 63 | va_list p; | ||
| 64 | |||
| 65 | va_start(p, s); | ||
| 66 | vperror_msg(s, p); | ||
| 67 | va_end(p); | ||
| 68 | } | ||
| 69 | #endif | ||
| 70 | |||
| 71 | static void perror_msg_and_die(const char *s, ...) | ||
| 72 | { | ||
| 73 | va_list p; | ||
| 74 | |||
| 75 | va_start(p, s); | ||
| 76 | vperror_msg(s, p); | ||
| 77 | va_end(p); | ||
| 78 | exit(EXIT_FAILURE); | ||
| 79 | } | ||
| 80 | |||
| 81 | static FILE *xfopen(const char *path, const char *mode) | ||
| 82 | { | ||
| 83 | FILE *fp; | ||
| 84 | |||
| 85 | if ((fp = fopen(path, mode)) == NULL) | ||
| 86 | perror_msg_and_die("%s", path); | ||
| 87 | return fp; | ||
| 88 | } | ||
| 89 | |||
| 90 | static char *xstrdup(const char *s) | ||
| 91 | { | ||
| 92 | char *t; | ||
| 93 | |||
| 94 | if (s == NULL) | ||
| 95 | return NULL; | ||
| 96 | |||
| 97 | t = strdup(s); | ||
| 98 | |||
| 99 | if (t == NULL) | ||
| 100 | error_msg_and_die(memory_exhausted); | ||
| 101 | |||
| 102 | return t; | ||
| 103 | } | ||
| 104 | |||
| 105 | |||
| 106 | static void add_new_directory(char *name, char *path, | ||
| 107 | unsigned long uid, unsigned long gid, unsigned long mode) | ||
| 108 | { | ||
| 109 | // printf("Directory: %s %s UID: %ld GID %ld MODE: %ld\n", path, name, uid, gid, mode); | ||
| 110 | } | ||
| 111 | |||
| 112 | static void add_new_device(char *name, char *path, unsigned long uid, | ||
| 113 | unsigned long gid, unsigned long mode, dev_t rdev) | ||
| 114 | { | ||
| 115 | int status; | ||
| 116 | struct stat sb; | ||
| 117 | time_t timestamp = time(NULL); | ||
| 118 | |||
| 119 | memset(&sb, 0, sizeof(struct stat)); | ||
| 120 | status = lstat(path, &sb); | ||
| 121 | |||
| 122 | if (status >= 0) { | ||
| 123 | /* It is ok for some types of files to not exit on disk (such as | ||
| 124 | * device nodes), but if they _do_ exist the specified mode had | ||
| 125 | * better match the actual file or strange things will happen.... */ | ||
| 126 | if ((mode & S_IFMT) != (sb.st_mode & S_IFMT)) | ||
| 127 | error_msg_and_die("%s: file type does not match specified type!", path); | ||
| 128 | timestamp = sb.st_mtime; | ||
| 129 | } | ||
| 130 | |||
| 131 | mknod(name, mode, rdev); | ||
| 132 | // printf("Device: %s %s UID: %ld GID: %ld MODE: %ld MAJOR: %d MINOR: %d\n", | ||
| 133 | // path, name, uid, gid, mode, (short)(rdev >> 8), (short)(rdev & 0xff)); | ||
| 134 | } | ||
| 135 | |||
| 136 | static void add_new_file(char *name, char *path, unsigned long uid, | ||
| 137 | unsigned long gid, unsigned long mode) | ||
| 138 | { | ||
| 139 | // printf("File: %s %s UID: %ld GID: %ld MODE: %ld\n", | ||
| 140 | // path, name, gid, uid, mode); | ||
| 141 | } | ||
| 142 | |||
| 143 | |||
| 144 | /* device table entries take the form of: | ||
| 145 | <path> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count> | ||
| 146 | /dev/mem c 640 0 0 1 1 0 0 - | ||
| 147 | |||
| 148 | type can be one of: | ||
| 149 | f A regular file | ||
| 150 | d Directory | ||
| 151 | c Character special device file | ||
| 152 | b Block special device file | ||
| 153 | p Fifo (named pipe) | ||
| 154 | |||
| 155 | I don't bother with symlinks (permissions are irrelevant), hard | ||
| 156 | links (special cases of regular files), or sockets (why bother). | ||
| 157 | |||
| 158 | Regular files must exist in the target root directory. If a char, | ||
| 159 | block, fifo, or directory does not exist, it will be created. | ||
| 160 | */ | ||
| 161 | static int interpret_table_entry(char *line) | ||
| 162 | { | ||
| 163 | char *name; | ||
| 164 | char path[4096], type; | ||
| 165 | unsigned long mode = 0755, uid = 0, gid = 0, major = 0, minor = 0; | ||
| 166 | unsigned long start = 0, increment = 1, count = 0; | ||
| 167 | |||
| 168 | if (0 > sscanf(line, "%40s %c %lo %lu %lu %lu %lu %lu %lu %lu", path, | ||
| 169 | &type, &mode, &uid, &gid, &major, &minor, &start, | ||
| 170 | &increment, &count)) | ||
| 171 | { | ||
| 172 | return 1; | ||
| 173 | } | ||
| 174 | |||
| 175 | if (!strcmp(path, "/")) { | ||
| 176 | error_msg_and_die("Device table entries require absolute paths"); | ||
| 177 | } | ||
| 178 | name = xstrdup(path + 1); | ||
| 179 | sprintf(path, "%s/%s\0", rootdir, name); | ||
| 180 | |||
| 181 | switch (type) { | ||
| 182 | case 'd': | ||
| 183 | mode |= S_IFDIR; | ||
| 184 | add_new_directory(name, path, uid, gid, mode); | ||
| 185 | break; | ||
| 186 | case 'f': | ||
| 187 | mode |= S_IFREG; | ||
| 188 | add_new_file(name, path, uid, gid, mode); | ||
| 189 | break; | ||
| 190 | case 'p': | ||
| 191 | mode |= S_IFIFO; | ||
| 192 | add_new_file(name, path, uid, gid, mode); | ||
| 193 | break; | ||
| 194 | case 'c': | ||
| 195 | case 'b': | ||
| 196 | mode |= (type == 'c') ? S_IFCHR : S_IFBLK; | ||
| 197 | if (count > 0) { | ||
| 198 | int i; | ||
| 199 | dev_t rdev; | ||
| 200 | char buf[80]; | ||
| 201 | |||
| 202 | for (i = start; i < count; i++) { | ||
| 203 | sprintf(buf, "%s%d", name, i); | ||
| 204 | /* FIXME: MKDEV uses illicit insider knowledge of kernel | ||
| 205 | * major/minor representation... */ | ||
| 206 | rdev = MKDEV(major, minor + (i * increment - start)); | ||
| 207 | add_new_device(buf, path, uid, gid, mode, rdev); | ||
| 208 | } | ||
| 209 | } else { | ||
| 210 | /* FIXME: MKDEV uses illicit insider knowledge of kernel | ||
| 211 | * major/minor representation... */ | ||
| 212 | dev_t rdev = MKDEV(major, minor); | ||
| 213 | |||
| 214 | add_new_device(name, path, uid, gid, mode, rdev); | ||
| 215 | } | ||
| 216 | break; | ||
| 217 | default: | ||
| 218 | error_msg_and_die("Unsupported file type"); | ||
| 219 | } | ||
| 220 | if (name) free(name); | ||
| 221 | return 0; | ||
| 222 | } | ||
| 223 | |||
| 224 | |||
| 225 | static void parse_device_table(FILE * file) | ||
| 226 | { | ||
| 227 | char *line; | ||
| 228 | size_t length = 256; | ||
| 229 | int len = 0; | ||
| 230 | |||
| 231 | /* Looks ok so far. The general plan now is to read in one | ||
| 232 | * line at a time, check for leading comment delimiters ('#'), | ||
| 233 | * then try and parse the line as a device table. If we fail | ||
| 234 | * to parse things, try and help the poor fool to fix their | ||
| 235 | * device table with a useful error msg... */ | ||
| 236 | |||
| 237 | if((line = (char *)malloc(length)) == NULL) { | ||
| 238 | fclose(file); | ||
| 239 | return; | ||
| 240 | } | ||
| 241 | |||
| 242 | while ((len = getline(&line, &length, file)) != -1) { | ||
| 243 | /* First trim off any whitespace */ | ||
| 244 | |||
| 245 | /* trim trailing whitespace */ | ||
| 246 | while (len > 0 && isspace(line[len - 1])) | ||
| 247 | line[--len] = '\0'; | ||
| 248 | |||
| 249 | /* trim leading whitespace */ | ||
| 250 | memmove(line, &line[strspn(line, " \n\r\t\v")], len + 1); | ||
| 251 | |||
| 252 | /* If this is NOT a comment line, try to interpret it */ | ||
| 253 | if (*line != '#') interpret_table_entry(line); | ||
| 254 | } | ||
| 255 | if (line) free(line); | ||
| 256 | |||
| 257 | fclose(file); | ||
| 258 | } | ||
| 259 | |||
| 260 | static int go(char *dname, FILE * devtable) | ||
| 261 | { | ||
| 262 | struct stat sb; | ||
| 263 | |||
| 264 | if (lstat(dname, &sb)) { | ||
| 265 | perror_msg_and_die("%s", dname); | ||
| 266 | } | ||
| 267 | if (chdir(dname)) | ||
| 268 | perror_msg_and_die("%s", dname); | ||
| 269 | |||
| 270 | if (devtable) | ||
| 271 | parse_device_table(devtable); | ||
| 272 | |||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | |||
| 277 | static struct option long_options[] = { | ||
| 278 | {"root", 1, NULL, 'r'}, | ||
| 279 | {"help", 0, NULL, 'h'}, | ||
| 280 | {"squash", 0, NULL, 'q'}, | ||
| 281 | {"version", 0, NULL, 'v'}, | ||
| 282 | {"devtable", 1, NULL, 'D'}, | ||
| 283 | {NULL, 0, NULL, 0} | ||
| 284 | }; | ||
| 285 | |||
| 286 | static char *helptext = | ||
| 287 | "Usage: makedevs [OPTIONS]\n" | ||
| 288 | "Build entries based upon device_table.txt\n\n" | ||
| 289 | "Options:\n" | ||
| 290 | " -r, -d, --root=DIR Build filesystem from directory DIR (default: cwd)\n" | ||
| 291 | " -D, --devtable=FILE Use the named FILE as a device table file\n" | ||
| 292 | " -q, --squash Squash permissions and owners making all files be owned by root\n" | ||
| 293 | " -h, --help Display this help text\n" | ||
| 294 | " -v, --version Display version information\n\n"; | ||
| 295 | |||
| 296 | |||
| 297 | static char *revtext = "$Revision: 0.1 $"; | ||
| 298 | |||
| 299 | int main(int argc, char **argv) | ||
| 300 | { | ||
| 301 | int c, opt; | ||
| 302 | extern char *optarg; | ||
| 303 | struct stat statbuf; | ||
| 304 | FILE *devtable = NULL; | ||
| 305 | |||
| 306 | umask (0); | ||
| 307 | |||
| 308 | while ((opt = getopt_long(argc, argv, "D:d:r:qhv", | ||
| 309 | long_options, &c)) >= 0) { | ||
| 310 | switch (opt) { | ||
| 311 | case 'D': | ||
| 312 | devtable = xfopen(optarg, "r"); | ||
| 313 | if (fstat(fileno(devtable), &statbuf) < 0) | ||
| 314 | perror_msg_and_die(optarg); | ||
| 315 | if (statbuf.st_size < 10) | ||
| 316 | error_msg_and_die("%s: not a proper device table file", optarg); | ||
| 317 | break; | ||
| 318 | case 'h': | ||
| 319 | fprintf(stderr, helptext); | ||
| 320 | exit(1); | ||
| 321 | case 'r': | ||
| 322 | case 'd': /* for compatibility with mkfs.jffs, genext2fs, etc... */ | ||
| 323 | if (rootdir != default_rootdir) { | ||
| 324 | error_msg_and_die("root directory specified more than once"); | ||
| 325 | } | ||
| 326 | rootdir = xstrdup(optarg); | ||
| 327 | break; | ||
| 328 | |||
| 329 | case 'v': | ||
| 330 | fprintf(stderr, "makedevs revision %.*s\n", | ||
| 331 | (int) strlen(revtext) - 13, revtext + 11); | ||
| 332 | exit(1); | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | go(rootdir, devtable); | ||
| 337 | return 0; | ||
| 338 | } | ||
diff --git a/meta/packages/makedevs/makedevs-native_1.0.0.bb b/meta/packages/makedevs/makedevs-native_1.0.0.bb new file mode 100644 index 0000000000..1a79403550 --- /dev/null +++ b/meta/packages/makedevs/makedevs-native_1.0.0.bb | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | SECTION = "base" | ||
| 2 | include makedevs_${PV}.bb | ||
| 3 | inherit native | ||
| 4 | |||
| 5 | FILESDIR = "${@os.path.dirname(bb.data.getVar('FILE',d,1))}/makedevs-${PV}" | ||
| 6 | |||
| 7 | do_stage() { | ||
| 8 | install -d ${STAGING_BINDIR}/ | ||
| 9 | install -m 0755 ${S}/makedevs ${STAGING_BINDIR}/ | ||
| 10 | } | ||
diff --git a/meta/packages/makedevs/makedevs_1.0.0.bb b/meta/packages/makedevs/makedevs_1.0.0.bb new file mode 100644 index 0000000000..f6c1ffbfa1 --- /dev/null +++ b/meta/packages/makedevs/makedevs_1.0.0.bb | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | DESCRIPTION = "A tool to make device nodes" | ||
| 2 | LICENSE = "GPL" | ||
| 3 | SECTION = "base" | ||
| 4 | PRIORITY = "required" | ||
| 5 | SRC_URI = "file://makedevs.c" | ||
| 6 | S = "${WORKDIR}/makedevs-${PV}" | ||
| 7 | PR = "r2" | ||
| 8 | |||
| 9 | do_configure() { | ||
| 10 | install -m 0644 ${WORKDIR}/makedevs.c ${S}/ | ||
| 11 | } | ||
| 12 | |||
| 13 | do_compile() { | ||
| 14 | ${CC} ${CFLAGS} -o ${S}/makedevs ${S}/makedevs.c | ||
| 15 | } | ||
| 16 | |||
| 17 | do_install() { | ||
| 18 | install -d ${D}${base_sbindir} | ||
| 19 | install -m 0755 ${S}/makedevs ${D}${base_sbindir}/makedevs | ||
| 20 | } | ||
