+/*
+ * Callback to retrieve progress information from Busybox utilities.
+ * Busybox utilities use a common progress bar format which progress percentage
+ * and current size can be can be parsed from.
+ */
+static int busybox_progress_cb(void *arg)
+{
+ const char *busybox_fmt = "%*s %u%*[%* |]%u%c %*u:%*u:%*u ETA\n";
+ struct process_info *procinfo = arg;
+ char *n, *s, suffix, *line = NULL;
+ struct device_handler *handler;
+ unsigned int percentage, size;
+ struct process *p;
+ int rc;
+
+ if (!arg)
+ return -1;
+
+ p = procinfo_get_process(procinfo);
+ handler = p->stdout_data;
+
+ rc = process_stdout_custom(procinfo, &line);
+
+ if (rc) {
+ /* Unregister ourselves from progress tracking */
+ device_handler_status_download_remove(handler, procinfo);
+ }
+
+ if (rc || !line)
+ return rc;
+
+ rc = sscanf(line, busybox_fmt, &percentage, &size, &suffix);
+
+ /*
+ * Many unrecognised lines are partial updates. If we see a partial
+ * line with a newline character, see if we can match a valid line
+ * at the end of stdout_buf
+ */
+ if (rc != 3) {
+ n = strchr(line, '\n');
+ if (n)
+ for (s = n - 1; s >= p->stdout_buf; s--)
+ if (*s == '\n') {
+ rc = sscanf(s + 1, busybox_fmt,
+ &percentage, &size, &suffix);
+ break;
+ }
+ }
+
+ if (rc != 3)
+ percentage = size = 0;
+
+ device_handler_status_download(handler, procinfo,
+ percentage, size, suffix);
+
+ return 0;
+}
+
+
+