static tn_array *parse_changelog(tn_alloc *na, tn_array *lines) { struct changelog_ent *ent = NULL; int i, max_MESSAGE = 1024; tn_array *entries; tn_buf *logmsg; entries = n_array_new(8, NULL, (tn_fn_cmp)changelog_ent_cmp); logmsg = n_buf_new(1024); for (i = 0; i < n_array_size(lines); i++) { char *line = n_array_nth(lines, i); if (*line == '*') { char *ts; if (ent != NULL) { n_snprintf(ent->message, max_MESSAGE, "%s", n_buf_ptr(logmsg)); n_buf_clean(logmsg); n_array_push(entries, ent); ent = NULL; } ent = na->na_malloc(na, sizeof(*ent) + max_MESSAGE); memset(ent, 0, sizeof(*ent)); ent->info = na_strdup(na, line, strlen(line)); ent->message[0] = '\0'; //* [rREV] YYYY-MM-DD HH:MM:SS rest ts = strchr(line, ' '); while (*ts && isspace(*ts)) ts++; if (ts && *ts == 'r') ts = strchr(ts, ' '); if (ts) { while (*ts && isspace(*ts)) ts++; if (ts) ent->ts = parse_datetime(ts); } continue; } if (ent) n_buf_printf(logmsg, "%s\n", line); } if (ent != NULL) { n_snprintf(ent->message, max_MESSAGE, "%s", n_buf_ptr(logmsg)); n_array_push(entries, ent); } n_buf_free(logmsg); return entries; }
static time_t parse_time (const char *p, const time_t now) { struct timespec nowspec = { 0, 0 }; struct timespec thenspec; nowspec.tv_sec = now; if (!parse_datetime (&thenspec, p, &nowspec)) return BAD_TIME; return thenspec.tv_sec; }
/* FIXME: an error exit at field i leaves fields [0..i) modified. */ bool format_from_json( void *dest, JsonObject *obj, const struct field_desc *fields, size_t num_fields, GError **err_p) { for(size_t i=0; i < num_fields; i++) { const char *name = fields[i].name; JsonNode *node = json_object_get_member(obj, name); if(node == NULL) { /* not present. skip. */ continue; } bool null_ok = islower(fields[i].type), is_null = json_node_is_null(node); if(!null_ok && is_null) { g_set_error(err_p, 0, 0, "%s: field `%s' is null, but not allowed to", __func__, name); return false; } void *ptr = dest + fields[i].offset; switch(tolower(fields[i].type)) { case 'i': *(uint64_t *)ptr = is_null ? 0 : json_object_get_int_member(obj, name); break; case 'b': *(bool *)ptr = is_null ? false : json_object_get_boolean_member(obj, name); break; case 's': g_free(*(char **)ptr); *(char **)ptr = is_null ? NULL : g_strdup(json_object_get_string_member(obj, name)); break; case 't': { GDateTime **dt_p = ptr; if(*dt_p != NULL) { g_date_time_unref(*dt_p); *dt_p = NULL; } *dt_p = parse_datetime(json_object_get_string_member(obj, name)); break; } default: assert(false); } } return true; }
int Exosite_SyncTime() { char day[11]; char time[9]; int http_status = 0; int strLen; char *testStr = "GET /ip HTTP/1.1\r\n"; unsigned char serverAddr[6] = {54, 183, 115, 21, 0, 80}; char strBuf[RX_SIZE]; DateTime datetime; if (!exosite_initialized) { return -1; } long sock = connect_to_exosite_with_server_addr("", serverAddr); if (sock < 0) { return -1; } exoHAL_SocketSend(sock, testStr, strlen(testStr)); sendLine(sock, HOST_LINE, NULL); sendLine(sock, ACCEPT_LINE, "\r\n"); http_status = get_http_status(sock); if (200 != http_status) return -1; strLen = exoHAL_SocketRecv(sock, strBuf, RX_SIZE); exoHAL_SocketClose(sock); if(strLen <= 0) return -1; if(parse_datetime(strBuf, strLen, &datetime) < 0) return -1; sprintf(day, "%s/%02d/%s", datetime.dayStr, month_to_num(datetime.monStr), datetime.yearStr); sprintf(time, "%s:%s:%s", datetime.hourStr, datetime.minStr, datetime.secStr); if(AtLibGs_SetTime(day, time) != ATLIBGS_MSG_ID_OK) return -1; return 0; }
int things_list(struct http_request *req) { int rc; char *zErrMsg = 0; char *query = "SELECT * FROM found ORDER BY last DESC"; template_t tmpl; attrlist_t attributes; struct timespec when; buf = kore_buf_create(mb); if(!thing) thing = hashmap_new(); // load template from assets template_load (asset_things_list_html, asset_len_things_list_html, &tmpl); // initialise attribute list attributes = attrinit(); if( ! parse_datetime(&when, "now", NULL) ) kore_log(LOG_ERR,"parse-datetime error"); else { struct tm *tt; tt = localtime (&when.tv_sec); mktime(tt); strftime(line, ml, "Dowse :: %d %m %Y - %H:%M:%S", tt); attrcat(attributes, "title", line); } sqlquery(query, things_list_cb, attributes); template_apply(&tmpl, attributes, buf); http_response(req, 200, buf->data, buf->offset); template_free(&tmpl); attrfree(attributes); kore_buf_free(buf); return (KORE_RESULT_OK); }
gboolean ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError **error) { GOptionContext *context; glnx_unref_object OstreeRepo *repo = NULL; gboolean ret = FALSE; gboolean skip_commit = FALSE; g_autoptr(GFile) object_to_commit = NULL; g_autofree char *parent = NULL; g_autofree char *commit_checksum = NULL; g_autoptr(GFile) root = NULL; g_autoptr(GVariant) metadata = NULL; g_autoptr(GVariant) detached_metadata = NULL; glnx_unref_object OstreeMutableTree *mtree = NULL; g_autofree char *tree_type = NULL; g_autoptr(GHashTable) mode_adds = NULL; g_autoptr(GHashTable) skip_list = NULL; OstreeRepoCommitModifierFlags flags = 0; OstreeRepoCommitModifier *modifier = NULL; OstreeRepoTransactionStats stats; struct CommitFilterData filter_data = { 0, }; context = g_option_context_new ("[PATH] - Commit a new revision"); if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error)) goto out; if (!ostree_ensure_repo_writable (repo, error)) goto out; if (opt_statoverride_file) { mode_adds = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); if (!parse_file_by_line (opt_statoverride_file, handle_statoverride_line, mode_adds, cancellable, error)) goto out; } if (opt_skiplist_file) { skip_list = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); if (!parse_file_by_line (opt_skiplist_file, handle_skiplist_line, skip_list, cancellable, error)) goto out; } if (opt_metadata_strings) { if (!parse_keyvalue_strings (opt_metadata_strings, &metadata, error)) goto out; } if (opt_detached_metadata_strings) { if (!parse_keyvalue_strings (opt_detached_metadata_strings, &detached_metadata, error)) goto out; } if (!(opt_branch || opt_orphan)) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "A branch must be specified with --branch, or use --orphan"); goto out; } if (opt_no_xattrs) flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS; if (opt_generate_sizes) flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES; if (opt_disable_fsync) ostree_repo_set_disable_fsync (repo, TRUE); if (flags != 0 || opt_owner_uid >= 0 || opt_owner_gid >= 0 || opt_statoverride_file != NULL || opt_skiplist_file != NULL || opt_no_xattrs) { filter_data.mode_adds = mode_adds; filter_data.skip_list = skip_list; modifier = ostree_repo_commit_modifier_new (flags, commit_filter, &filter_data, NULL); } if (opt_parent) { if (g_str_equal (opt_parent, "none")) parent = NULL; else { if (!ostree_validate_checksum_string (opt_parent, error)) goto out; parent = g_strdup (opt_parent); } } else if (!opt_orphan) { if (!ostree_repo_resolve_rev (repo, opt_branch, TRUE, &parent, error)) { if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY)) { /* A folder exists with the specified ref name, * which is handled by _ostree_repo_write_ref */ g_clear_error (error); } else goto out; } } if (opt_editor) { if (!commit_editor (repo, opt_branch, &opt_subject, &opt_body, cancellable, error)) goto out; } if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) goto out; if (opt_link_checkout_speedup && !ostree_repo_scan_hardlinks (repo, cancellable, error)) goto out; mtree = ostree_mutable_tree_new (); if (argc <= 1 && (opt_trees == NULL || opt_trees[0] == NULL)) { if (!ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, ".", mtree, modifier, cancellable, error)) goto out; } else if (opt_trees != NULL) { const char *const*tree_iter; const char *tree; const char *eq; for (tree_iter = (const char *const*)opt_trees; *tree_iter; tree_iter++) { tree = *tree_iter; eq = strchr (tree, '='); if (!eq) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Missing type in tree specification '%s'", tree); goto out; } g_free (tree_type); tree_type = g_strndup (tree, eq - tree); tree = eq + 1; g_clear_object (&object_to_commit); if (strcmp (tree_type, "dir") == 0) { if (!ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, tree, mtree, modifier, cancellable, error)) goto out; } else if (strcmp (tree_type, "tar") == 0) { object_to_commit = g_file_new_for_path (tree); if (!ostree_repo_write_archive_to_mtree (repo, object_to_commit, mtree, modifier, opt_tar_autocreate_parents, cancellable, error)) goto out; } else if (strcmp (tree_type, "ref") == 0) { if (!ostree_repo_read_commit (repo, tree, &object_to_commit, NULL, cancellable, error)) goto out; if (!ostree_repo_write_directory_to_mtree (repo, object_to_commit, mtree, modifier, cancellable, error)) goto out; } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid tree type specification '%s'", tree_type); goto out; } } } else { g_assert (argc > 1); if (!ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, argv[1], mtree, modifier, cancellable, error)) goto out; } if (mode_adds && g_hash_table_size (mode_adds) > 0) { GHashTableIter hash_iter; gpointer key, value; g_hash_table_iter_init (&hash_iter, mode_adds); while (g_hash_table_iter_next (&hash_iter, &key, &value)) { g_printerr ("Unmatched statoverride path: %s\n", (char*)key); } g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unmatched statoverride paths"); goto out; } if (skip_list && g_hash_table_size (skip_list) > 0) { GHashTableIter hash_iter; gpointer key; g_hash_table_iter_init (&hash_iter, skip_list); while (g_hash_table_iter_next (&hash_iter, &key, NULL)) { g_printerr ("Unmatched skip-list path: %s\n", (char*)key); } g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unmatched skip-list paths"); goto out; } if (!ostree_repo_write_mtree (repo, mtree, &root, cancellable, error)) goto out; if (opt_skip_if_unchanged && parent) { g_autoptr(GFile) parent_root; if (!ostree_repo_read_commit (repo, parent, &parent_root, NULL, cancellable, error)) goto out; if (g_file_equal (root, parent_root)) skip_commit = TRUE; } if (!skip_commit) { gboolean update_summary; guint64 timestamp; if (!opt_timestamp) { GDateTime *now = g_date_time_new_now_utc (); timestamp = g_date_time_to_unix (now); g_date_time_unref (now); if (!ostree_repo_write_commit (repo, parent, opt_subject, opt_body, metadata, OSTREE_REPO_FILE (root), &commit_checksum, cancellable, error)) goto out; } else { struct timespec ts; if (!parse_datetime (&ts, opt_timestamp, NULL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Could not parse '%s'", opt_timestamp); goto out; } timestamp = ts.tv_sec; if (!ostree_repo_write_commit_with_time (repo, parent, opt_subject, opt_body, metadata, OSTREE_REPO_FILE (root), timestamp, &commit_checksum, cancellable, error)) goto out; } if (detached_metadata) { if (!ostree_repo_write_commit_detached_metadata (repo, commit_checksum, detached_metadata, cancellable, error)) goto out; } if (opt_key_ids) { char **iter; for (iter = opt_key_ids; iter && *iter; iter++) { const char *keyid = *iter; if (!ostree_repo_sign_commit (repo, commit_checksum, keyid, opt_gpg_homedir, cancellable, error)) goto out; } } if (opt_branch) ostree_repo_transaction_set_ref (repo, NULL, opt_branch, commit_checksum); else g_assert (opt_orphan); if (!ostree_repo_commit_transaction (repo, &stats, cancellable, error)) goto out; /* The default for this option is FALSE, even for archive-z2 repos, * because ostree supports multiple processes committing to the same * repo (but different refs) concurrently, and in fact gnome-continuous * actually does this. In that context it's best to update the summary * explicitly instead of automatically here. */ if (!ot_keyfile_get_boolean_with_default (ostree_repo_get_config (repo), "core", "commit-update-summary", FALSE, &update_summary, error)) goto out; if (update_summary && !ostree_repo_regenerate_summary (repo, NULL, cancellable, error)) goto out; } else { commit_checksum = g_strdup (parent); } if (opt_table_output) { g_print ("Commit: %s\n", commit_checksum); g_print ("Metadata Total: %u\n", stats.metadata_objects_total); g_print ("Metadata Written: %u\n", stats.metadata_objects_written); g_print ("Content Total: %u\n", stats.content_objects_total); g_print ("Content Written: %u\n", stats.content_objects_written); g_print ("Content Bytes Written: %" G_GUINT64_FORMAT "\n", stats.content_bytes_written); } else { g_print ("%s\n", commit_checksum); } ret = TRUE; out: if (repo) ostree_repo_abort_transaction (repo, cancellable, NULL); if (context) g_option_context_free (context); if (modifier) ostree_repo_commit_modifier_unref (modifier); return ret; }
int main (int argc _GL_UNUSED, char **argv) { struct timespec result; struct timespec result2; struct timespec expected; struct timespec now; const char *p; int i; long gmtoff; set_program_name (argv[0]); gmtoff = gmt_offset (); /* ISO 8601 extended date and time of day representation, 'T' separator, local time zone */ p = "2011-05-01T11:55:18"; expected.tv_sec = 1304250918 - gmtoff; expected.tv_nsec = 0; ASSERT (parse_datetime (&result, p, 0)); LOG (p, expected, result); ASSERT (expected.tv_sec == result.tv_sec && expected.tv_nsec == result.tv_nsec); /* ISO 8601 extended date and time of day representation, ' ' separator, local time zone */ p = "2011-05-01 11:55:18"; expected.tv_sec = 1304250918 - gmtoff; expected.tv_nsec = 0; ASSERT (parse_datetime (&result, p, 0)); LOG (p, expected, result); ASSERT (expected.tv_sec == result.tv_sec && expected.tv_nsec == result.tv_nsec); /* ISO 8601, extended date and time of day representation, 'T' separator, UTC */ p = "2011-05-01T11:55:18Z"; expected.tv_sec = 1304250918; expected.tv_nsec = 0; ASSERT (parse_datetime (&result, p, 0)); LOG (p, expected, result); ASSERT (expected.tv_sec == result.tv_sec && expected.tv_nsec == result.tv_nsec); /* ISO 8601, extended date and time of day representation, ' ' separator, UTC */ p = "2011-05-01 11:55:18Z"; expected.tv_sec = 1304250918; expected.tv_nsec = 0; ASSERT (parse_datetime (&result, p, 0)); LOG (p, expected, result); ASSERT (expected.tv_sec == result.tv_sec && expected.tv_nsec == result.tv_nsec); /* ISO 8601 extended date and time of day representation, 'T' separator, w/UTC offset */ p = "2011-05-01T11:55:18-07:00"; expected.tv_sec = 1304276118; expected.tv_nsec = 0; ASSERT (parse_datetime (&result, p, 0)); LOG (p, expected, result); ASSERT (expected.tv_sec == result.tv_sec && expected.tv_nsec == result.tv_nsec); /* ISO 8601 extended date and time of day representation, ' ' separator, w/UTC offset */ p = "2011-05-01 11:55:18-07:00"; expected.tv_sec = 1304276118; expected.tv_nsec = 0; ASSERT (parse_datetime (&result, p, 0)); LOG (p, expected, result); ASSERT (expected.tv_sec == result.tv_sec && expected.tv_nsec == result.tv_nsec); /* ISO 8601 extended date and time of day representation, 'T' separator, w/hour only UTC offset */ p = "2011-05-01T11:55:18-07"; expected.tv_sec = 1304276118; expected.tv_nsec = 0; ASSERT (parse_datetime (&result, p, 0)); LOG (p, expected, result); ASSERT (expected.tv_sec == result.tv_sec && expected.tv_nsec == result.tv_nsec); /* ISO 8601 extended date and time of day representation, ' ' separator, w/hour only UTC offset */ p = "2011-05-01 11:55:18-07"; expected.tv_sec = 1304276118; expected.tv_nsec = 0; ASSERT (parse_datetime (&result, p, 0)); LOG (p, expected, result); ASSERT (expected.tv_sec == result.tv_sec && expected.tv_nsec == result.tv_nsec); now.tv_sec = 4711; now.tv_nsec = 1267; p = "now"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); ASSERT (now.tv_sec == result.tv_sec && now.tv_nsec == result.tv_nsec); now.tv_sec = 4711; now.tv_nsec = 1267; p = "tomorrow"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); ASSERT (now.tv_sec + 24 * 60 * 60 == result.tv_sec && now.tv_nsec == result.tv_nsec); now.tv_sec = 4711; now.tv_nsec = 1267; p = "yesterday"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); ASSERT (now.tv_sec - 24 * 60 * 60 == result.tv_sec && now.tv_nsec == result.tv_nsec); now.tv_sec = 4711; now.tv_nsec = 1267; p = "4 hours"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); ASSERT (now.tv_sec + 4 * 60 * 60 == result.tv_sec && now.tv_nsec == result.tv_nsec); /* test if timezone is not being ignored for day offset */ now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC+400 +24 hours"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); p = "UTC+400 +1 day"; ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); /* test if several time zones formats are handled same way */ now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC+14:00"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); p = "UTC+14"; ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); p = "UTC+1400"; ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC-14:00"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); p = "UTC-14"; ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); p = "UTC-1400"; ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC+0:15"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); p = "UTC+0015"; ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC-1:30"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); p = "UTC-130"; ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); /* TZ out of range should cause parse_datetime failure */ now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC+25:00"; ASSERT (!parse_datetime (&result, p, &now)); /* Check for several invalid countable dayshifts */ now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC+4:00 +40 yesterday"; ASSERT (!parse_datetime (&result, p, &now)); p = "UTC+4:00 next yesterday"; ASSERT (!parse_datetime (&result, p, &now)); p = "UTC+4:00 tomorrow ago"; ASSERT (!parse_datetime (&result, p, &now)); p = "UTC+4:00 tomorrow hence"; ASSERT (!parse_datetime (&result, p, &now)); p = "UTC+4:00 40 now ago"; ASSERT (!parse_datetime (&result, p, &now)); p = "UTC+4:00 last tomorrow"; ASSERT (!parse_datetime (&result, p, &now)); p = "UTC+4:00 -4 today"; ASSERT (!parse_datetime (&result, p, &now)); /* And check correct usage of dayshifts */ now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC+400 tomorrow"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); p = "UTC+400 +1 day"; ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); p = "UTC+400 1 day hence"; ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC+400 yesterday"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); p = "UTC+400 1 day ago"; ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC+400 now"; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); p = "UTC+400 +0 minutes"; /* silly, but simple "UTC+400" is different*/ ASSERT (parse_datetime (&result2, p, &now)); LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); /* Check that some "next Monday", "last Wednesday", etc. are correct. */ setenv ("TZ", "UTC0", 1); for (i = 0; day_table[i]; i++) { unsigned int thur2 = 7 * 24 * 3600; /* 2nd thursday */ char tmp[32]; sprintf (tmp, "NEXT %s", day_table[i]); now.tv_sec = thur2 + 4711; now.tv_nsec = 1267; ASSERT (parse_datetime (&result, tmp, &now)); LOG (tmp, now, result); ASSERT (result.tv_nsec == 0); ASSERT (result.tv_sec == thur2 + (i == 4 ? 7 : (i + 3) % 7) * 24 * 3600); sprintf (tmp, "LAST %s", day_table[i]); now.tv_sec = thur2 + 4711; now.tv_nsec = 1267; ASSERT (parse_datetime (&result, tmp, &now)); LOG (tmp, now, result); ASSERT (result.tv_nsec == 0); ASSERT (result.tv_sec == thur2 + ((i + 3) % 7 - 7) * 24 * 3600); } p = "THURSDAY UTC+00"; /* The epoch was on Thursday. */ now.tv_sec = 0; now.tv_nsec = 0; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); ASSERT (result.tv_sec == now.tv_sec && result.tv_nsec == now.tv_nsec); p = "FRIDAY UTC+00"; now.tv_sec = 0; now.tv_nsec = 0; ASSERT (parse_datetime (&result, p, &now)); LOG (p, now, result); ASSERT (result.tv_sec == 24 * 3600 && result.tv_nsec == now.tv_nsec); return 0; }
int main (int argc, char **argv) { List nflist; short file_flag = FALSE; short quit_flag = FALSE; int result; newts_failed_malloc_hook = curses_malloc_die; srand ((unsigned) time (NULL)); time (&orig_seqtime); time (&seqtime); #ifdef __GLIBC__ program_name = program_invocation_short_name; #else program_name = base_name (argv[0]); #endif /* Initialize i18n. */ #ifdef HAVE_SETLOCALE if (setlocale (LC_ALL, "") == NULL) { fprintf (stderr, _("%s: could not determine your locale\nCheck the " "environment variables LANG, LC_ALL, etc.\n"), program_name); exit (EXIT_FAILURE); } #endif #if ENABLE_NLS bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); #endif /* Initial setup and global variable init. */ init_blacklist (); list_init (&nflist, (void * (*) (void)) nfref_alloc, (void (*) (void *)) nfref_free, NULL); setup (); while (1) { int opt; short override_flag = FALSE; static struct option long_options[] = { {"alternate", required_argument, 0, 'a'}, {"black-threads", no_argument, 0, 'b'}, {"debug", no_argument, 0, 'D'}, {"seq-own-notes", no_argument, 0, 'e'}, {"file", required_argument, 0, 'f'}, {"no-signature", no_argument, 0, 'g'}, {"index", no_argument, 0, 'i'}, {"skip-own-notes", no_argument, 0, 'k'}, {"modern", no_argument, 0, 'm'}, {"no-sequencer", no_argument, 0, 'n'}, {"time", required_argument, 0, 'o'}, {"sequencer", no_argument, 0, 's'}, {"traditional", no_argument, 0, 't'}, {"user", required_argument, 0, 'u'}, {"white-basenotes", no_argument, 0, 'w'}, {"extended", no_argument, 0, 'x'}, {"imsa", no_argument, 0, 'y'}, {"no-blacklist", no_argument, 0, 'z'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 0}, {0, 0, 0, 0} }; opt = getopt_long (argc, argv, "a:bDef:ghikmno:stu:wxz", long_options, NULL); if (opt == -1) break; switch (opt) { case 0: { char *version_string; asprintf (&version_string, _("revision: %s"), newts_revision); printf (N_("notes - %s %s (%s)\n"), PACKAGE_NAME, VERSION, version_string); free (version_string); list_destroy (&nflist); teardown (); if (fclose (stdout) == EOF) error (EXIT_FAILURE, errno, _("error writing output")); exit (EXIT_SUCCESS); } case 'a': { alt_sequencer = TRUE; if (sequencer == NONE) sequencer = SEQUENCER; newts_nrealloc (seqname, strlen (username) + strlen (optarg) + 2, sizeof (char)); strcpy (seqname, username); strcat (seqname, ":"); strcat (seqname, optarg); if (alt_seqname) newts_free (alt_seqname); alt_seqname = newts_strdup (optarg); break; } case 'b': black_skip_seq = TRUE; break; case 'D': debug = TRUE; break; case 'f': if (parse_file (optarg, &nflist)) file_flag = TRUE; break; case 'g': signature = FALSE; break; case 'i': sequencer = INDEX; break; case 'k': seq_own_notes = FALSE; override_flag = TRUE; break; case 'm': seq_own_notes = TRUE; break; case 'n': sequencer = NONE; break; case 'o': { struct timespec parsed_time, now; now.tv_sec = orig_seqtime; if (parse_datetime (&parsed_time, optarg, &now)) { if (alt_time) { fprintf (stderr, _("%s: cannot specify multiple alternate times\n"), program_name); fprintf (stderr, _("See 'info newts' for more information.\n")); list_destroy (&nflist); teardown (); exit (EXIT_FAILURE); } else if (parsed_time.tv_sec <= orig_seqtime) { orig_seqtime = seqtime = parsed_time.tv_sec; if (sequencer == NONE) sequencer = SEQUENCER; alt_time = TRUE; } else { fprintf (stderr, _("%s: parsed time '%s' in the future\n"), program_name, optarg); fprintf (stderr, _("See 'info newts' for more information.\n")); list_destroy (&nflist); teardown (); exit (EXIT_FAILURE); } } else { fprintf (stderr, _("%s: error parsing time '%s'\n"), program_name, optarg); list_destroy (&nflist); teardown (); exit (EXIT_FAILURE); } break; } case 's': sequencer = SEQUENCER; break; case 't': case 'y': /* Pseudo-option for --imsa */ traditional = TRUE; if (!override_flag) seq_own_notes = TRUE; break; case 'u': { struct passwd *pw; if (getuid () != 0) { fprintf (stderr, _("%s: only root is allowed to use '--user'\n"), program_name); list_destroy (&nflist); teardown (); exit (EXIT_FAILURE); } pw = getpwnam (optarg); if (pw) { seteuid (pw->pw_uid); newts_free (username); username = newts_strdup (pw->pw_name); if (alt_sequencer) { newts_nrealloc (seqname, strlen (username) + strlen (alt_seqname) + 2, sizeof (char)); strcpy (seqname, username); strcat (seqname, ":"); strcat (seqname, alt_seqname); } else { newts_free (seqname); seqname = newts_strdup (username); } } else { fprintf (stderr, _("%s: no such user: '******'\n"), program_name, optarg); list_destroy (&nflist); teardown (); exit (EXIT_FAILURE); } } break; case 'w': white_basenotes = TRUE; break; case 'x': sequencer = EXTENDED; break; case 'z': no_blacklist = TRUE; break; case 'h': printf (_("Usage: %s [OPTION]... NOTESFILE...\n" "Run the UIUC-compatible notesfile client.\n\n"), program_name); printf (_("If an argument to a long option is mandatory, it is also mandatory " "for the\ncorresponding short option.\n\n")); printf (_("General options:\n" " -f, --file=FILE Read list of notesfiles to view from specified file\n" " -g, --no-signature Turn off automatic signature inclusion\n" " -h, --help Display this help and exit\n" " -u, --user=USER As root, run notes as the specified user\n" " --debug Print debugging messages to stderr\n" " --version Display version information and exit\n\n")); printf (_("Display options:\n" " -m, --modern Use modern, consistent display style (default)\n" " -t, --traditional Use traditional UIUC-style display\n" " --imsa Use IMSA-style display (same as -t)\n\n")); printf (_("Blacklist options:\n" " -b, --black-threads Skip threads with blacklisted basenotes while seqing\n" " -w, --white-basenotes Do not apply blacklist to basenotes\n" " -z, --no-blacklist Do not use the blacklist\n\n")); printf (_("Sequencer options:\n" " -a, --alternate=SEQ Use alternate sequencer SEQ\n" " -e, --seq-own-notes Make the sequencer view your notes\n" " -i, --index Use the index sequencer\n" " -k, --skip-own-notes Make the sequencer ignore your notes (default)\n" " -n, --no-sequencer Do not use the sequencer (default)\n" " -o, --time=TIME Use this date and time for the sequencer\n" " -s, --sequencer Use the sequencer to read notes\n" " -x, --extended Use the extended sequencer\n\n")); printf (_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); list_destroy (&nflist); teardown (); if (fclose (stdout) == EOF) error (EXIT_FAILURE, errno, _("error writing output")); exit (EXIT_SUCCESS); case '?': fprintf (stderr, _("Try '%s --help' for more information.\n"), program_name); list_destroy (&nflist); teardown (); exit (EXIT_FAILURE); } } if (optind == argc && !file_flag) { if (sequencer == NONE) { struct stat statbuf; fprintf (stderr, _("%s: too few arguments\n"), program_name); fprintf (stderr, _("Try '%s --help' for more information.\n"), program_name); /* FIXME: should be a call to the notes system. */ if (stat ("/etc/avail.notes", &statbuf) == 0) { fprintf (stderr, _("Hit <RET> for a list of notesfiles on this system.\n")); getchar (); spawn_process (NULL, pager, "/etc/avail.notes", NULL); } list_destroy (&nflist); teardown (); exit (EXIT_FAILURE); } else { char *copy, *list, *token, *nfseq; nfseq = getenv ("NFSEQ"); if (nfseq == NULL) { fprintf (stderr, _("%s: NFSEQ environment variable not set\n"), program_name); fprintf (stderr, _("See 'info newts' for more information.\n")); list_destroy (&nflist); teardown (); exit (EXIT_FAILURE); } copy = newts_strdup (nfseq); token = strtok_r (copy, ", ", &list); while (token != NULL) { parse_nf (token, &nflist); token = strtok_r (NULL, ", ", &list); } newts_free (copy); } } else { while (optind < argc) parse_nf (argv[optind++], &nflist); } handle_signals (); /* For each notesfile, start up the master routine and go. */ { ListNode *node = list_head (&nflist); while (node && !quit_flag) { newts_nfref *ref = (newts_nfref *) list_data (node); result = master (ref); node = list_next (node); if (result == QUITSEQ || result == QUITNOSEQ) quit_flag = TRUE; } } ignore_signals (); exit_curses (); if (*messages != '\0') printf ("%s", messages); teardown (); if (fclose (stdout) == EOF) error (EXIT_FAILURE, errno, _("error writing output")); exit (EXIT_SUCCESS); }
static gboolean prune_commits_keep_younger_than_date (OstreeRepo *repo, const char *date, GCancellable *cancellable, GError **error) { g_autoptr(GHashTable) refs = NULL; g_autoptr(GHashTable) ref_heads = g_hash_table_new (g_str_hash, g_str_equal); g_autoptr(GHashTable) objects = NULL; GHashTableIter hash_iter; gpointer key, value; struct timespec ts; gboolean ret = FALSE; if (!parse_datetime (&ts, date, NULL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Could not parse '%s'", date); goto out; } if (!ot_enable_tombstone_commits (repo, error)) goto out; if (!ostree_repo_list_refs (repo, NULL, &refs, cancellable, error)) goto out; /* We used to prune the HEAD of a given ref by default, but that's * broken for a few reasons. One is that people may use branches as * tags. Second is that if we do it, we should be deleting the ref * too, otherwise e.g. `summary -u` breaks trying to load it, etc. */ g_hash_table_iter_init (&hash_iter, refs); while (g_hash_table_iter_next (&hash_iter, &key, &value)) { /* Value is lifecycle bound to refs */ g_hash_table_add (ref_heads, (char*)value); } if (!ostree_repo_list_objects (repo, OSTREE_REPO_LIST_OBJECTS_ALL, &objects, cancellable, error)) goto out; g_hash_table_iter_init (&hash_iter, objects); while (g_hash_table_iter_next (&hash_iter, &key, &value)) { GVariant *serialized_key = key; const char *checksum; OstreeObjectType objtype; guint64 commit_timestamp; g_autoptr(GVariant) commit = NULL; ostree_object_name_deserialize (serialized_key, &checksum, &objtype); if (objtype != OSTREE_OBJECT_TYPE_COMMIT) continue; if (g_hash_table_contains (ref_heads, checksum)) continue; if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, checksum, &commit, error)) goto out; commit_timestamp = ostree_commit_get_timestamp (commit); if (commit_timestamp < ts.tv_sec) { if (opt_static_deltas_only) { if(!ostree_repo_prune_static_deltas (repo, checksum, cancellable, error)) goto out; } else { if (!ostree_repo_delete_object (repo, OSTREE_OBJECT_TYPE_COMMIT, checksum, cancellable, error)) goto out; } } } ret = TRUE; out: return ret; }
gboolean flatpak_builtin_build_commit_from (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; g_autoptr(GFile) dst_repofile = NULL; g_autoptr(OstreeRepo) dst_repo = NULL; g_autoptr(GFile) src_repofile = NULL; g_autoptr(OstreeRepo) src_repo = NULL; g_autofree char *src_repo_uri = NULL; const char *dst_repo_arg; const char **dst_refs; int n_dst_refs = 0; g_autoptr(FlatpakRepoTransaction) transaction = NULL; g_autoptr(GPtrArray) src_refs = NULL; g_autoptr(GPtrArray) resolved_src_refs = NULL; OstreeRepoCommitState src_commit_state; struct timespec ts; guint64 timestamp; int i; context = g_option_context_new (_("DST-REPO [DST-REF…] - Make a new commit from existing commits")); g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error)) return FALSE; if (argc < 2) return usage_error (context, _("DST-REPO must be specified"), error); dst_repo_arg = argv[1]; dst_refs = (const char **) argv + 2; n_dst_refs = argc - 2; if (opt_src_repo == NULL && n_dst_refs != 1) return usage_error (context, _("If --src-repo is not specified, exactly one destination ref must be specified"), error); if (opt_src_ref != NULL && n_dst_refs != 1) return usage_error (context, _("If --src-ref is specified, exactly one destination ref must be specified"), error); if (opt_src_repo == NULL && opt_src_ref == NULL) return flatpak_fail (error, _("Either --src-repo or --src-ref must be specified.")); /* Always create a commit if we're eol:ing, even though the app is the same */ if (opt_endoflife != NULL || opt_endoflife_rebase != NULL) opt_force = TRUE; if (opt_endoflife_rebase) { opt_endoflife_rebase_new = g_new0 (char *, g_strv_length (opt_endoflife_rebase)); for (i = 0; opt_endoflife_rebase[i] != NULL; i++) { char *rebase_old = opt_endoflife_rebase[i]; char *rebase_new = strchr (rebase_old, '='); if (rebase_new == NULL) { return usage_error (context, _("Invalid argument format of use --end-of-life-rebase=OLDID=NEWID"), error); } *rebase_new = 0; rebase_new++; if (!flatpak_is_valid_name (rebase_old, error)) return glnx_prefix_error (error, _("Invalid name %s in --end-of-life-rebase"), rebase_old); if (!flatpak_is_valid_name (rebase_new, error)) return glnx_prefix_error (error, _("Invalid name %s in --end-of-life-rebase"), rebase_new); opt_endoflife_rebase_new[i] = rebase_new; } } if (opt_timestamp) { if (!parse_datetime (&ts, opt_timestamp, NULL)) return flatpak_fail (error, _("Could not parse '%s'"), opt_timestamp); } dst_repofile = g_file_new_for_commandline_arg (dst_repo_arg); if (!g_file_query_exists (dst_repofile, cancellable)) return flatpak_fail (error, _("'%s' is not a valid repository"), dst_repo_arg); dst_repo = ostree_repo_new (dst_repofile); if (!ostree_repo_open (dst_repo, cancellable, error)) return FALSE; if (opt_disable_fsync) ostree_repo_set_disable_fsync (dst_repo, TRUE); if (opt_src_repo) { src_repofile = g_file_new_for_commandline_arg (opt_src_repo); if (!g_file_query_exists (src_repofile, cancellable)) return flatpak_fail (error, _("'%s' is not a valid repository"), opt_src_repo); src_repo_uri = g_file_get_uri (src_repofile); src_repo = ostree_repo_new (src_repofile); if (!ostree_repo_open (src_repo, cancellable, error)) return FALSE; } else { src_repo = g_object_ref (dst_repo); } src_refs = g_ptr_array_new_with_free_func (g_free); if (opt_src_ref) { g_assert (n_dst_refs == 1); g_ptr_array_add (src_refs, g_strdup (opt_src_ref)); } else { g_assert (opt_src_repo != NULL); if (n_dst_refs == 0) { g_autofree const char **keys = NULL; g_autoptr(GHashTable) all_src_refs = NULL; if (!ostree_repo_list_refs (src_repo, NULL, &all_src_refs, cancellable, error)) return FALSE; keys = (const char **) g_hash_table_get_keys_as_array (all_src_refs, NULL); for (i = 0; keys[i] != NULL; i++) { if (g_str_has_prefix (keys[i], "runtime/") || g_str_has_prefix (keys[i], "app/")) g_ptr_array_add (src_refs, g_strdup (keys[i])); } n_dst_refs = src_refs->len; dst_refs = (const char **) src_refs->pdata; } else { for (i = 0; i < n_dst_refs; i++) g_ptr_array_add (src_refs, g_strdup (dst_refs[i])); } } resolved_src_refs = g_ptr_array_new_with_free_func (g_free); for (i = 0; i < src_refs->len; i++) { const char *src_ref = g_ptr_array_index (src_refs, i); char *resolved_ref; if (!ostree_repo_resolve_rev (src_repo, src_ref, FALSE, &resolved_ref, error)) return FALSE; g_ptr_array_add (resolved_src_refs, resolved_ref); } if (src_repo_uri != NULL) { OstreeRepoPullFlags pullflags = 0; GVariantBuilder builder; g_autoptr(OstreeAsyncProgress) progress = NULL; g_auto(GLnxConsoleRef) console = { 0, }; g_autoptr(GVariant) options = NULL; gboolean res; if (opt_untrusted) pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED; glnx_console_lock (&console); if (console.is_tty) progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console); g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&builder, "{s@v}", "flags", g_variant_new_variant (g_variant_new_int32 (pullflags))); g_variant_builder_add (&builder, "{s@v}", "refs", g_variant_new_variant (g_variant_new_strv ((const char * const *) resolved_src_refs->pdata, resolved_src_refs->len))); g_variant_builder_add (&builder, "{s@v}", "depth", g_variant_new_variant (g_variant_new_int32 (0))); options = g_variant_ref_sink (g_variant_builder_end (&builder)); res = ostree_repo_pull_with_options (dst_repo, src_repo_uri, options, progress, cancellable, error); if (progress) ostree_async_progress_finish (progress); if (!res) return FALSE; } /* By now we have the commit with commit_id==resolved_ref and dependencies in dst_repo. We now create a new * commit based on the toplevel tree ref from that commit. * This is equivalent to: * ostree commit --skip-if-unchanged --repo=${destrepo} --tree=ref=${resolved_ref} */ transaction = flatpak_repo_transaction_start (dst_repo, cancellable, error); if (transaction == NULL) return FALSE; for (i = 0; i < resolved_src_refs->len; i++) { const char *dst_ref = dst_refs[i]; const char *resolved_ref = g_ptr_array_index (resolved_src_refs, i); g_autofree char *dst_parent = NULL; g_autoptr(GFile) dst_parent_root = NULL; g_autoptr(GFile) src_ref_root = NULL; g_autoptr(GVariant) src_commitv = NULL; g_autoptr(GVariant) dst_commitv = NULL; g_autoptr(OstreeMutableTree) mtree = NULL; g_autoptr(GFile) dst_root = NULL; g_autoptr(GVariant) commitv_metadata = NULL; g_autoptr(GVariant) metadata = NULL; const char *subject; const char *body; g_autofree char *commit_checksum = NULL; GVariantBuilder metadata_builder; gint j; const char *dst_collection_id = NULL; const char *main_collection_id = NULL; g_autoptr(GPtrArray) collection_ids = NULL; if (!ostree_repo_resolve_rev (dst_repo, dst_ref, TRUE, &dst_parent, error)) return FALSE; if (dst_parent != NULL && !ostree_repo_read_commit (dst_repo, dst_parent, &dst_parent_root, NULL, cancellable, error)) return FALSE; if (!ostree_repo_read_commit (dst_repo, resolved_ref, &src_ref_root, NULL, cancellable, error)) return FALSE; if (!ostree_repo_load_commit (dst_repo, resolved_ref, &src_commitv, &src_commit_state, error)) return FALSE; if (src_commit_state & OSTREE_REPO_COMMIT_STATE_PARTIAL) return flatpak_fail (error, _("Can't commit from partial source commit.")); /* Don't create a new commit if this is the same tree */ if (!opt_force && dst_parent_root != NULL && g_file_equal (dst_parent_root, src_ref_root)) { g_print (_("%s: no change\n"), dst_ref); continue; } mtree = ostree_mutable_tree_new (); if (!ostree_repo_write_directory_to_mtree (dst_repo, src_ref_root, mtree, NULL, cancellable, error)) return FALSE; if (!ostree_repo_write_mtree (dst_repo, mtree, &dst_root, cancellable, error)) return FALSE; commitv_metadata = g_variant_get_child_value (src_commitv, 0); g_variant_get_child (src_commitv, 3, "&s", &subject); if (opt_subject) subject = (const char *) opt_subject; g_variant_get_child (src_commitv, 4, "&s", &body); if (opt_body) body = (const char *) opt_body; dst_collection_id = ostree_repo_get_collection_id (dst_repo); collection_ids = g_ptr_array_new_with_free_func (g_free); if (dst_collection_id) { main_collection_id = dst_collection_id; g_ptr_array_add (collection_ids, g_strdup (dst_collection_id)); } if (opt_extra_collection_ids != NULL) { for (j = 0; opt_extra_collection_ids[j] != NULL; j++) { const char *cid = opt_extra_collection_ids[j]; if (main_collection_id == NULL) main_collection_id = cid; /* Fall back to first arg */ if (g_strcmp0 (cid, dst_collection_id) != 0) g_ptr_array_add (collection_ids, g_strdup (cid)); } } g_ptr_array_sort (collection_ids, (GCompareFunc) flatpak_strcmp0_ptr); /* Copy old metadata */ g_variant_builder_init (&metadata_builder, G_VARIANT_TYPE ("a{sv}")); /* Bindings. xa.ref is deprecated but added anyway for backwards compatibility. */ g_variant_builder_add (&metadata_builder, "{sv}", "ostree.collection-binding", g_variant_new_string (main_collection_id ? main_collection_id : "")); if (collection_ids->len > 0) { g_autoptr(GVariantBuilder) cr_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(ss)")); for (j = 0; j < collection_ids->len; j++) g_variant_builder_add (cr_builder, "(ss)", g_ptr_array_index (collection_ids, j), dst_ref); g_variant_builder_add (&metadata_builder, "{sv}", "ostree.collection-refs-binding", g_variant_builder_end (cr_builder)); } g_variant_builder_add (&metadata_builder, "{sv}", "ostree.ref-binding", g_variant_new_strv (&dst_ref, 1)); g_variant_builder_add (&metadata_builder, "{sv}", "xa.ref", g_variant_new_string (dst_ref)); /* Record the source commit. This is nice to have, but it also means the commit-from gets a different commit id, which avoids problems with e.g. sharing .commitmeta files (signatures) */ g_variant_builder_add (&metadata_builder, "{sv}", "xa.from_commit", g_variant_new_string (resolved_ref)); for (j = 0; j < g_variant_n_children (commitv_metadata); j++) { g_autoptr(GVariant) child = g_variant_get_child_value (commitv_metadata, j); g_autoptr(GVariant) keyv = g_variant_get_child_value (child, 0); const char *key = g_variant_get_string (keyv, NULL); if (strcmp (key, "xa.ref") == 0 || strcmp (key, "xa.from_commit") == 0 || strcmp (key, "ostree.collection-binding") == 0 || strcmp (key, "ostree.collection-refs-binding") == 0 || strcmp (key, "ostree.ref-binding") == 0) continue; if (opt_endoflife && strcmp (key, OSTREE_COMMIT_META_KEY_ENDOFLIFE) == 0) continue; if (opt_endoflife_rebase && strcmp (key, OSTREE_COMMIT_META_KEY_ENDOFLIFE_REBASE) == 0) continue; g_variant_builder_add_value (&metadata_builder, child); } if (opt_endoflife && *opt_endoflife) g_variant_builder_add (&metadata_builder, "{sv}", OSTREE_COMMIT_META_KEY_ENDOFLIFE, g_variant_new_string (opt_endoflife)); if (opt_endoflife_rebase) { g_auto(GStrv) dst_ref_parts = g_strsplit (dst_ref, "/", 0); for (j = 0; opt_endoflife_rebase[j] != NULL; j++) { const char *old_prefix = opt_endoflife_rebase[j]; if (flatpak_has_name_prefix (dst_ref_parts[1], old_prefix)) { g_autofree char *new_id = g_strconcat (opt_endoflife_rebase_new[j], dst_ref_parts[1] + strlen(old_prefix), NULL); g_autofree char *rebased_ref = g_build_filename (dst_ref_parts[0], new_id, dst_ref_parts[2], dst_ref_parts[3], NULL); g_variant_builder_add (&metadata_builder, "{sv}", OSTREE_COMMIT_META_KEY_ENDOFLIFE_REBASE, g_variant_new_string (rebased_ref)); break; } } } timestamp = ostree_commit_get_timestamp (src_commitv); if (opt_timestamp) timestamp = ts.tv_sec; metadata = g_variant_ref_sink (g_variant_builder_end (&metadata_builder)); if (!ostree_repo_write_commit_with_time (dst_repo, dst_parent, subject, body, metadata, OSTREE_REPO_FILE (dst_root), timestamp, &commit_checksum, cancellable, error)) return FALSE; g_print ("%s: %s\n", dst_ref, commit_checksum); if (!ostree_repo_load_commit (dst_repo, commit_checksum, &dst_commitv, NULL, error)) return FALSE; /* This doesn't copy the detached metadata. I'm not sure if this is a problem. * The main thing there is commit signatures, and we can't copy those, as the commit hash changes. */ if (opt_gpg_key_ids) { char **iter; for (iter = opt_gpg_key_ids; iter && *iter; iter++) { const char *keyid = *iter; g_autoptr(GError) my_error = NULL; if (!ostree_repo_sign_commit (dst_repo, commit_checksum, keyid, opt_gpg_homedir, cancellable, &my_error) && !g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS)) { g_propagate_error (error, g_steal_pointer (&my_error)); return FALSE; } } } if (dst_collection_id != NULL) { OstreeCollectionRef ref = { (char *) dst_collection_id, (char *) dst_ref }; ostree_repo_transaction_set_collection_ref (dst_repo, &ref, commit_checksum); } else { ostree_repo_transaction_set_ref (dst_repo, NULL, dst_ref, commit_checksum); } if (opt_extra_collection_ids) { for (j = 0; opt_extra_collection_ids[j] != NULL; j++) { OstreeCollectionRef ref = { (char *) opt_extra_collection_ids[j], (char *) dst_ref }; ostree_repo_transaction_set_collection_ref (dst_repo, &ref, commit_checksum); } } /* Copy + Rewrite any deltas */ { const char *from[2]; gsize j, n_from = 0; if (dst_parent != NULL) from[n_from++] = dst_parent; from[n_from++] = NULL; for (j = 0; j < n_from; j++) { g_autoptr(GError) local_error = NULL; if (!rewrite_delta (src_repo, resolved_ref, dst_repo, commit_checksum, dst_commitv, from[j], &local_error)) g_debug ("Failed to copy delta: %s", local_error->message); } } } if (!ostree_repo_commit_transaction (dst_repo, NULL, cancellable, error)) return FALSE; if (opt_update_appstream && !flatpak_repo_generate_appstream (dst_repo, (const char **) opt_gpg_key_ids, opt_gpg_homedir, 0, cancellable, error)) return FALSE; if (!opt_no_update_summary && !flatpak_repo_update (dst_repo, (const char **) opt_gpg_key_ids, opt_gpg_homedir, cancellable, error)) return FALSE; return TRUE; }
bool hp98035_io_card::parse_unit_command(const uint8_t*& p, unsigned unit_no) { unit_no--; timer_unit_t& unit = m_units[ unit_no ]; bool get_out = false; unsigned msec; uint8_t to_match[ 5 ]; std::ostringstream out; LOG(("U %c %u %p\n" , *p , unit_no , &unit)); switch (*p++) { case '=': // Assign unit if (*p == 'I') { p++; get_out = assign_unit(unit , p , true); } else if (*p == 'O') { p++; get_out = assign_unit(unit , p , false); } break; case 'C': // Clear input unit if (unit.m_input && unit.m_port) { unit.m_value = 0; } else { set_error(ERR_MASK_WRONG_UNIT); } break; case 'D': // Set delay on output unit if (parse_msec(p , msec)) { if (!unit.m_input && unit.m_port) { if (unit.m_state == UNIT_IDLE) { unit.m_delay = msec; } else { set_error(ERR_MASK_CANT_EXEC); } } else { set_error(ERR_MASK_WRONG_UNIT); } } else { set_error(ERR_MASK_WRONG_INS); } get_out = true; break; case 'G': // Activate unit if (unit.m_port && unit.m_state == UNIT_IDLE) { unit.adv_state(true); LOG(("act %p %d %d %u %02u:%02u:%02u:%02u %u %u %u\n" , &unit , unit.m_state , unit.m_input , unit.m_port , unit.m_match_datetime[ 0 ] , unit.m_match_datetime[ 1 ] , unit.m_match_datetime[ 2 ] , unit.m_match_datetime[ 3 ] , unit.m_delay , unit.m_period , unit.m_value)); } else { set_error(ERR_MASK_WRONG_UNIT); } break; case 'H': // Halt unit if (unit.m_port) { unit.deactivate(); } else { set_error(ERR_MASK_WRONG_UNIT); } break; case 'M': // Set date/time to match on output unit if (!unit.m_input && unit.m_port) { if (unit.m_state == UNIT_IDLE) { if (*p == '\0') { unit.m_match_datetime[ 0 ] = EMPTY_FIELD; unit.m_match_datetime[ 1 ] = EMPTY_FIELD; unit.m_match_datetime[ 2 ] = EMPTY_FIELD; unit.m_match_datetime[ 3 ] = EMPTY_FIELD; } else if (parse_datetime(p , to_match) && *p == '\0') { unit.m_match_datetime[ 0 ] = to_match[ 1 ]; unit.m_match_datetime[ 1 ] = to_match[ 2 ]; unit.m_match_datetime[ 2 ] = to_match[ 3 ]; unit.m_match_datetime[ 3 ] = to_match[ 4 ]; } else { set_error(ERR_MASK_WRONG_INS); } } else { set_error(ERR_MASK_CANT_EXEC); } } else { set_error(ERR_MASK_WRONG_UNIT); } get_out = true; break; case 'P': // Set period on output unit if (parse_msec(p , msec)) { if (!unit.m_input && unit.m_port) { if (unit.m_state == UNIT_IDLE) { unit.m_period = msec; } else { set_error(ERR_MASK_CANT_EXEC); } } else { set_error(ERR_MASK_WRONG_UNIT); } } else { set_error(ERR_MASK_WRONG_INS); } get_out = true; break; case 'V': // Get value of input unit if (unit.m_input && unit.m_port) { util::stream_format(out , "%010u" , unit.m_value); set_obuffer(out.str().c_str()); } else { set_error(ERR_MASK_WRONG_UNIT); } break; } return get_out; }
void hp98035_io_card::process_ibuffer(void) { m_ibuffer[ m_ibuffer_ptr ] = '\0'; const uint8_t *p = &m_ibuffer[ 0 ]; clear_obuffer(); bool get_out = false; while (*p != '\0' && !get_out) { std::ostringstream out; uint8_t datetime[ 5 ]; unsigned unit_no; switch (*p++) { case 'A': // Halt all timer units for (timer_unit_t& unit : m_units) { unit.deactivate(); } m_inten = false; m_intflag = false; update_irq(); break; case 'B': // Warm reset half_init(); get_out = true; break; case 'E': // Read and clear errors set_obuffer(m_error); m_error = 0; break; case 'F': // Activate all timer units for (timer_unit_t& unit : m_units) { if (unit.m_port) { unit.adv_state(true); } } break; case 'R': // Read time // Assume US format of dates util::stream_format(out , "%02u:%02u:%02u:%02u:%02u" , m_mon , m_dom , m_hrs , m_min , m_sec); set_obuffer(out.str().c_str()); break; case 'S': // Set time if (parse_datetime(p , datetime)) { // Cannot set time when there's one or more active output units if (std::any_of(std::begin(m_units) , std::end(m_units) , [](const timer_unit_t& u) { return u.m_state != UNIT_IDLE && !u.m_input; })) { set_error(ERR_MASK_CANT_EXEC); } else { m_msec = 0; m_sec = datetime[ 4 ]; if (datetime[ 3 ] != EMPTY_FIELD) { m_min = datetime[ 3 ]; if (datetime[ 2 ] != EMPTY_FIELD) { m_hrs = datetime[ 2 ]; if (datetime[ 1 ] != EMPTY_FIELD) { m_dom = datetime[ 1 ]; if (datetime[ 0 ] != EMPTY_FIELD) { m_mon = datetime[ 0 ]; } } } } } } else { set_error(ERR_MASK_WRONG_INS); get_out = true; } break; case 'T': // Read triggered outputs set_obuffer(m_triggered); m_triggered = 0; break; case 'U': // Control timer units if (parse_unit_no(p , unit_no)) { get_out = parse_unit_command(p , unit_no); } else { set_error(ERR_MASK_WRONG_INS); get_out = true; } break; case 'W': // Read unserviced interrupts set_obuffer(m_lost_irq); m_lost_irq = 0; break; default: set_error(ERR_MASK_WRONG_INS); get_out = true; break; } } m_ibuffer_ptr = 0; }
/* remove header; add '*'s; replace "Revision REV" with "rREV" */ static char *prepare_pld_changelog(tn_alloc *na, const char *changelog) { struct changelog_ent *ent = NULL; char *entmark = "Revision", *prepared_log; int i, started, max_MESSAGE = 1024, len; tn_array *entries, *lines; tn_buf *logmsg; lines = n_str_etokl_ext(changelog, "\n", "", "", '\\'); len = strlen(entmark); entries = n_array_new(8, NULL, (tn_fn_cmp)changelog_ent_cmp); logmsg = n_buf_new(1024); started = 0; for (i = 0; i < n_array_size(lines); i++) { char *line = n_array_nth(lines, i); if (strncmp(line, entmark, len) == 0) started = 1; if (!started) continue; if (strncmp(line, entmark, len) == 0) { char *tstr, *rev, info[80]; time_t ts; int n; if (ent != NULL) { n_snprintf(ent->message, max_MESSAGE, "%s", n_buf_ptr(logmsg)); n_buf_clean(logmsg); n_array_push(entries, ent); ent = NULL; } //Revision REV YYYY-MM-DD HH:MM:SS rest rev = line + len + 1; /* skip Revision */ while (*rev && isspace(*rev)) rev++; tstr = strchr(rev, ' '); if (tstr) { *tstr = '\0'; tstr++; while (*tstr && isspace(*tstr)) tstr++; } if (rev && tstr) { ts = parse_datetime(tstr); if (ts == 0) continue; } n = n_snprintf(info, sizeof(info), "* r%s %s", rev, tstr); ent = n_malloc(sizeof(*ent) + max_MESSAGE); memset(ent, 0, sizeof(*ent)); ent->info = n_strdupl(info, n); ent->message[0] = '\0'; continue; } if (ent) n_buf_printf(logmsg, "%s\n", line); } if (ent != NULL) { n_snprintf(ent->message, max_MESSAGE, "%s", n_buf_ptr(logmsg)); n_array_push(entries, ent); } n_array_free(lines); n_buf_clean(logmsg); /* shift && free entries cause ents are simply malloc()ed here */ while (n_array_size(entries)) { ent = n_array_shift(entries); n_buf_printf(logmsg, "%s\n", ent->info); n_buf_printf(logmsg, "%s\n", ent->message); } n_array_free(entries); prepared_log = na_strdup(na, n_buf_ptr(logmsg), n_buf_size(logmsg)); n_buf_free(logmsg); return prepared_log; }
static gboolean prune_commits_keep_younger_than_date (OstreeRepo *repo, const char *date, GCancellable *cancellable, GError **error) { g_autoptr(GHashTable) objects = NULL; GHashTableIter hash_iter; gpointer key, value; struct timespec ts; gboolean ret = FALSE; if (!parse_datetime (&ts, date, NULL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Could not parse '%s'", date); goto out; } if (!ot_enable_tombstone_commits (repo, error)) goto out; if (!ostree_repo_list_objects (repo, OSTREE_REPO_LIST_OBJECTS_ALL, &objects, cancellable, error)) goto out; g_hash_table_iter_init (&hash_iter, objects); while (g_hash_table_iter_next (&hash_iter, &key, &value)) { GVariant *serialized_key = key; const char *checksum; OstreeObjectType objtype; guint64 commit_timestamp; g_autoptr(GVariant) commit = NULL; ostree_object_name_deserialize (serialized_key, &checksum, &objtype); if (objtype != OSTREE_OBJECT_TYPE_COMMIT) continue; if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, checksum, &commit, error)) goto out; commit_timestamp = ostree_commit_get_timestamp (commit); if (commit_timestamp < ts.tv_sec) { if (opt_static_deltas_only) { if(!ostree_repo_prune_static_deltas (repo, checksum, cancellable, error)) goto out; } else { if (!ostree_repo_delete_object (repo, OSTREE_OBJECT_TYPE_COMMIT, checksum, cancellable, error)) goto out; } } } ret = TRUE; out: return ret; }