+static int load_dep_bb(void)
+{
+ char *line;
+ FILE *fp = fopen_for_read(DEPFILE_BB);
+
+ if (!fp)
+ return 0;
+
+ dep_bb_seen = 1;
+ dbg1_error_msg("loading "DEPFILE_BB);
+
+ /* Why? There is a rare scenario: we did not find modprobe.dep.bb,
+ * we scanned the dir and found no module by name, then we search
+ * for alias (full scan), and we decided to generate modprobe.dep.bb.
+ * But we see modprobe.dep.bb.new! Other modprobe is at work!
+ * We wait and other modprobe renames it to modprobe.dep.bb.
+ * Now we can use it.
+ * But we already have modinfo[] filled, and "module_count = 0"
+ * makes us start anew. Yes, we leak modinfo[].xxx pointers -
+ * there is not much of data there anyway. */
+ module_count = 0;
+ memset(&modinfo[0], 0, sizeof(modinfo[0]));
+
+ while ((line = xmalloc_fgetline(fp)) != NULL) {
+ char* space;
+ char* linebuf;
+ int cur;
+
+ if (!line[0]) {
+ free(line);
+ continue;
+ }
+ space = strchrnul(line, ' ');
+ cur = module_count++;
+ modinfo = xrealloc_vector(modinfo, 12, cur);
+ /*modinfo[cur+1].pathname = NULL; - xrealloc_vector did it */
+ modinfo[cur].pathname = line; /* we take ownership of malloced block here */
+ if (*space)
+ *space++ = '\0';
+ modinfo[cur].aliases = space;
+ linebuf = xmalloc_fgetline(fp);
+ modinfo[cur].deps = linebuf ? linebuf : xzalloc(1);
+ if (modinfo[cur].deps[0]) {
+ /* deps are not "", so next line must be empty */
+ line = xmalloc_fgetline(fp);
+ /* Refuse to work with damaged config file */
+ if (line && line[0])
+ bb_error_msg_and_die("error in %s at '%s'", DEPFILE_BB, line);
+ free(line);
+ }
+ }
+ return 1;
+}
+
+static int start_dep_bb_writeout(void)
+{
+ int fd;
+
+ /* depmod -n: write result to stdout */
+ if (applet_name[0] == 'd' && (option_mask32 & 1))
+ return STDOUT_FILENO;
+
+ fd = open(DEPFILE_BB".new", O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0644);
+ if (fd < 0) {
+ if (errno == EEXIST) {
+ int count = 5 * 20;
+ dbg1_error_msg(DEPFILE_BB".new exists, waiting for "DEPFILE_BB);
+ while (1) {
+ usleep(1000*1000 / 20);
+ if (load_dep_bb()) {
+ dbg1_error_msg(DEPFILE_BB" appeared");
+ return -2; /* magic number */
+ }
+ if (!--count)
+ break;
+ }
+ bb_error_msg("deleting stale %s", DEPFILE_BB".new");
+ fd = open_or_warn(DEPFILE_BB".new", O_WRONLY | O_CREAT | O_TRUNC);
+ }
+ }
+ dbg1_error_msg("opened "DEPFILE_BB".new:%d", fd);
+ return fd;
+}
+
+static void write_out_dep_bb(int fd)
+{
+ int i;
+ FILE *fp;
+
+ /* We want good error reporting. fdprintf is not good enough. */
+ fp = xfdopen_for_write(fd);
+ i = 0;
+ while (modinfo[i].pathname) {
+ fprintf(fp, "%s%s%s\n" "%s%s\n",
+ modinfo[i].pathname, modinfo[i].aliases[0] ? " " : "", modinfo[i].aliases,
+ modinfo[i].deps, modinfo[i].deps[0] ? "\n" : "");
+ i++;
+ }
+ /* Badly formatted depfile is a no-no. Be paranoid. */
+ errno = 0;
+ if (ferror(fp) | fclose(fp)) /* | instead of || is intended */
+ goto err;
+
+ if (fd == STDOUT_FILENO) /* it was depmod -n */
+ goto ok;
+
+ if (rename(DEPFILE_BB".new", DEPFILE_BB) != 0) {
+ err:
+ bb_perror_msg("can't create '%s'", DEPFILE_BB);
+ unlink(DEPFILE_BB".new");
+ } else {
+ ok:
+ wrote_dep_bb_ok = 1;
+ dbg1_error_msg("created "DEPFILE_BB);
+ }
+}
+