From aa32a5f58bf4c11142d018ce57478f847a74ac5e Mon Sep 17 00:00:00 2001 From: Sahil Dua Date: Sun, 26 Jun 2016 05:14:45 +0530 Subject: [PATCH 1/3] Replace samples for C language --- samples/C/array.c | 45 +++ samples/C/array.h | 58 +++ samples/C/cache.c | 99 ------ samples/C/cpu.c | 725 ------------------------------------- samples/C/diff.c | 784 ----------------------------------------- samples/C/fudge_node.c | 188 ++++++++++ samples/C/hash.c | 74 ---- 7 files changed, 291 insertions(+), 1682 deletions(-) create mode 100644 samples/C/array.c create mode 100644 samples/C/array.h delete mode 100644 samples/C/cache.c delete mode 100644 samples/C/cpu.c delete mode 100644 samples/C/diff.c create mode 100644 samples/C/fudge_node.c delete mode 100644 samples/C/hash.c diff --git a/samples/C/array.c b/samples/C/array.c new file mode 100644 index 00000000..924b9ffd --- /dev/null +++ b/samples/C/array.c @@ -0,0 +1,45 @@ +#include + +unsigned __bump_up(unsigned n) { + unsigned base = 1; + --n; + while (base < sizeof n * 8) { + n |= n >> base; + base *= 2; + } + ++n; + n += (n == 0); + return n; +} + +void *__array_alloc(size_t size, unsigned length) { + unsigned allocated = __bump_up(length); + struct __array_header *head = malloc(sizeof *head + allocated * size); + assert(head); + head->length = length; + head->allocated = allocated; + return (void *) (head + 1); +} + +void __array_resize(void **array, size_t size, int difference) { + if (difference == 0) { + return; + } + struct __array_header *head = __header(*array); + head->length += difference; + if (head->length >= head->allocated) { + head->allocated = __bump_up(head->length); + head = realloc(head, sizeof *head + head->allocated * size); + assert(head); + *array = head + 1; + } +} + +int __array_search(void *array, void *elem, size_t size) { + for (unsigned i = 0; i < alength(array) * size; i += size) { + if (memcmp((char *)array + i, elem, size) == 0) { + return 1; + } + } + return 0; +} diff --git a/samples/C/array.h b/samples/C/array.h new file mode 100644 index 00000000..22ad72dc --- /dev/null +++ b/samples/C/array.h @@ -0,0 +1,58 @@ +#ifndef ARRAY_H +#define ARRAY_H value + +#include +#include +#include + +#define array(type, name, initial_length) \ + type *name = __array_alloc(sizeof(type), initial_length) + +#define aforeach(it, array) \ + for (unsigned it = 0; \ + it < alength(array); \ + ++it) + +#define __header(array) \ + ((struct __array_header *) array - 1) + +#define alength(array) \ + (__header(array)->length) + +#define afree(array) \ + free(__header(array)) + +#define apush(array, elem) \ + __array_resize((void **) &array, sizeof *array, 1); \ + array[alength(array)-1] = elem + +#define apop(array) \ + aremove(array, (alength(array) - 1)) + +#define aremove(array, index) \ + assert(alength(array) > index); \ + memmove(array + index, array + index + 1, sizeof *array * (alength(array) - index - 1)); \ + __array_resize((void **) &array, sizeof *array, -1) + +#define ainsert(array, index, elem) \ + __array_resize((void **) &array, sizeof *array, index >= alength(array) ? index - alength(array) + 1 : 1); \ + memmove(array + index + 1, array + index, sizeof *array * (alength(array) - index - 1)); \ + array[index] = elem + +#define acontains(array, elem) \ + __array_search(array, &elem, sizeof elem) + +#define __arrayallocated(array) \ + (__header(array)->allocated) + +struct __array_header { + unsigned length; + unsigned allocated; +}; + +unsigned __bump_up(unsigned n); +void *__array_alloc(size_t size, unsigned length); +void __array_resize(void **array, size_t size, int difference); +int __array_search(void *array, void *elem, size_t size); + +#endif /* ifndef ARRAY_H */ diff --git a/samples/C/cache.c b/samples/C/cache.c deleted file mode 100644 index f8d89403..00000000 --- a/samples/C/cache.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2009-2012 the libgit2 contributors - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#include "common.h" -#include "repository.h" -#include "commit.h" -#include "thread-utils.h" -#include "util.h" -#include "cache.h" - -int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr) -{ - if (size < 8) - size = 8; - size = git__size_t_powerof2(size); - - cache->size_mask = size - 1; - cache->lru_count = 0; - cache->free_obj = free_ptr; - - git_mutex_init(&cache->lock); - - cache->nodes = git__malloc(size * sizeof(git_cached_obj *)); - GITERR_CHECK_ALLOC(cache->nodes); - - memset(cache->nodes, 0x0, size * sizeof(git_cached_obj *)); - return 0; -} - -void git_cache_free(git_cache *cache) -{ - size_t i; - - for (i = 0; i < (cache->size_mask + 1); ++i) { - if (cache->nodes[i] != NULL) - git_cached_obj_decref(cache->nodes[i], cache->free_obj); - } - - git__free(cache->nodes); -} - -void *git_cache_get(git_cache *cache, const git_oid *oid) -{ - uint32_t hash; - git_cached_obj *node = NULL, *result = NULL; - - memcpy(&hash, oid->id, sizeof(hash)); - - git_mutex_lock(&cache->lock); - { - node = cache->nodes[hash & cache->size_mask]; - - if (node != NULL && git_oid_cmp(&node->oid, oid) == 0) { - git_cached_obj_incref(node); - result = node; - } - } - git_mutex_unlock(&cache->lock); - - return result; -} - -void *git_cache_try_store(git_cache *cache, void *_entry) -{ - git_cached_obj *entry = _entry; - uint32_t hash; - - memcpy(&hash, &entry->oid, sizeof(uint32_t)); - - /* increase the refcount on this object, because - * the cache now owns it */ - git_cached_obj_incref(entry); - - git_mutex_lock(&cache->lock); - { - git_cached_obj *node = cache->nodes[hash & cache->size_mask]; - - if (node == NULL) { - cache->nodes[hash & cache->size_mask] = entry; - } else if (git_oid_cmp(&node->oid, &entry->oid) == 0) { - git_cached_obj_decref(entry, cache->free_obj); - entry = node; - } else { - git_cached_obj_decref(node, cache->free_obj); - cache->nodes[hash & cache->size_mask] = entry; - } - } - git_mutex_unlock(&cache->lock); - - /* increase the refcount again, because we are - * returning it to the user */ - git_cached_obj_incref(entry); - - return entry; -} diff --git a/samples/C/cpu.c b/samples/C/cpu.c deleted file mode 100644 index a4eb5227..00000000 --- a/samples/C/cpu.c +++ /dev/null @@ -1,725 +0,0 @@ -/* CPU control. - * (C) 2001, 2002, 2003, 2004 Rusty Russell - * - * This code is licenced under the GPL. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "smpboot.h" - -#ifdef CONFIG_SMP -/* Serializes the updates to cpu_online_mask, cpu_present_mask */ -static DEFINE_MUTEX(cpu_add_remove_lock); - -/* - * The following two API's must be used when attempting - * to serialize the updates to cpu_online_mask, cpu_present_mask. - */ -void cpu_maps_update_begin(void) -{ - mutex_lock(&cpu_add_remove_lock); -} - -void cpu_maps_update_done(void) -{ - mutex_unlock(&cpu_add_remove_lock); -} - -static RAW_NOTIFIER_HEAD(cpu_chain); - -/* If set, cpu_up and cpu_down will return -EBUSY and do nothing. - * Should always be manipulated under cpu_add_remove_lock - */ -static int cpu_hotplug_disabled; - -#ifdef CONFIG_HOTPLUG_CPU - -static struct { - struct task_struct *active_writer; - struct mutex lock; /* Synchronizes accesses to refcount, */ - /* - * Also blocks the new readers during - * an ongoing cpu hotplug operation. - */ - int refcount; -} cpu_hotplug = { - .active_writer = NULL, - .lock = __MUTEX_INITIALIZER(cpu_hotplug.lock), - .refcount = 0, -}; - -void get_online_cpus(void) -{ - might_sleep(); - if (cpu_hotplug.active_writer == current) - return; - mutex_lock(&cpu_hotplug.lock); - cpu_hotplug.refcount++; - mutex_unlock(&cpu_hotplug.lock); - -} -EXPORT_SYMBOL_GPL(get_online_cpus); - -void put_online_cpus(void) -{ - if (cpu_hotplug.active_writer == current) - return; - mutex_lock(&cpu_hotplug.lock); - if (!--cpu_hotplug.refcount && unlikely(cpu_hotplug.active_writer)) - wake_up_process(cpu_hotplug.active_writer); - mutex_unlock(&cpu_hotplug.lock); - -} -EXPORT_SYMBOL_GPL(put_online_cpus); - -/* - * This ensures that the hotplug operation can begin only when the - * refcount goes to zero. - * - * Note that during a cpu-hotplug operation, the new readers, if any, - * will be blocked by the cpu_hotplug.lock - * - * Since cpu_hotplug_begin() is always called after invoking - * cpu_maps_update_begin(), we can be sure that only one writer is active. - * - * Note that theoretically, there is a possibility of a livelock: - * - Refcount goes to zero, last reader wakes up the sleeping - * writer. - * - Last reader unlocks the cpu_hotplug.lock. - * - A new reader arrives at this moment, bumps up the refcount. - * - The writer acquires the cpu_hotplug.lock finds the refcount - * non zero and goes to sleep again. - * - * However, this is very difficult to achieve in practice since - * get_online_cpus() not an api which is called all that often. - * - */ -static void cpu_hotplug_begin(void) -{ - cpu_hotplug.active_writer = current; - - for (;;) { - mutex_lock(&cpu_hotplug.lock); - if (likely(!cpu_hotplug.refcount)) - break; - __set_current_state(TASK_UNINTERRUPTIBLE); - mutex_unlock(&cpu_hotplug.lock); - schedule(); - } -} - -static void cpu_hotplug_done(void) -{ - cpu_hotplug.active_writer = NULL; - mutex_unlock(&cpu_hotplug.lock); -} - -#else /* #if CONFIG_HOTPLUG_CPU */ -static void cpu_hotplug_begin(void) {} -static void cpu_hotplug_done(void) {} -#endif /* #else #if CONFIG_HOTPLUG_CPU */ - -/* Need to know about CPUs going up/down? */ -int __ref register_cpu_notifier(struct notifier_block *nb) -{ - int ret; - cpu_maps_update_begin(); - ret = raw_notifier_chain_register(&cpu_chain, nb); - cpu_maps_update_done(); - return ret; -} - -static int __cpu_notify(unsigned long val, void *v, int nr_to_call, - int *nr_calls) -{ - int ret; - - ret = __raw_notifier_call_chain(&cpu_chain, val, v, nr_to_call, - nr_calls); - - return notifier_to_errno(ret); -} - -static int cpu_notify(unsigned long val, void *v) -{ - return __cpu_notify(val, v, -1, NULL); -} - -#ifdef CONFIG_HOTPLUG_CPU - -static void cpu_notify_nofail(unsigned long val, void *v) -{ - BUG_ON(cpu_notify(val, v)); -} -EXPORT_SYMBOL(register_cpu_notifier); - -void __ref unregister_cpu_notifier(struct notifier_block *nb) -{ - cpu_maps_update_begin(); - raw_notifier_chain_unregister(&cpu_chain, nb); - cpu_maps_update_done(); -} -EXPORT_SYMBOL(unregister_cpu_notifier); - -/** - * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU - * @cpu: a CPU id - * - * This function walks all processes, finds a valid mm struct for each one and - * then clears a corresponding bit in mm's cpumask. While this all sounds - * trivial, there are various non-obvious corner cases, which this function - * tries to solve in a safe manner. - * - * Also note that the function uses a somewhat relaxed locking scheme, so it may - * be called only for an already offlined CPU. - */ -void clear_tasks_mm_cpumask(int cpu) -{ - struct task_struct *p; - - /* - * This function is called after the cpu is taken down and marked - * offline, so its not like new tasks will ever get this cpu set in - * their mm mask. -- Peter Zijlstra - * Thus, we may use rcu_read_lock() here, instead of grabbing - * full-fledged tasklist_lock. - */ - WARN_ON(cpu_online(cpu)); - rcu_read_lock(); - for_each_process(p) { - struct task_struct *t; - - /* - * Main thread might exit, but other threads may still have - * a valid mm. Find one. - */ - t = find_lock_task_mm(p); - if (!t) - continue; - cpumask_clear_cpu(cpu, mm_cpumask(t->mm)); - task_unlock(t); - } - rcu_read_unlock(); -} - -static inline void check_for_tasks(int cpu) -{ - struct task_struct *p; - - write_lock_irq(&tasklist_lock); - for_each_process(p) { - if (task_cpu(p) == cpu && p->state == TASK_RUNNING && - (p->utime || p->stime)) - printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d " - "(state = %ld, flags = %x)\n", - p->comm, task_pid_nr(p), cpu, - p->state, p->flags); - } - write_unlock_irq(&tasklist_lock); -} - -struct take_cpu_down_param { - unsigned long mod; - void *hcpu; -}; - -/* Take this CPU down. */ -static int __ref take_cpu_down(void *_param) -{ - struct take_cpu_down_param *param = _param; - int err; - - /* Ensure this CPU doesn't handle any more interrupts. */ - err = __cpu_disable(); - if (err < 0) - return err; - - cpu_notify(CPU_DYING | param->mod, param->hcpu); - return 0; -} - -/* Requires cpu_add_remove_lock to be held */ -static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) -{ - int err, nr_calls = 0; - void *hcpu = (void *)(long)cpu; - unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; - struct take_cpu_down_param tcd_param = { - .mod = mod, - .hcpu = hcpu, - }; - - if (num_online_cpus() == 1) - return -EBUSY; - - if (!cpu_online(cpu)) - return -EINVAL; - - cpu_hotplug_begin(); - - err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls); - if (err) { - nr_calls--; - __cpu_notify(CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL); - printk("%s: attempt to take down CPU %u failed\n", - __func__, cpu); - goto out_release; - } - - err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); - if (err) { - /* CPU didn't die: tell everyone. Can't complain. */ - cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu); - - goto out_release; - } - BUG_ON(cpu_online(cpu)); - - /* - * The migration_call() CPU_DYING callback will have removed all - * runnable tasks from the cpu, there's only the idle task left now - * that the migration thread is done doing the stop_machine thing. - * - * Wait for the stop thread to go away. - */ - while (!idle_cpu(cpu)) - cpu_relax(); - - /* This actually kills the CPU. */ - __cpu_die(cpu); - - /* CPU is completely dead: tell everyone. Too late to complain. */ - cpu_notify_nofail(CPU_DEAD | mod, hcpu); - - check_for_tasks(cpu); - -out_release: - cpu_hotplug_done(); - if (!err) - cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu); - return err; -} - -int __ref cpu_down(unsigned int cpu) -{ - int err; - - cpu_maps_update_begin(); - - if (cpu_hotplug_disabled) { - err = -EBUSY; - goto out; - } - - err = _cpu_down(cpu, 0); - -out: - cpu_maps_update_done(); - return err; -} -EXPORT_SYMBOL(cpu_down); -#endif /*CONFIG_HOTPLUG_CPU*/ - -/* Requires cpu_add_remove_lock to be held */ -static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) -{ - int ret, nr_calls = 0; - void *hcpu = (void *)(long)cpu; - unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; - struct task_struct *idle; - - if (cpu_online(cpu) || !cpu_present(cpu)) - return -EINVAL; - - cpu_hotplug_begin(); - - idle = idle_thread_get(cpu); - if (IS_ERR(idle)) { - ret = PTR_ERR(idle); - goto out; - } - - ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls); - if (ret) { - nr_calls--; - printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n", - __func__, cpu); - goto out_notify; - } - - /* Arch-specific enabling code. */ - ret = __cpu_up(cpu, idle); - if (ret != 0) - goto out_notify; - BUG_ON(!cpu_online(cpu)); - - /* Now call notifier in preparation. */ - cpu_notify(CPU_ONLINE | mod, hcpu); - -out_notify: - if (ret != 0) - __cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL); -out: - cpu_hotplug_done(); - - return ret; -} - -int __cpuinit cpu_up(unsigned int cpu) -{ - int err = 0; - -#ifdef CONFIG_MEMORY_HOTPLUG - int nid; - pg_data_t *pgdat; -#endif - - if (!cpu_possible(cpu)) { - printk(KERN_ERR "can't online cpu %d because it is not " - "configured as may-hotadd at boot time\n", cpu); -#if defined(CONFIG_IA64) - printk(KERN_ERR "please check additional_cpus= boot " - "parameter\n"); -#endif - return -EINVAL; - } - -#ifdef CONFIG_MEMORY_HOTPLUG - nid = cpu_to_node(cpu); - if (!node_online(nid)) { - err = mem_online_node(nid); - if (err) - return err; - } - - pgdat = NODE_DATA(nid); - if (!pgdat) { - printk(KERN_ERR - "Can't online cpu %d due to NULL pgdat\n", cpu); - return -ENOMEM; - } - - if (pgdat->node_zonelists->_zonerefs->zone == NULL) { - mutex_lock(&zonelists_mutex); - build_all_zonelists(NULL); - mutex_unlock(&zonelists_mutex); - } -#endif - - cpu_maps_update_begin(); - - if (cpu_hotplug_disabled) { - err = -EBUSY; - goto out; - } - - err = _cpu_up(cpu, 0); - -out: - cpu_maps_update_done(); - return err; -} -EXPORT_SYMBOL_GPL(cpu_up); - -#ifdef CONFIG_PM_SLEEP_SMP -static cpumask_var_t frozen_cpus; - -void __weak arch_disable_nonboot_cpus_begin(void) -{ -} - -void __weak arch_disable_nonboot_cpus_end(void) -{ -} - -int disable_nonboot_cpus(void) -{ - int cpu, first_cpu, error = 0; - - cpu_maps_update_begin(); - first_cpu = cpumask_first(cpu_online_mask); - /* - * We take down all of the non-boot CPUs in one shot to avoid races - * with the userspace trying to use the CPU hotplug at the same time - */ - cpumask_clear(frozen_cpus); - arch_disable_nonboot_cpus_begin(); - - printk("Disabling non-boot CPUs ...\n"); - for_each_online_cpu(cpu) { - if (cpu == first_cpu) - continue; - error = _cpu_down(cpu, 1); - if (!error) - cpumask_set_cpu(cpu, frozen_cpus); - else { - printk(KERN_ERR "Error taking CPU%d down: %d\n", - cpu, error); - break; - } - } - - arch_disable_nonboot_cpus_end(); - - if (!error) { - BUG_ON(num_online_cpus() > 1); - /* Make sure the CPUs won't be enabled by someone else */ - cpu_hotplug_disabled = 1; - } else { - printk(KERN_ERR "Non-boot CPUs are not disabled\n"); - } - cpu_maps_update_done(); - return error; -} - -void __weak arch_enable_nonboot_cpus_begin(void) -{ -} - -void __weak arch_enable_nonboot_cpus_end(void) -{ -} - -void __ref enable_nonboot_cpus(void) -{ - int cpu, error; - - /* Allow everyone to use the CPU hotplug again */ - cpu_maps_update_begin(); - cpu_hotplug_disabled = 0; - if (cpumask_empty(frozen_cpus)) - goto out; - - printk(KERN_INFO "Enabling non-boot CPUs ...\n"); - - arch_enable_nonboot_cpus_begin(); - - for_each_cpu(cpu, frozen_cpus) { - error = _cpu_up(cpu, 1); - if (!error) { - printk(KERN_INFO "CPU%d is up\n", cpu); - continue; - } - printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error); - } - - arch_enable_nonboot_cpus_end(); - - cpumask_clear(frozen_cpus); -out: - cpu_maps_update_done(); -} - -static int __init alloc_frozen_cpus(void) -{ - if (!alloc_cpumask_var(&frozen_cpus, GFP_KERNEL|__GFP_ZERO)) - return -ENOMEM; - return 0; -} -core_initcall(alloc_frozen_cpus); - -/* - * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU - * hotplug when tasks are about to be frozen. Also, don't allow the freezer - * to continue until any currently running CPU hotplug operation gets - * completed. - * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the - * 'cpu_add_remove_lock'. And this same lock is also taken by the regular - * CPU hotplug path and released only after it is complete. Thus, we - * (and hence the freezer) will block here until any currently running CPU - * hotplug operation gets completed. - */ -void cpu_hotplug_disable_before_freeze(void) -{ - cpu_maps_update_begin(); - cpu_hotplug_disabled = 1; - cpu_maps_update_done(); -} - - -/* - * When tasks have been thawed, re-enable regular CPU hotplug (which had been - * disabled while beginning to freeze tasks). - */ -void cpu_hotplug_enable_after_thaw(void) -{ - cpu_maps_update_begin(); - cpu_hotplug_disabled = 0; - cpu_maps_update_done(); -} - -/* - * When callbacks for CPU hotplug notifications are being executed, we must - * ensure that the state of the system with respect to the tasks being frozen - * or not, as reported by the notification, remains unchanged *throughout the - * duration* of the execution of the callbacks. - * Hence we need to prevent the freezer from racing with regular CPU hotplug. - * - * This synchronization is implemented by mutually excluding regular CPU - * hotplug and Suspend/Hibernate call paths by hooking onto the Suspend/ - * Hibernate notifications. - */ -static int -cpu_hotplug_pm_callback(struct notifier_block *nb, - unsigned long action, void *ptr) -{ - switch (action) { - - case PM_SUSPEND_PREPARE: - case PM_HIBERNATION_PREPARE: - cpu_hotplug_disable_before_freeze(); - break; - - case PM_POST_SUSPEND: - case PM_POST_HIBERNATION: - cpu_hotplug_enable_after_thaw(); - break; - - default: - return NOTIFY_DONE; - } - - return NOTIFY_OK; -} - - -static int __init cpu_hotplug_pm_sync_init(void) -{ - pm_notifier(cpu_hotplug_pm_callback, 0); - return 0; -} -core_initcall(cpu_hotplug_pm_sync_init); - -#endif /* CONFIG_PM_SLEEP_SMP */ - -/** - * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers - * @cpu: cpu that just started - * - * This function calls the cpu_chain notifiers with CPU_STARTING. - * It must be called by the arch code on the new cpu, before the new cpu - * enables interrupts and before the "boot" cpu returns from __cpu_up(). - */ -void __cpuinit notify_cpu_starting(unsigned int cpu) -{ - unsigned long val = CPU_STARTING; - -#ifdef CONFIG_PM_SLEEP_SMP - if (frozen_cpus != NULL && cpumask_test_cpu(cpu, frozen_cpus)) - val = CPU_STARTING_FROZEN; -#endif /* CONFIG_PM_SLEEP_SMP */ - cpu_notify(val, (void *)(long)cpu); -} - -#endif /* CONFIG_SMP */ - -/* - * cpu_bit_bitmap[] is a special, "compressed" data structure that - * represents all NR_CPUS bits binary values of 1< 32 - MASK_DECLARE_8(32), MASK_DECLARE_8(40), - MASK_DECLARE_8(48), MASK_DECLARE_8(56), -#endif -}; -EXPORT_SYMBOL_GPL(cpu_bit_bitmap); - -const DECLARE_BITMAP(cpu_all_bits, NR_CPUS) = CPU_BITS_ALL; -EXPORT_SYMBOL(cpu_all_bits); - -#ifdef CONFIG_INIT_ALL_POSSIBLE -static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly - = CPU_BITS_ALL; -#else -static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly; -#endif -const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits); -EXPORT_SYMBOL(cpu_possible_mask); - -static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly; -const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits); -EXPORT_SYMBOL(cpu_online_mask); - -static DECLARE_BITMAP(cpu_present_bits, CONFIG_NR_CPUS) __read_mostly; -const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits); -EXPORT_SYMBOL(cpu_present_mask); - -static DECLARE_BITMAP(cpu_active_bits, CONFIG_NR_CPUS) __read_mostly; -const struct cpumask *const cpu_active_mask = to_cpumask(cpu_active_bits); -EXPORT_SYMBOL(cpu_active_mask); - -void set_cpu_possible(unsigned int cpu, bool possible) -{ - if (possible) - cpumask_set_cpu(cpu, to_cpumask(cpu_possible_bits)); - else - cpumask_clear_cpu(cpu, to_cpumask(cpu_possible_bits)); -} - -void set_cpu_present(unsigned int cpu, bool present) -{ - if (present) - cpumask_set_cpu(cpu, to_cpumask(cpu_present_bits)); - else - cpumask_clear_cpu(cpu, to_cpumask(cpu_present_bits)); -} - -void set_cpu_online(unsigned int cpu, bool online) -{ - if (online) - cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits)); - else - cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits)); -} - -void set_cpu_active(unsigned int cpu, bool active) -{ - if (active) - cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits)); - else - cpumask_clear_cpu(cpu, to_cpumask(cpu_active_bits)); -} - -void init_cpu_present(const struct cpumask *src) -{ - cpumask_copy(to_cpumask(cpu_present_bits), src); -} - -void init_cpu_possible(const struct cpumask *src) -{ - cpumask_copy(to_cpumask(cpu_possible_bits), src); -} - -void init_cpu_online(const struct cpumask *src) -{ - cpumask_copy(to_cpumask(cpu_online_bits), src); -} diff --git a/samples/C/diff.c b/samples/C/diff.c deleted file mode 100644 index 90baa958..00000000 --- a/samples/C/diff.c +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright (C) 2012 the libgit2 contributors - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ -#include "common.h" -#include "git2/diff.h" -#include "diff.h" -#include "fileops.h" -#include "config.h" -#include "attr_file.h" - -static char *diff_prefix_from_pathspec(const git_strarray *pathspec) -{ - git_buf prefix = GIT_BUF_INIT; - const char *scan; - - if (git_buf_common_prefix(&prefix, pathspec) < 0) - return NULL; - - /* diff prefix will only be leading non-wildcards */ - for (scan = prefix.ptr; *scan && !git__iswildcard(*scan); ++scan); - git_buf_truncate(&prefix, scan - prefix.ptr); - - if (prefix.size > 0) - return git_buf_detach(&prefix); - - git_buf_free(&prefix); - return NULL; -} - -static bool diff_pathspec_is_interesting(const git_strarray *pathspec) -{ - const char *str; - - if (pathspec == NULL || pathspec->count == 0) - return false; - if (pathspec->count > 1) - return true; - - str = pathspec->strings[0]; - if (!str || !str[0] || (!str[1] && (str[0] == '*' || str[0] == '.'))) - return false; - return true; -} - -static bool diff_path_matches_pathspec(git_diff_list *diff, const char *path) -{ - unsigned int i; - git_attr_fnmatch *match; - - if (!diff->pathspec.length) - return true; - - git_vector_foreach(&diff->pathspec, i, match) { - int result = p_fnmatch(match->pattern, path, 0); - - /* if we didn't match, look for exact dirname prefix match */ - if (result == FNM_NOMATCH && - (match->flags & GIT_ATTR_FNMATCH_HASWILD) == 0 && - strncmp(path, match->pattern, match->length) == 0 && - path[match->length] == '/') - result = 0; - - if (result == 0) - return (match->flags & GIT_ATTR_FNMATCH_NEGATIVE) ? false : true; - } - - return false; -} - -static git_diff_delta *diff_delta__alloc( - git_diff_list *diff, - git_delta_t status, - const char *path) -{ - git_diff_delta *delta = git__calloc(1, sizeof(git_diff_delta)); - if (!delta) - return NULL; - - delta->old_file.path = git_pool_strdup(&diff->pool, path); - if (delta->old_file.path == NULL) { - git__free(delta); - return NULL; - } - - delta->new_file.path = delta->old_file.path; - - if (diff->opts.flags & GIT_DIFF_REVERSE) { - switch (status) { - case GIT_DELTA_ADDED: status = GIT_DELTA_DELETED; break; - case GIT_DELTA_DELETED: status = GIT_DELTA_ADDED; break; - default: break; /* leave other status values alone */ - } - } - delta->status = status; - - return delta; -} - -static git_diff_delta *diff_delta__dup( - const git_diff_delta *d, git_pool *pool) -{ - git_diff_delta *delta = git__malloc(sizeof(git_diff_delta)); - if (!delta) - return NULL; - - memcpy(delta, d, sizeof(git_diff_delta)); - - delta->old_file.path = git_pool_strdup(pool, d->old_file.path); - if (delta->old_file.path == NULL) - goto fail; - - if (d->new_file.path != d->old_file.path) { - delta->new_file.path = git_pool_strdup(pool, d->new_file.path); - if (delta->new_file.path == NULL) - goto fail; - } else { - delta->new_file.path = delta->old_file.path; - } - - return delta; - -fail: - git__free(delta); - return NULL; -} - -static git_diff_delta *diff_delta__merge_like_cgit( - const git_diff_delta *a, const git_diff_delta *b, git_pool *pool) -{ - git_diff_delta *dup = diff_delta__dup(a, pool); - if (!dup) - return NULL; - - if (git_oid_cmp(&dup->new_file.oid, &b->new_file.oid) == 0) - return dup; - - git_oid_cpy(&dup->new_file.oid, &b->new_file.oid); - - dup->new_file.mode = b->new_file.mode; - dup->new_file.size = b->new_file.size; - dup->new_file.flags = b->new_file.flags; - - /* Emulate C git for merging two diffs (a la 'git diff '). - * - * When C git does a diff between the work dir and a tree, it actually - * diffs with the index but uses the workdir contents. This emulates - * those choices so we can emulate the type of diff. - */ - if (git_oid_cmp(&dup->old_file.oid, &dup->new_file.oid) == 0) { - if (dup->status == GIT_DELTA_DELETED) - /* preserve pending delete info */; - else if (b->status == GIT_DELTA_UNTRACKED || - b->status == GIT_DELTA_IGNORED) - dup->status = b->status; - else - dup->status = GIT_DELTA_UNMODIFIED; - } - else if (dup->status == GIT_DELTA_UNMODIFIED || - b->status == GIT_DELTA_DELETED) - dup->status = b->status; - - return dup; -} - -static int diff_delta__from_one( - git_diff_list *diff, - git_delta_t status, - const git_index_entry *entry) -{ - git_diff_delta *delta; - - if (status == GIT_DELTA_IGNORED && - (diff->opts.flags & GIT_DIFF_INCLUDE_IGNORED) == 0) - return 0; - - if (status == GIT_DELTA_UNTRACKED && - (diff->opts.flags & GIT_DIFF_INCLUDE_UNTRACKED) == 0) - return 0; - - if (!diff_path_matches_pathspec(diff, entry->path)) - return 0; - - delta = diff_delta__alloc(diff, status, entry->path); - GITERR_CHECK_ALLOC(delta); - - /* This fn is just for single-sided diffs */ - assert(status != GIT_DELTA_MODIFIED); - - if (delta->status == GIT_DELTA_DELETED) { - delta->old_file.mode = entry->mode; - delta->old_file.size = entry->file_size; - git_oid_cpy(&delta->old_file.oid, &entry->oid); - } else /* ADDED, IGNORED, UNTRACKED */ { - delta->new_file.mode = entry->mode; - delta->new_file.size = entry->file_size; - git_oid_cpy(&delta->new_file.oid, &entry->oid); - } - - delta->old_file.flags |= GIT_DIFF_FILE_VALID_OID; - delta->new_file.flags |= GIT_DIFF_FILE_VALID_OID; - - if (git_vector_insert(&diff->deltas, delta) < 0) { - git__free(delta); - return -1; - } - - return 0; -} - -static int diff_delta__from_two( - git_diff_list *diff, - git_delta_t status, - const git_index_entry *old_entry, - const git_index_entry *new_entry, - git_oid *new_oid) -{ - git_diff_delta *delta; - - if (status == GIT_DELTA_UNMODIFIED && - (diff->opts.flags & GIT_DIFF_INCLUDE_UNMODIFIED) == 0) - return 0; - - if ((diff->opts.flags & GIT_DIFF_REVERSE) != 0) { - const git_index_entry *temp = old_entry; - old_entry = new_entry; - new_entry = temp; - } - - delta = diff_delta__alloc(diff, status, old_entry->path); - GITERR_CHECK_ALLOC(delta); - - delta->old_file.mode = old_entry->mode; - git_oid_cpy(&delta->old_file.oid, &old_entry->oid); - delta->old_file.flags |= GIT_DIFF_FILE_VALID_OID; - - delta->new_file.mode = new_entry->mode; - git_oid_cpy(&delta->new_file.oid, new_oid ? new_oid : &new_entry->oid); - if (new_oid || !git_oid_iszero(&new_entry->oid)) - delta->new_file.flags |= GIT_DIFF_FILE_VALID_OID; - - if (git_vector_insert(&diff->deltas, delta) < 0) { - git__free(delta); - return -1; - } - - return 0; -} - -static char *diff_strdup_prefix(git_pool *pool, const char *prefix) -{ - size_t len = strlen(prefix); - - /* append '/' at end if needed */ - if (len > 0 && prefix[len - 1] != '/') - return git_pool_strcat(pool, prefix, "/"); - else - return git_pool_strndup(pool, prefix, len + 1); -} - -static int diff_delta__cmp(const void *a, const void *b) -{ - const git_diff_delta *da = a, *db = b; - int val = strcmp(da->old_file.path, db->old_file.path); - return val ? val : ((int)da->status - (int)db->status); -} - -static int config_bool(git_config *cfg, const char *name, int defvalue) -{ - int val = defvalue; - - if (git_config_get_bool(&val, cfg, name) < 0) - giterr_clear(); - - return val; -} - -static git_diff_list *git_diff_list_alloc( - git_repository *repo, const git_diff_options *opts) -{ - git_config *cfg; - size_t i; - git_diff_list *diff = git__calloc(1, sizeof(git_diff_list)); - if (diff == NULL) - return NULL; - - diff->repo = repo; - - if (git_vector_init(&diff->deltas, 0, diff_delta__cmp) < 0 || - git_pool_init(&diff->pool, 1, 0) < 0) - goto fail; - - /* load config values that affect diff behavior */ - if (git_repository_config__weakptr(&cfg, repo) < 0) - goto fail; - if (config_bool(cfg, "core.symlinks", 1)) - diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_HAS_SYMLINKS; - if (config_bool(cfg, "core.ignorestat", 0)) - diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_ASSUME_UNCHANGED; - if (config_bool(cfg, "core.filemode", 1)) - diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_EXEC_BIT; - if (config_bool(cfg, "core.trustctime", 1)) - diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_CTIME; - /* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */ - - if (opts == NULL) - return diff; - - memcpy(&diff->opts, opts, sizeof(git_diff_options)); - memset(&diff->opts.pathspec, 0, sizeof(diff->opts.pathspec)); - - diff->opts.old_prefix = diff_strdup_prefix(&diff->pool, - opts->old_prefix ? opts->old_prefix : DIFF_OLD_PREFIX_DEFAULT); - diff->opts.new_prefix = diff_strdup_prefix(&diff->pool, - opts->new_prefix ? opts->new_prefix : DIFF_NEW_PREFIX_DEFAULT); - - if (!diff->opts.old_prefix || !diff->opts.new_prefix) - goto fail; - - if (diff->opts.flags & GIT_DIFF_REVERSE) { - char *swap = diff->opts.old_prefix; - diff->opts.old_prefix = diff->opts.new_prefix; - diff->opts.new_prefix = swap; - } - - /* only copy pathspec if it is "interesting" so we can test - * diff->pathspec.length > 0 to know if it is worth calling - * fnmatch as we iterate. - */ - if (!diff_pathspec_is_interesting(&opts->pathspec)) - return diff; - - if (git_vector_init( - &diff->pathspec, (unsigned int)opts->pathspec.count, NULL) < 0) - goto fail; - - for (i = 0; i < opts->pathspec.count; ++i) { - int ret; - const char *pattern = opts->pathspec.strings[i]; - git_attr_fnmatch *match = git__calloc(1, sizeof(git_attr_fnmatch)); - if (!match) - goto fail; - match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE; - ret = git_attr_fnmatch__parse(match, &diff->pool, NULL, &pattern); - if (ret == GIT_ENOTFOUND) { - git__free(match); - continue; - } else if (ret < 0) - goto fail; - - if (git_vector_insert(&diff->pathspec, match) < 0) - goto fail; - } - - return diff; - -fail: - git_diff_list_free(diff); - return NULL; -} - -void git_diff_list_free(git_diff_list *diff) -{ - git_diff_delta *delta; - git_attr_fnmatch *match; - unsigned int i; - - if (!diff) - return; - - git_vector_foreach(&diff->deltas, i, delta) { - git__free(delta); - diff->deltas.contents[i] = NULL; - } - git_vector_free(&diff->deltas); - - git_vector_foreach(&diff->pathspec, i, match) { - git__free(match); - diff->pathspec.contents[i] = NULL; - } - git_vector_free(&diff->pathspec); - - git_pool_clear(&diff->pool); - git__free(diff); -} - -static int oid_for_workdir_item( - git_repository *repo, - const git_index_entry *item, - git_oid *oid) -{ - int result; - git_buf full_path = GIT_BUF_INIT; - - if (git_buf_joinpath(&full_path, git_repository_workdir(repo), item->path) < 0) - return -1; - - /* calculate OID for file if possible*/ - if (S_ISLNK(item->mode)) - result = git_odb__hashlink(oid, full_path.ptr); - else if (!git__is_sizet(item->file_size)) { - giterr_set(GITERR_OS, "File size overflow for 32-bit systems"); - result = -1; - } else { - int fd = git_futils_open_ro(full_path.ptr); - if (fd < 0) - result = fd; - else { - result = git_odb__hashfd( - oid, fd, (size_t)item->file_size, GIT_OBJ_BLOB); - p_close(fd); - } - } - - git_buf_free(&full_path); - - return result; -} - -#define EXEC_BIT_MASK 0000111 - -static int maybe_modified( - git_iterator *old_iter, - const git_index_entry *oitem, - git_iterator *new_iter, - const git_index_entry *nitem, - git_diff_list *diff) -{ - git_oid noid, *use_noid = NULL; - git_delta_t status = GIT_DELTA_MODIFIED; - unsigned int omode = oitem->mode; - unsigned int nmode = nitem->mode; - - GIT_UNUSED(old_iter); - - if (!diff_path_matches_pathspec(diff, oitem->path)) - return 0; - - /* on platforms with no symlinks, promote plain files to symlinks */ - if (S_ISLNK(omode) && S_ISREG(nmode) && - !(diff->diffcaps & GIT_DIFFCAPS_HAS_SYMLINKS)) - nmode = GIT_MODE_TYPE(omode) | (nmode & GIT_MODE_PERMS_MASK); - - /* on platforms with no execmode, clear exec bit from comparisons */ - if (!(diff->diffcaps & GIT_DIFFCAPS_TRUST_EXEC_BIT)) { - omode = omode & ~EXEC_BIT_MASK; - nmode = nmode & ~EXEC_BIT_MASK; - } - - /* support "assume unchanged" (badly, b/c we still stat everything) */ - if ((diff->diffcaps & GIT_DIFFCAPS_ASSUME_UNCHANGED) != 0) - status = (oitem->flags_extended & GIT_IDXENTRY_INTENT_TO_ADD) ? - GIT_DELTA_MODIFIED : GIT_DELTA_UNMODIFIED; - - /* support "skip worktree" index bit */ - else if ((oitem->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE) != 0) - status = GIT_DELTA_UNMODIFIED; - - /* if basic type of file changed, then split into delete and add */ - else if (GIT_MODE_TYPE(omode) != GIT_MODE_TYPE(nmode)) { - if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 || - diff_delta__from_one(diff, GIT_DELTA_ADDED, nitem) < 0) - return -1; - return 0; - } - - /* if oids and modes match, then file is unmodified */ - else if (git_oid_cmp(&oitem->oid, &nitem->oid) == 0 && - omode == nmode) - status = GIT_DELTA_UNMODIFIED; - - /* if we have a workdir item with an unknown oid, check deeper */ - else if (git_oid_iszero(&nitem->oid) && new_iter->type == GIT_ITERATOR_WORKDIR) { - /* TODO: add check against index file st_mtime to avoid racy-git */ - - /* if they files look exactly alike, then we'll assume the same */ - if (oitem->file_size == nitem->file_size && - (!(diff->diffcaps & GIT_DIFFCAPS_TRUST_CTIME) || - (oitem->ctime.seconds == nitem->ctime.seconds)) && - oitem->mtime.seconds == nitem->mtime.seconds && - (!(diff->diffcaps & GIT_DIFFCAPS_USE_DEV) || - (oitem->dev == nitem->dev)) && - oitem->ino == nitem->ino && - oitem->uid == nitem->uid && - oitem->gid == nitem->gid) - status = GIT_DELTA_UNMODIFIED; - - else if (S_ISGITLINK(nmode)) { - git_submodule *sub; - - if ((diff->opts.flags & GIT_DIFF_IGNORE_SUBMODULES) != 0) - status = GIT_DELTA_UNMODIFIED; - else if (git_submodule_lookup(&sub, diff->repo, nitem->path) < 0) - return -1; - else if (sub->ignore == GIT_SUBMODULE_IGNORE_ALL) - status = GIT_DELTA_UNMODIFIED; - else { - /* TODO: support other GIT_SUBMODULE_IGNORE values */ - status = GIT_DELTA_UNMODIFIED; - } - } - - /* TODO: check git attributes so we will not have to read the file - * in if it is marked binary. - */ - - else if (oid_for_workdir_item(diff->repo, nitem, &noid) < 0) - return -1; - - else if (git_oid_cmp(&oitem->oid, &noid) == 0 && - omode == nmode) - status = GIT_DELTA_UNMODIFIED; - - /* store calculated oid so we don't have to recalc later */ - use_noid = &noid; - } - - return diff_delta__from_two(diff, status, oitem, nitem, use_noid); -} - -static int diff_from_iterators( - git_repository *repo, - const git_diff_options *opts, /**< can be NULL for defaults */ - git_iterator *old_iter, - git_iterator *new_iter, - git_diff_list **diff_ptr) -{ - const git_index_entry *oitem, *nitem; - git_buf ignore_prefix = GIT_BUF_INIT; - git_diff_list *diff = git_diff_list_alloc(repo, opts); - if (!diff) - goto fail; - - diff->old_src = old_iter->type; - diff->new_src = new_iter->type; - - if (git_iterator_current(old_iter, &oitem) < 0 || - git_iterator_current(new_iter, &nitem) < 0) - goto fail; - - /* run iterators building diffs */ - while (oitem || nitem) { - - /* create DELETED records for old items not matched in new */ - if (oitem && (!nitem || strcmp(oitem->path, nitem->path) < 0)) { - if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 || - git_iterator_advance(old_iter, &oitem) < 0) - goto fail; - } - - /* create ADDED, TRACKED, or IGNORED records for new items not - * matched in old (and/or descend into directories as needed) - */ - else if (nitem && (!oitem || strcmp(oitem->path, nitem->path) > 0)) { - git_delta_t delta_type = GIT_DELTA_UNTRACKED; - - /* check if contained in ignored parent directory */ - if (git_buf_len(&ignore_prefix) && - git__prefixcmp(nitem->path, git_buf_cstr(&ignore_prefix)) == 0) - delta_type = GIT_DELTA_IGNORED; - - if (S_ISDIR(nitem->mode)) { - /* recurse into directory only if there are tracked items in - * it or if the user requested the contents of untracked - * directories and it is not under an ignored directory. - */ - if ((oitem && git__prefixcmp(oitem->path, nitem->path) == 0) || - (delta_type == GIT_DELTA_UNTRACKED && - (diff->opts.flags & GIT_DIFF_RECURSE_UNTRACKED_DIRS) != 0)) - { - /* if this directory is ignored, remember it as the - * "ignore_prefix" for processing contained items - */ - if (delta_type == GIT_DELTA_UNTRACKED && - git_iterator_current_is_ignored(new_iter)) - git_buf_sets(&ignore_prefix, nitem->path); - - if (git_iterator_advance_into_directory(new_iter, &nitem) < 0) - goto fail; - - continue; - } - } - - /* In core git, the next two "else if" clauses are effectively - * reversed -- i.e. when an untracked file contained in an - * ignored directory is individually ignored, it shows up as an - * ignored file in the diff list, even though other untracked - * files in the same directory are skipped completely. - * - * To me, this is odd. If the directory is ignored and the file - * is untracked, we should skip it consistently, regardless of - * whether it happens to match a pattern in the ignore file. - * - * To match the core git behavior, just reverse the following - * two "else if" cases so that individual file ignores are - * checked before container directory exclusions are used to - * skip the file. - */ - else if (delta_type == GIT_DELTA_IGNORED) { - if (git_iterator_advance(new_iter, &nitem) < 0) - goto fail; - continue; /* ignored parent directory, so skip completely */ - } - - else if (git_iterator_current_is_ignored(new_iter)) - delta_type = GIT_DELTA_IGNORED; - - else if (new_iter->type != GIT_ITERATOR_WORKDIR) - delta_type = GIT_DELTA_ADDED; - - if (diff_delta__from_one(diff, delta_type, nitem) < 0 || - git_iterator_advance(new_iter, &nitem) < 0) - goto fail; - } - - /* otherwise item paths match, so create MODIFIED record - * (or ADDED and DELETED pair if type changed) - */ - else { - assert(oitem && nitem && strcmp(oitem->path, nitem->path) == 0); - - if (maybe_modified(old_iter, oitem, new_iter, nitem, diff) < 0 || - git_iterator_advance(old_iter, &oitem) < 0 || - git_iterator_advance(new_iter, &nitem) < 0) - goto fail; - } - } - - git_iterator_free(old_iter); - git_iterator_free(new_iter); - git_buf_free(&ignore_prefix); - - *diff_ptr = diff; - return 0; - -fail: - git_iterator_free(old_iter); - git_iterator_free(new_iter); - git_buf_free(&ignore_prefix); - - git_diff_list_free(diff); - *diff_ptr = NULL; - return -1; -} - - -int git_diff_tree_to_tree( - git_repository *repo, - const git_diff_options *opts, /**< can be NULL for defaults */ - git_tree *old_tree, - git_tree *new_tree, - git_diff_list **diff) -{ - git_iterator *a = NULL, *b = NULL; - char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL; - - assert(repo && old_tree && new_tree && diff); - - if (git_iterator_for_tree_range(&a, repo, old_tree, prefix, prefix) < 0 || - git_iterator_for_tree_range(&b, repo, new_tree, prefix, prefix) < 0) - return -1; - - git__free(prefix); - - return diff_from_iterators(repo, opts, a, b, diff); -} - -int git_diff_index_to_tree( - git_repository *repo, - const git_diff_options *opts, - git_tree *old_tree, - git_diff_list **diff) -{ - git_iterator *a = NULL, *b = NULL; - char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL; - - assert(repo && diff); - - if (git_iterator_for_tree_range(&a, repo, old_tree, prefix, prefix) < 0 || - git_iterator_for_index_range(&b, repo, prefix, prefix) < 0) - return -1; - - git__free(prefix); - - return diff_from_iterators(repo, opts, a, b, diff); -} - -int git_diff_workdir_to_index( - git_repository *repo, - const git_diff_options *opts, - git_diff_list **diff) -{ - git_iterator *a = NULL, *b = NULL; - char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL; - - assert(repo && diff); - - if (git_iterator_for_index_range(&a, repo, prefix, prefix) < 0 || - git_iterator_for_workdir_range(&b, repo, prefix, prefix) < 0) - return -1; - - git__free(prefix); - - return diff_from_iterators(repo, opts, a, b, diff); -} - - -int git_diff_workdir_to_tree( - git_repository *repo, - const git_diff_options *opts, - git_tree *old_tree, - git_diff_list **diff) -{ - git_iterator *a = NULL, *b = NULL; - char *prefix = opts ? diff_prefix_from_pathspec(&opts->pathspec) : NULL; - - assert(repo && old_tree && diff); - - if (git_iterator_for_tree_range(&a, repo, old_tree, prefix, prefix) < 0 || - git_iterator_for_workdir_range(&b, repo, prefix, prefix) < 0) - return -1; - - git__free(prefix); - - return diff_from_iterators(repo, opts, a, b, diff); -} - -int git_diff_merge( - git_diff_list *onto, - const git_diff_list *from) -{ - int error = 0; - git_pool onto_pool; - git_vector onto_new; - git_diff_delta *delta; - unsigned int i, j; - - assert(onto && from); - - if (!from->deltas.length) - return 0; - - if (git_vector_init(&onto_new, onto->deltas.length, diff_delta__cmp) < 0 || - git_pool_init(&onto_pool, 1, 0) < 0) - return -1; - - for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) { - git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i); - const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j); - int cmp = !f ? -1 : !o ? 1 : strcmp(o->old_file.path, f->old_file.path); - - if (cmp < 0) { - delta = diff_delta__dup(o, &onto_pool); - i++; - } else if (cmp > 0) { - delta = diff_delta__dup(f, &onto_pool); - j++; - } else { - delta = diff_delta__merge_like_cgit(o, f, &onto_pool); - i++; - j++; - } - - if ((error = !delta ? -1 : git_vector_insert(&onto_new, delta)) < 0) - break; - } - - if (!error) { - git_vector_swap(&onto->deltas, &onto_new); - git_pool_swap(&onto->pool, &onto_pool); - onto->new_src = from->new_src; - } - - git_vector_foreach(&onto_new, i, delta) - git__free(delta); - git_vector_free(&onto_new); - git_pool_clear(&onto_pool); - - return error; -} - diff --git a/samples/C/fudge_node.c b/samples/C/fudge_node.c new file mode 100644 index 00000000..41a335d5 --- /dev/null +++ b/samples/C/fudge_node.c @@ -0,0 +1,188 @@ +/* Copyright (c) 2010 Jens Nyberg + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include "pipe.h" + +static struct system_node root; +static struct system_node clone; + +static unsigned int read(struct pipe_end *endself, struct pipe_end *endtarget, struct service_state *state, unsigned int count, void *buffer) +{ + + count = buffer_rcfifo(&endself->buffer, count, buffer); + + if (!count && endtarget->node.refcount) + { + + list_add(&endself->readlinks, &state->link); + task_setstatus(state->link.data, TASK_STATUS_BLOCKED); + + } + + system_wakeup(&endtarget->writelinks); + + return count; + +} + +static unsigned int write(struct pipe_end *endself, struct pipe_end *endtarget, struct service_state *state, unsigned int count, void *buffer) +{ + + count = buffer_wcfifo(&endtarget->buffer, count, buffer); + + if (!count) + { + + list_add(&endself->writelinks, &state->link); + task_setstatus(state->link.data, TASK_STATUS_BLOCKED); + + } + + system_wakeup(&endtarget->readlinks); + + return count; + +} + +static unsigned int end0_read(struct system_node *self, struct service_state *state, unsigned int count, void *buffer) +{ + + struct pipe *pipe = (struct pipe *)self->parent; + + return read(&pipe->end0, &pipe->end1, state, count, buffer); + +} + +static unsigned int end0_write(struct system_node *self, struct service_state *state, unsigned int count, void *buffer) +{ + + struct pipe *pipe = (struct pipe *)self->parent; + + return write(&pipe->end0, &pipe->end1, state, count, buffer); + +} + +static unsigned int end1_read(struct system_node *self, struct service_state *state, unsigned int count, void *buffer) +{ + + struct pipe *pipe = (struct pipe *)self->parent; + + return read(&pipe->end1, &pipe->end0, state, count, buffer); + +} + +static unsigned int end1_write(struct system_node *self, struct service_state *state, unsigned int count, void *buffer) +{ + + struct pipe *pipe = (struct pipe *)self->parent; + + return write(&pipe->end1, &pipe->end0, state, count, buffer); + +} + +static unsigned int clone_child(struct system_node *self, unsigned int count, char *path) +{ + + struct list_item *current; + + for (current = root.children.head; current; current = current->next) + { + + struct system_node *node = current->data; + struct pipe *pipe = current->data; + + if (node == self) + continue; + + if (pipe->end0.node.refcount || pipe->end1.node.refcount) + continue; + + return node->child(node, count, path); + + } + + return 0; + +} + +void pipe_init(struct pipe *pipe) +{ + + buffer_init(&pipe->end0.buffer, 4096, pipe->end0.data); + buffer_init(&pipe->end1.buffer, 4096, pipe->end1.data); + system_initnode(&pipe->end0.node, SYSTEM_NODETYPE_NORMAL, "0"); + system_initnode(&pipe->end1.node, SYSTEM_NODETYPE_NORMAL, "1"); + + pipe->end0.node.read = end0_read; + pipe->end0.node.write = end0_write; + pipe->end1.node.read = end1_read; + pipe->end1.node.write = end1_write; + + system_initnode(&pipe->root, SYSTEM_NODETYPE_GROUP | SYSTEM_NODETYPE_MULTI, "pipe"); + system_addchild(&pipe->root, &pipe->end0.node); + system_addchild(&pipe->root, &pipe->end1.node); + +} + +void pipe_register(struct pipe *pipe) +{ + + system_addchild(&root, &pipe->root); + +} + +void pipe_unregister(struct pipe *pipe) +{ + + system_removechild(&root, &pipe->root); + +} + +void module_init(void) +{ + + system_initnode(&root, SYSTEM_NODETYPE_GROUP, "pipe"); + system_initnode(&clone, SYSTEM_NODETYPE_GROUP, "clone"); + + clone.child = clone_child; + + system_addchild(&root, &clone); + +} + +void module_register(void) +{ + + system_registernode(&root); + +} + +void module_unregister(void) +{ + + system_unregisternode(&root); + +} diff --git a/samples/C/hash.c b/samples/C/hash.c deleted file mode 100644 index 46075691..00000000 --- a/samples/C/hash.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2009-2012 the libgit2 contributors - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#include "common.h" -#include "hash.h" - -#if defined(PPC_SHA1) -# include "ppc/sha1.h" -#else -# include "sha1.h" -#endif - -struct git_hash_ctx { - SHA_CTX c; -}; - -git_hash_ctx *git_hash_new_ctx(void) -{ - git_hash_ctx *ctx = git__malloc(sizeof(*ctx)); - - if (!ctx) - return NULL; - - SHA1_Init(&ctx->c); - - return ctx; -} - -void git_hash_free_ctx(git_hash_ctx *ctx) -{ - git__free(ctx); -} - -void git_hash_init(git_hash_ctx *ctx) -{ - assert(ctx); - SHA1_Init(&ctx->c); -} - -void git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) -{ - assert(ctx); - SHA1_Update(&ctx->c, data, len); -} - -void git_hash_final(git_oid *out, git_hash_ctx *ctx) -{ - assert(ctx); - SHA1_Final(out->id, &ctx->c); -} - -void git_hash_buf(git_oid *out, const void *data, size_t len) -{ - SHA_CTX c; - - SHA1_Init(&c); - SHA1_Update(&c, data, len); - SHA1_Final(out->id, &c); -} - -void git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n) -{ - SHA_CTX c; - size_t i; - - SHA1_Init(&c); - for (i = 0; i < n; i++) - SHA1_Update(&c, vec[i].data, vec[i].len); - SHA1_Final(out->id, &c); -} From 85516563f7f82cc1f82a680de48f02a1e6426e77 Mon Sep 17 00:00:00 2001 From: Sahil Dua Date: Sun, 26 Jun 2016 05:17:10 +0530 Subject: [PATCH 2/3] Add another sample file for C --- samples/C/code.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 samples/C/code.c diff --git a/samples/C/code.c b/samples/C/code.c new file mode 100644 index 00000000..43fb1466 --- /dev/null +++ b/samples/C/code.c @@ -0,0 +1,106 @@ +/*A C calculator...of sorts*/ +/* An attempt at a C calculator from stuff read so far */ + +#include + +/* function for addition */ + +int add(int input1, int input2) +{ + int result; + + result = input1 + input2; + + return result; +} + +/* function for multiplication */ + +int multi(int input1, int input2) +{ + int result; + + result = input1 * input2; + + return result; +} + +/* function for subtraction */ + +int sub(int input1, int input2) +{ + int result; + + result = input1 - input2; + + return result; +} + +/* division function */ + +float div(float input1, float input2) +{ + float result; + + result = input1 / input2; + + return result; +} + +int main() +{ + int a, b, output; + float output2; + char myinput; + + printf("Please enter a number\n"); + scanf("%d", &a); + printf("Enter another number\n"); + scanf("%d", &b); + printf("What calculation would you like to perform?\n"); + printf("a) addition\n"); + printf("b) mulitplication\n"); + printf("c) subtraction\n"); + printf("d) division\n"); + scanf(" %c", &myinput); + + /* switch statement to run certain calculations */ + switch(myinput) + { + case 'a': + { + printf("Adding the numbers entered...\n"); + output = add(a, b); + printf("The sum of %d and %d is: %d\n", a, b, output); + break; + } + case 'b': + { + printf("Multiplication chosen\n"); + output = multi(a, b); + printf("Multiplying %d and %d equals %d\n", a, b , output); + break; + } + case 'c': + { + printf("Subtracting %d from %d\n", a, b); + output = sub(a, b); + printf("%d minus %d is: %d\n", a, b, output); + break; + } + case 'd': + { + printf("Divison program running...\n"); + output2 = div(a, b); + printf("Division of %d by %d equals %f\n", a, b, output2); + break; + } + default: + { + printf("Invalid entry\n"); + printf("Please run again\n"); + } + } + + return 0; +} From 39cd635086c41de3ece1ecd92bd9b62edaadb15b Mon Sep 17 00:00:00 2001 From: Sahil Dua Date: Mon, 27 Jun 2016 11:54:36 +0530 Subject: [PATCH 3/3] Replace sample without license --- samples/C/code.c | 106 -------------- samples/C/custom_extensions.c | 257 ++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+), 106 deletions(-) delete mode 100644 samples/C/code.c create mode 100644 samples/C/custom_extensions.c diff --git a/samples/C/code.c b/samples/C/code.c deleted file mode 100644 index 43fb1466..00000000 --- a/samples/C/code.c +++ /dev/null @@ -1,106 +0,0 @@ -/*A C calculator...of sorts*/ -/* An attempt at a C calculator from stuff read so far */ - -#include - -/* function for addition */ - -int add(int input1, int input2) -{ - int result; - - result = input1 + input2; - - return result; -} - -/* function for multiplication */ - -int multi(int input1, int input2) -{ - int result; - - result = input1 * input2; - - return result; -} - -/* function for subtraction */ - -int sub(int input1, int input2) -{ - int result; - - result = input1 - input2; - - return result; -} - -/* division function */ - -float div(float input1, float input2) -{ - float result; - - result = input1 / input2; - - return result; -} - -int main() -{ - int a, b, output; - float output2; - char myinput; - - printf("Please enter a number\n"); - scanf("%d", &a); - printf("Enter another number\n"); - scanf("%d", &b); - printf("What calculation would you like to perform?\n"); - printf("a) addition\n"); - printf("b) mulitplication\n"); - printf("c) subtraction\n"); - printf("d) division\n"); - scanf(" %c", &myinput); - - /* switch statement to run certain calculations */ - switch(myinput) - { - case 'a': - { - printf("Adding the numbers entered...\n"); - output = add(a, b); - printf("The sum of %d and %d is: %d\n", a, b, output); - break; - } - case 'b': - { - printf("Multiplication chosen\n"); - output = multi(a, b); - printf("Multiplying %d and %d equals %d\n", a, b , output); - break; - } - case 'c': - { - printf("Subtracting %d from %d\n", a, b); - output = sub(a, b); - printf("%d minus %d is: %d\n", a, b, output); - break; - } - case 'd': - { - printf("Divison program running...\n"); - output2 = div(a, b); - printf("Division of %d by %d equals %f\n", a, b, output2); - break; - } - default: - { - printf("Invalid entry\n"); - printf("Please run again\n"); - } - } - - return 0; -} diff --git a/samples/C/custom_extensions.c b/samples/C/custom_extensions.c new file mode 100644 index 00000000..75702154 --- /dev/null +++ b/samples/C/custom_extensions.c @@ -0,0 +1,257 @@ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + + +void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension) { + OPENSSL_free(custom_extension); +} + +static const SSL_CUSTOM_EXTENSION *custom_ext_find( + STACK_OF(SSL_CUSTOM_EXTENSION) *stack, + unsigned *out_index, uint16_t value) { + size_t i; + for (i = 0; i < sk_SSL_CUSTOM_EXTENSION_num(stack); i++) { + const SSL_CUSTOM_EXTENSION *ext = sk_SSL_CUSTOM_EXTENSION_value(stack, i); + if (ext->value == value) { + if (out_index != NULL) { + *out_index = i; + } + return ext; + } + } + + return NULL; +} + +/* default_add_callback is used as the |add_callback| when the user doesn't + * provide one. For servers, it does nothing while, for clients, it causes an + * empty extension to be included. */ +static int default_add_callback(SSL *ssl, unsigned extension_value, + const uint8_t **out, size_t *out_len, + int *out_alert_value, void *add_arg) { + if (ssl->server) { + return 0; + } + *out_len = 0; + return 1; +} + +static int custom_ext_add_hello(SSL *ssl, CBB *extensions) { + STACK_OF(SSL_CUSTOM_EXTENSION) *stack = ssl->ctx->client_custom_extensions; + if (ssl->server) { + stack = ssl->ctx->server_custom_extensions; + } + + if (stack == NULL) { + return 1; + } + + size_t i; + for (i = 0; i < sk_SSL_CUSTOM_EXTENSION_num(stack); i++) { + const SSL_CUSTOM_EXTENSION *ext = sk_SSL_CUSTOM_EXTENSION_value(stack, i); + + if (ssl->server && + !(ssl->s3->tmp.custom_extensions.received & (1u << i))) { + /* Servers cannot echo extensions that the client didn't send. */ + continue; + } + + const uint8_t *contents; + size_t contents_len; + int alert = SSL_AD_DECODE_ERROR; + CBB contents_cbb; + + switch (ext->add_callback(ssl, ext->value, &contents, &contents_len, &alert, + ext->add_arg)) { + case 1: + if (!CBB_add_u16(extensions, ext->value) || + !CBB_add_u16_length_prefixed(extensions, &contents_cbb) || + !CBB_add_bytes(&contents_cbb, contents, contents_len) || + !CBB_flush(extensions)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + ERR_add_error_dataf("extension: %u", (unsigned) ext->value); + if (ext->free_callback && 0 < contents_len) { + ext->free_callback(ssl, ext->value, contents, ext->add_arg); + } + return 0; + } + + if (ext->free_callback && 0 < contents_len) { + ext->free_callback(ssl, ext->value, contents, ext->add_arg); + } + + if (!ssl->server) { + assert((ssl->s3->tmp.custom_extensions.sent & (1u << i)) == 0); + ssl->s3->tmp.custom_extensions.sent |= (1u << i); + } + break; + + case 0: + break; + + default: + ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); + OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR); + ERR_add_error_dataf("extension: %u", (unsigned) ext->value); + return 0; + } + } + + return 1; +} + +int custom_ext_add_clienthello(SSL *ssl, CBB *extensions) { + return custom_ext_add_hello(ssl, extensions); +} + +int custom_ext_parse_serverhello(SSL *ssl, int *out_alert, uint16_t value, + const CBS *extension) { + unsigned index; + const SSL_CUSTOM_EXTENSION *ext = + custom_ext_find(ssl->ctx->client_custom_extensions, &index, value); + + if (/* Unknown extensions are not allowed in a ServerHello. */ + ext == NULL || + /* Also, if we didn't send the extension, that's also unacceptable. */ + !(ssl->s3->tmp.custom_extensions.sent & (1u << index))) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); + ERR_add_error_dataf("extension: %u", (unsigned)value); + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + if (ext->parse_callback != NULL && + !ext->parse_callback(ssl, value, CBS_data(extension), CBS_len(extension), + out_alert, ext->parse_arg)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR); + ERR_add_error_dataf("extension: %u", (unsigned)ext->value); + return 0; + } + + return 1; +} + +int custom_ext_parse_clienthello(SSL *ssl, int *out_alert, uint16_t value, + const CBS *extension) { + unsigned index; + const SSL_CUSTOM_EXTENSION *ext = + custom_ext_find(ssl->ctx->server_custom_extensions, &index, value); + + if (ext == NULL) { + return 1; + } + + assert((ssl->s3->tmp.custom_extensions.received & (1u << index)) == 0); + ssl->s3->tmp.custom_extensions.received |= (1u << index); + + if (ext->parse_callback && + !ext->parse_callback(ssl, value, CBS_data(extension), CBS_len(extension), + out_alert, ext->parse_arg)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR); + ERR_add_error_dataf("extension: %u", (unsigned)ext->value); + return 0; + } + + return 1; +} + +int custom_ext_add_serverhello(SSL *ssl, CBB *extensions) { + return custom_ext_add_hello(ssl, extensions); +} + +/* MAX_NUM_CUSTOM_EXTENSIONS is the maximum number of custom extensions that + * can be set on an |SSL_CTX|. It's determined by the size of the bitset used + * to track when an extension has been sent. */ +#define MAX_NUM_CUSTOM_EXTENSIONS \ + (sizeof(((struct ssl3_state_st *)NULL)->tmp.custom_extensions.sent) * 8) + +static int custom_ext_append(STACK_OF(SSL_CUSTOM_EXTENSION) **stack, + unsigned extension_value, + SSL_custom_ext_add_cb add_cb, + SSL_custom_ext_free_cb free_cb, void *add_arg, + SSL_custom_ext_parse_cb parse_cb, + void *parse_arg) { + if (add_cb == NULL || + 0xffff < extension_value || + SSL_extension_supported(extension_value) || + /* Specifying a free callback without an add callback is nonsensical + * and an error. */ + (*stack != NULL && + (MAX_NUM_CUSTOM_EXTENSIONS <= sk_SSL_CUSTOM_EXTENSION_num(*stack) || + custom_ext_find(*stack, NULL, extension_value) != NULL))) { + return 0; + } + + SSL_CUSTOM_EXTENSION *ext = OPENSSL_malloc(sizeof(SSL_CUSTOM_EXTENSION)); + if (ext == NULL) { + return 0; + } + ext->add_callback = add_cb; + ext->add_arg = add_arg; + ext->free_callback = free_cb; + ext->parse_callback = parse_cb; + ext->parse_arg = parse_arg; + ext->value = extension_value; + + if (*stack == NULL) { + *stack = sk_SSL_CUSTOM_EXTENSION_new_null(); + if (*stack == NULL) { + SSL_CUSTOM_EXTENSION_free(ext); + return 0; + } + } + + if (!sk_SSL_CUSTOM_EXTENSION_push(*stack, ext)) { + SSL_CUSTOM_EXTENSION_free(ext); + if (sk_SSL_CUSTOM_EXTENSION_num(*stack) == 0) { + sk_SSL_CUSTOM_EXTENSION_free(*stack); + *stack = NULL; + } + return 0; + } + + return 1; +} + +int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned extension_value, + SSL_custom_ext_add_cb add_cb, + SSL_custom_ext_free_cb free_cb, void *add_arg, + SSL_custom_ext_parse_cb parse_cb, + void *parse_arg) { + return custom_ext_append(&ctx->client_custom_extensions, extension_value, + add_cb ? add_cb : default_add_callback, free_cb, + add_arg, parse_cb, parse_arg); +} + +int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned extension_value, + SSL_custom_ext_add_cb add_cb, + SSL_custom_ext_free_cb free_cb, void *add_arg, + SSL_custom_ext_parse_cb parse_cb, + void *parse_arg) { + return custom_ext_append(&ctx->server_custom_extensions, extension_value, + add_cb ? add_cb : default_add_callback, free_cb, + add_arg, parse_cb, parse_arg); +} \ No newline at end of file