Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
78e16c34
Commit
78e16c34
authored
9 years ago
by
Carlos Martín Nieto
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3597 from ethomson/filter_registration
Filter registration
parents
b643501d
82abd40d
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
368 additions
and
302 deletions
+368
-302
include/git2/sys/filter.h
+34
-25
src/filter.c
+154
-123
src/filter.h
+2
-0
src/global.c
+55
-153
src/openssl_stream.c
+120
-0
src/openssl_stream.h
+2
-0
src/thread-utils.h
+1
-1
No files found.
include/git2/sys/filter.h
View file @
78e16c34
...
...
@@ -127,17 +127,6 @@ GIT_EXTERN(git_filter_mode_t) git_filter_source_mode(const git_filter_source *sr
*/
GIT_EXTERN
(
uint32_t
)
git_filter_source_flags
(
const
git_filter_source
*
src
);
/*
* struct git_filter
*
* The filter lifecycle:
* - initialize - first use of filter
* - shutdown - filter removed/unregistered from system
* - check - considering filter for file
* - apply - apply filter to file contents
* - cleanup - done with file
*/
/**
* Initialize callback on filter
*
...
...
@@ -233,31 +222,51 @@ typedef void (*git_filter_cleanup_fn)(
* To associate extra data with a filter, allocate extra data and put the
* `git_filter` struct at the start of your data buffer, then cast the
* `self` pointer to your larger structure when your callback is invoked.
*
* `version` should be set to GIT_FILTER_VERSION
*
* `attributes` is a whitespace-separated list of attribute names to check
* for this filter (e.g. "eol crlf text"). If the attribute name is bare,
* it will be simply loaded and passed to the `check` callback. If it has
* a value (i.e. "name=value"), the attribute must match that value for
* the filter to be applied. The value may be a wildcard (eg, "name=*"),
* in which case the filter will be invoked for any value for the given
* attribute name. See the attribute parameter of the `check` callback
* for the attribute value that was specified.
*
* The `initialize`, `shutdown`, `check`, `apply`, and `cleanup` callbacks
* are all documented above with the respective function pointer typedefs.
*/
struct
git_filter
{
/** The `version` field should be set to `GIT_FILTER_VERSION`. */
unsigned
int
version
;
/**
* A whitespace-separated list of attribute names to check for this
* filter (e.g. "eol crlf text"). If the attribute name is bare, it
* will be simply loaded and passed to the `check` callback. If it
* has a value (i.e. "name=value"), the attribute must match that
* value for the filter to be applied. The value may be a wildcard
* (eg, "name=*"), in which case the filter will be invoked for any
* value for the given attribute name. See the attribute parameter
* of the `check` callback for the attribute value that was specified.
*/
const
char
*
attributes
;
/** Called when the filter is first used for any file. */
git_filter_init_fn
initialize
;
/** Called when the filter is removed or unregistered from the system. */
git_filter_shutdown_fn
shutdown
;
/**
* Called to determine whether the filter should be invoked for a
* given file. If this function returns `GIT_PASSTHROUGH` then the
* `apply` function will not be invoked and the contents will be passed
* through unmodified.
*/
git_filter_check_fn
check
;
/**
* Called to actually apply the filter to file contents. If this
* function returns `GIT_PASSTHROUGH` then the contents will be passed
* through unmodified.
*/
git_filter_apply_fn
apply
;
/**
* Called to apply the filter in a streaming manner. If this is not
* specified then the system will call `apply` with the whole buffer.
*/
git_filter_stream_fn
stream
;
/** Called when the system is done filtering for a file. */
git_filter_cleanup_fn
cleanup
;
};
...
...
This diff is collapsed.
Click to expand it.
src/filter.c
View file @
78e16c34
...
...
@@ -56,80 +56,15 @@ static int filter_def_priority_cmp(const void *a, const void *b)
return
(
pa
<
pb
)
?
-
1
:
(
pa
>
pb
)
?
1
:
0
;
}
struct
filter_registry
{
struct
git_filter_registry
{
git_rwlock
lock
;
git_vector
filters
;
};
static
struct
filter_registry
*
git__filter_registry
=
NULL
;
static
struct
git_filter_registry
filter_registry
;
static
void
filter_registry_shutdown
(
void
)
{
struct
filter_registry
*
reg
=
NULL
;
size_t
pos
;
git_filter_def
*
fdef
;
if
((
reg
=
git__swap
(
git__filter_registry
,
NULL
))
==
NULL
)
return
;
git_vector_foreach
(
&
reg
->
filters
,
pos
,
fdef
)
{
if
(
fdef
->
filter
&&
fdef
->
filter
->
shutdown
)
{
fdef
->
filter
->
shutdown
(
fdef
->
filter
);
fdef
->
initialized
=
false
;
}
static
void
git_filter_global_shutdown
(
void
);
git__free
(
fdef
->
filter_name
);
git__free
(
fdef
->
attrdata
);
git__free
(
fdef
);
}
git_vector_free
(
&
reg
->
filters
);
git__free
(
reg
);
}
static
int
filter_registry_initialize
(
void
)
{
int
error
=
0
;
struct
filter_registry
*
reg
;
if
(
git__filter_registry
)
return
0
;
reg
=
git__calloc
(
1
,
sizeof
(
struct
filter_registry
));
GITERR_CHECK_ALLOC
(
reg
);
if
((
error
=
git_vector_init
(
&
reg
->
filters
,
2
,
filter_def_priority_cmp
))
<
0
)
goto
cleanup
;
reg
=
git__compare_and_swap
(
&
git__filter_registry
,
NULL
,
reg
);
if
(
reg
!=
NULL
)
goto
cleanup
;
git__on_shutdown
(
filter_registry_shutdown
);
/* try to register both default filters */
{
git_filter
*
crlf
=
git_crlf_filter_new
();
git_filter
*
ident
=
git_ident_filter_new
();
if
(
crlf
&&
git_filter_register
(
GIT_FILTER_CRLF
,
crlf
,
GIT_FILTER_CRLF_PRIORITY
)
<
0
)
crlf
=
NULL
;
if
(
ident
&&
git_filter_register
(
GIT_FILTER_IDENT
,
ident
,
GIT_FILTER_IDENT_PRIORITY
)
<
0
)
ident
=
NULL
;
if
(
!
crlf
||
!
ident
)
return
-
1
;
}
return
0
;
cleanup:
git_vector_free
(
&
reg
->
filters
);
git__free
(
reg
);
return
error
;
}
static
int
filter_def_scan_attrs
(
git_buf
*
attrs
,
size_t
*
nattr
,
size_t
*
nmatch
,
const
char
*
attr_str
)
...
...
@@ -210,40 +145,14 @@ static int filter_def_filter_key_check(const void *key, const void *fdef)
return
(
key
==
filter
)
?
0
:
-
1
;
}
static
int
filter_registry_find
(
size_t
*
pos
,
const
char
*
name
)
{
return
git_vector_search2
(
pos
,
&
git__filter_registry
->
filters
,
filter_def_name_key_check
,
name
);
}
static
git_filter_def
*
filter_registry_lookup
(
size_t
*
pos
,
const
char
*
name
)
{
git_filter_def
*
fdef
=
NULL
;
if
(
!
filter_registry_find
(
pos
,
name
))
fdef
=
git_vector_get
(
&
git__filter_registry
->
filters
,
*
pos
);
return
fdef
;
}
int
git_filter_register
(
/* Note: callers must lock the registry before calling this function */
static
int
filter_registry_insert
(
const
char
*
name
,
git_filter
*
filter
,
int
priority
)
{
git_filter_def
*
fdef
;
size_t
nattr
=
0
,
nmatch
=
0
,
alloc_len
;
git_buf
attrs
=
GIT_BUF_INIT
;
assert
(
name
&&
filter
);
if
(
filter_registry_initialize
()
<
0
)
return
-
1
;
if
(
!
filter_registry_find
(
NULL
,
name
))
{
giterr_set
(
GITERR_FILTER
,
"Attempt to reregister existing filter '%s'"
,
name
);
return
GIT_EEXISTS
;
}
if
(
filter_def_scan_attrs
(
&
attrs
,
&
nattr
,
&
nmatch
,
filter
->
attributes
)
<
0
)
return
-
1
;
...
...
@@ -265,21 +174,123 @@ int git_filter_register(
filter_def_set_attrs
(
fdef
);
if
(
git_vector_insert
(
&
git__filter_registry
->
filters
,
fdef
)
<
0
)
{
if
(
git_vector_insert
(
&
filter_registry
.
filters
,
fdef
)
<
0
)
{
git__free
(
fdef
->
filter_name
);
git__free
(
fdef
->
attrdata
);
git__free
(
fdef
);
return
-
1
;
}
git_vector_sort
(
&
git__filter_registry
->
filters
);
git_vector_sort
(
&
filter_registry
.
filters
);
return
0
;
}
int
git_filter_global_init
(
void
)
{
git_filter
*
crlf
=
NULL
,
*
ident
=
NULL
;
int
error
=
0
;
if
(
git_rwlock_init
(
&
filter_registry
.
lock
)
<
0
)
return
-
1
;
if
((
error
=
git_vector_init
(
&
filter_registry
.
filters
,
2
,
filter_def_priority_cmp
))
<
0
)
goto
done
;
if
((
crlf
=
git_crlf_filter_new
())
==
NULL
||
filter_registry_insert
(
GIT_FILTER_CRLF
,
crlf
,
GIT_FILTER_CRLF_PRIORITY
)
<
0
||
(
ident
=
git_ident_filter_new
())
==
NULL
||
filter_registry_insert
(
GIT_FILTER_IDENT
,
ident
,
GIT_FILTER_IDENT_PRIORITY
)
<
0
)
error
=
-
1
;
git__on_shutdown
(
git_filter_global_shutdown
);
done:
if
(
error
)
{
git_filter_free
(
crlf
);
git_filter_free
(
ident
);
}
return
error
;
}
static
void
git_filter_global_shutdown
(
void
)
{
size_t
pos
;
git_filter_def
*
fdef
;
if
(
git_rwlock_wrlock
(
&
filter_registry
.
lock
)
<
0
)
return
;
git_vector_foreach
(
&
filter_registry
.
filters
,
pos
,
fdef
)
{
if
(
fdef
->
filter
&&
fdef
->
filter
->
shutdown
)
{
fdef
->
filter
->
shutdown
(
fdef
->
filter
);
fdef
->
initialized
=
false
;
}
git__free
(
fdef
->
filter_name
);
git__free
(
fdef
->
attrdata
);
git__free
(
fdef
);
}
git_vector_free
(
&
filter_registry
.
filters
);
git_rwlock_wrunlock
(
&
filter_registry
.
lock
);
git_rwlock_free
(
&
filter_registry
.
lock
);
}
/* Note: callers must lock the registry before calling this function */
static
int
filter_registry_find
(
size_t
*
pos
,
const
char
*
name
)
{
return
git_vector_search2
(
pos
,
&
filter_registry
.
filters
,
filter_def_name_key_check
,
name
);
}
/* Note: callers must lock the registry before calling this function */
static
git_filter_def
*
filter_registry_lookup
(
size_t
*
pos
,
const
char
*
name
)
{
git_filter_def
*
fdef
=
NULL
;
if
(
!
filter_registry_find
(
pos
,
name
))
fdef
=
git_vector_get
(
&
filter_registry
.
filters
,
*
pos
);
return
fdef
;
}
int
git_filter_register
(
const
char
*
name
,
git_filter
*
filter
,
int
priority
)
{
int
error
;
assert
(
name
&&
filter
);
if
(
git_rwlock_wrlock
(
&
filter_registry
.
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"failed to lock filter registry"
);
return
-
1
;
}
if
(
!
filter_registry_find
(
NULL
,
name
))
{
giterr_set
(
GITERR_FILTER
,
"attempt to reregister existing filter '%s'"
,
name
);
error
=
GIT_EEXISTS
;
goto
done
;
}
error
=
filter_registry_insert
(
name
,
filter
,
priority
);
done:
git_rwlock_wrunlock
(
&
filter_registry
.
lock
);
return
error
;
}
int
git_filter_unregister
(
const
char
*
name
)
{
size_t
pos
;
git_filter_def
*
fdef
;
int
error
=
0
;
assert
(
name
);
...
...
@@ -289,12 +300,18 @@ int git_filter_unregister(const char *name)
return
-
1
;
}
if
(
git_rwlock_wrlock
(
&
filter_registry
.
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"failed to lock filter registry"
);
return
-
1
;
}
if
((
fdef
=
filter_registry_lookup
(
&
pos
,
name
))
==
NULL
)
{
giterr_set
(
GITERR_FILTER
,
"Cannot find filter '%s' to unregister"
,
name
);
return
GIT_ENOTFOUND
;
error
=
GIT_ENOTFOUND
;
goto
done
;
}
(
void
)
git_vector_remove
(
&
git__filter_registry
->
filters
,
pos
);
git_vector_remove
(
&
filter_registry
.
filters
,
pos
);
if
(
fdef
->
initialized
&&
fdef
->
filter
&&
fdef
->
filter
->
shutdown
)
{
fdef
->
filter
->
shutdown
(
fdef
->
filter
);
...
...
@@ -305,20 +322,17 @@ int git_filter_unregister(const char *name)
git__free
(
fdef
->
attrdata
);
git__free
(
fdef
);
return
0
;
done:
git_rwlock_wrunlock
(
&
filter_registry
.
lock
);
return
error
;
}
static
int
filter_initialize
(
git_filter_def
*
fdef
)
{
int
error
=
0
;
if
(
!
fdef
->
initialized
&&
fdef
->
filter
&&
fdef
->
filter
->
initialize
&&
(
error
=
fdef
->
filter
->
initialize
(
fdef
->
filter
))
<
0
)
{
/* auto-unregister if initialize fails */
git_filter_unregister
(
fdef
->
filter_name
);
if
(
!
fdef
->
initialized
&&
fdef
->
filter
&&
fdef
->
filter
->
initialize
)
{
if
((
error
=
fdef
->
filter
->
initialize
(
fdef
->
filter
))
<
0
)
return
error
;
}
...
...
@@ -330,17 +344,22 @@ git_filter *git_filter_lookup(const char *name)
{
size_t
pos
;
git_filter_def
*
fdef
;
git_filter
*
filter
=
NULL
;
if
(
filter_registry_initialize
()
<
0
)
if
(
git_rwlock_rdlock
(
&
filter_registry
.
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"failed to lock filter registry"
);
return
NULL
;
}
if
((
fdef
=
filter_registry_lookup
(
&
pos
,
name
))
==
NULL
)
return
NULL
;
if
((
fdef
=
filter_registry_lookup
(
&
pos
,
name
))
==
NULL
||
(
!
fdef
->
initialized
&&
filter_initialize
(
fdef
)
<
0
))
goto
done
;
if
(
!
fdef
->
initialized
&&
filter_initialize
(
fdef
)
<
0
)
return
NULL
;
filter
=
fdef
->
filter
;
return
fdef
->
filter
;
done:
git_rwlock_rdunlock
(
&
filter_registry
.
lock
);
return
filter
;
}
void
git_filter_free
(
git_filter
*
filter
)
...
...
@@ -478,8 +497,10 @@ int git_filter_list__load_ext(
size_t
idx
;
git_filter_def
*
fdef
;
if
(
filter_registry_initialize
()
<
0
)
if
(
git_rwlock_rdlock
(
&
filter_registry
.
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"failed to lock filter registry"
);
return
-
1
;
}
src
.
repo
=
repo
;
src
.
path
=
path
;
...
...
@@ -489,7 +510,7 @@ int git_filter_list__load_ext(
if
(
blob
)
git_oid_cpy
(
&
src
.
oid
,
git_blob_id
(
blob
));
git_vector_foreach
(
&
git__filter_registry
->
filters
,
idx
,
fdef
)
{
git_vector_foreach
(
&
filter_registry
.
filters
,
idx
,
fdef
)
{
const
char
**
values
=
NULL
;
void
*
payload
=
NULL
;
...
...
@@ -523,7 +544,7 @@ int git_filter_list__load_ext(
else
{
if
(
!
fl
)
{
if
((
error
=
filter_list_new
(
&
fl
,
&
src
))
<
0
)
return
error
;
break
;
fl
->
temp_buf
=
filter_opts
->
temp_buf
;
}
...
...
@@ -537,6 +558,8 @@ int git_filter_list__load_ext(
}
}
git_rwlock_rdunlock
(
&
filter_registry
.
lock
);
if
(
error
&&
fl
!=
NULL
)
{
git_array_clear
(
fl
->
filters
);
git__free
(
fl
);
...
...
@@ -604,20 +627,28 @@ int git_filter_list_push(
{
int
error
=
0
;
size_t
pos
;
git_filter_def
*
fdef
;
git_filter_def
*
fdef
=
NULL
;
git_filter_entry
*
fe
;
assert
(
fl
&&
filter
);
if
(
git_rwlock_rdlock
(
&
filter_registry
.
lock
)
<
0
)
{
giterr_set
(
GITERR_OS
,
"failed to lock filter registry"
);
return
-
1
;
}
if
(
git_vector_search2
(
&
pos
,
&
git__filter_registry
->
filters
,
filter_def_filter_key_check
,
filter
)
<
0
)
{
&
pos
,
&
filter_registry
.
filters
,
filter_def_filter_key_check
,
filter
)
==
0
)
fdef
=
git_vector_get
(
&
filter_registry
.
filters
,
pos
);
git_rwlock_rdunlock
(
&
filter_registry
.
lock
);
if
(
fdef
==
NULL
)
{
giterr_set
(
GITERR_FILTER
,
"Cannot use an unregistered filter"
);
return
-
1
;
}
fdef
=
git_vector_get
(
&
git__filter_registry
->
filters
,
pos
);
if
(
!
fdef
->
initialized
&&
(
error
=
filter_initialize
(
fdef
))
<
0
)
return
error
;
...
...
This diff is collapsed.
Click to expand it.
src/filter.h
View file @
78e16c34
...
...
@@ -32,6 +32,8 @@ typedef struct {
#define GIT_FILTER_OPTIONS_INIT {0}
extern
int
git_filter_global_init
(
void
);
extern
void
git_filter_free
(
git_filter
*
filter
);
extern
int
git_filter_list__load_ext
(
...
...
This diff is collapsed.
Click to expand it.
src/global.c
View file @
78e16c34
...
...
@@ -8,9 +8,11 @@
#include "global.h"
#include "hash.h"
#include "sysdir.h"
#include "
git2/global
.h"
#include "
git2/sys/openssl
.h"
#include "
filter
.h"
#include "
openssl_stream
.h"
#include "thread-utils.h"
#include "git2/global.h"
#if defined(GIT_MSVC_CRTDBG)
#include "win32/w32_stack.h"
#include "win32/w32_crtdbg_stacktrace.h"
...
...
@@ -49,118 +51,48 @@ static void git__global_state_cleanup(git_global_st *st)
st
->
error_t
.
message
=
NULL
;
}
static
void
git__shutdown
(
void
)
{
int
pos
;
/* Shutdown subsystems that have registered */
for
(
pos
=
git_atomic_get
(
&
git__n_shutdown_callbacks
);
pos
>
0
;
pos
=
git_atomic_dec
(
&
git__n_shutdown_callbacks
))
{
git_global_shutdown_fn
cb
=
git__swap
(
git__shutdown_callbacks
[
pos
-
1
],
NULL
);
if
(
cb
!=
NULL
)
cb
();
}
}
#if defined(GIT_THREADS) && defined(GIT_OPENSSL)
void
openssl_locking_function
(
int
mode
,
int
n
,
const
char
*
file
,
int
line
)
static
int
init_common
(
void
)
{
int
lock
;
GIT_UNUSED
(
file
);
GIT_UNUSED
(
line
);
lock
=
mode
&
CRYPTO_LOCK
;
if
(
lock
)
{
git_mutex_lock
(
&
openssl_locks
[
n
]);
}
else
{
git_mutex_unlock
(
&
openssl_locks
[
n
]);
}
}
static
void
shutdown_ssl_locking
(
void
)
{
int
num_locks
,
i
;
num_locks
=
CRYPTO_num_locks
();
CRYPTO_set_locking_callback
(
NULL
);
int
ret
;
for
(
i
=
0
;
i
<
num_locks
;
++
i
)
git_mutex_free
(
openssl_locks
);
git_
_free
(
openssl_locks
);
}
/* Initialize the CRT debug allocator first, before our first malloc */
#if defined(GIT_MSVC_CRTDBG)
git_
win32__crtdbg_stacktrace_init
(
);
git_win32__stack_init
();
#endif
static
void
init_ssl
(
void
)
{
#ifdef GIT_OPENSSL
long
ssl_opts
=
SSL_OP_NO_SSLv2
|
SSL_OP_NO_SSLv3
;
/* Initialize any other subsystems that have global state */
if
((
ret
=
git_hash_global_init
())
==
0
&&
(
ret
=
git_sysdir_global_init
())
==
0
&&
(
ret
=
git_filter_global_init
())
==
0
)
ret
=
git_openssl_stream_global_init
();
/* Older OpenSSL and MacOS OpenSSL doesn't have this */
#ifdef SSL_OP_NO_COMPRESSION
ssl_opts
|=
SSL_OP_NO_COMPRESSION
;
#endif
GIT_MEMORY_BARRIER
;
SSL_load_error_strings
();
OpenSSL_add_ssl_algorithms
();
/*
* Load SSLv{2,3} and TLSv1 so that we can talk with servers
* which use the SSL hellos, which are often used for
* compatibility. We then disable SSL so we only allow OpenSSL
* to speak TLSv1 to perform the encryption itself.
*/
git__ssl_ctx
=
SSL_CTX_new
(
SSLv23_method
());
SSL_CTX_set_options
(
git__ssl_ctx
,
ssl_opts
);
SSL_CTX_set_mode
(
git__ssl_ctx
,
SSL_MODE_AUTO_RETRY
);
SSL_CTX_set_verify
(
git__ssl_ctx
,
SSL_VERIFY_NONE
,
NULL
);
if
(
!
SSL_CTX_set_default_verify_paths
(
git__ssl_ctx
))
{
SSL_CTX_free
(
git__ssl_ctx
);
git__ssl_ctx
=
NULL
;
}
#endif
return
ret
;
}
/**
* This function aims to clean-up the SSL context which
* we allocated.
*/
static
void
uninit_ssl
(
void
)
static
void
shutdown_common
(
void
)
{
#ifdef GIT_OPENSSL
if
(
git__ssl_ctx
)
{
SSL_CTX_free
(
git__ssl_ctx
);
git__ssl_ctx
=
NULL
;
}
#endif
}
int
pos
;
int
git_openssl_set_locking
(
void
)
{
#ifdef GIT_OPENSSL
# ifdef GIT_THREADS
int
num_locks
,
i
;
/* Shutdown subsystems that have registered */
for
(
pos
=
git_atomic_get
(
&
git__n_shutdown_callbacks
);
pos
>
0
;
pos
=
git_atomic_dec
(
&
git__n_shutdown_callbacks
))
{
num_locks
=
CRYPTO_num_locks
();
openssl_locks
=
git__calloc
(
num_locks
,
sizeof
(
git_mutex
));
GITERR_CHECK_ALLOC
(
openssl_locks
);
git_global_shutdown_fn
cb
=
git__swap
(
git__shutdown_callbacks
[
pos
-
1
],
NULL
);
for
(
i
=
0
;
i
<
num_locks
;
i
++
)
{
if
(
git_mutex_init
(
&
openssl_locks
[
i
])
!=
0
)
{
giterr_set
(
GITERR_SSL
,
"failed to initialize openssl locks"
);
return
-
1
;
}
if
(
cb
!=
NULL
)
cb
();
}
CRYPTO_set_locking_callback
(
openssl_locking_function
);
git__on_shutdown
(
shutdown_ssl_locking
);
return
0
;
# else
giterr_set
(
GITERR_THREAD
,
"libgit2 as not built with threads"
);
return
-
1
;
# endif
#else
giterr_set
(
GITERR_SSL
,
"libgit2 was not built with OpenSSL support"
);
return
-
1
;
git__free
(
git__user_agent
);
#if defined(GIT_MSVC_CRTDBG)
git_win32__crtdbg_stacktrace_cleanup
();
git_win32__stack_cleanup
();
#endif
}
...
...
@@ -208,14 +140,13 @@ static int synchronized_threads_init(void)
int
error
;
_tls_index
=
TlsAlloc
();
win32_pthread_initialize
();
if
(
git_mutex_init
(
&
git__mwindow_mutex
))
return
-
1
;
/* Initialize any other subsystems that have global state */
if
((
error
=
git_hash_global_init
())
>=
0
)
error
=
git_sysdir_global_init
();
win32_pthread_initialize
();
error
=
init_common
();
return
error
;
}
...
...
@@ -229,11 +160,6 @@ int git_libgit2_init(void)
/* Only do work on a 0 -> 1 transition of the refcount */
if
((
ret
=
git_atomic_inc
(
&
git__n_inits
))
==
1
)
{
#if defined(GIT_MSVC_CRTDBG)
git_win32__crtdbg_stacktrace_init
();
git_win32__stack_init
();
#endif
if
(
synchronized_threads_init
()
<
0
)
ret
=
-
1
;
}
...
...
@@ -244,17 +170,6 @@ int git_libgit2_init(void)
return
ret
;
}
static
void
synchronized_threads_shutdown
(
void
)
{
/* Shut down any subsystems that have global state */
git__shutdown
();
git__free_tls_data
();
TlsFree
(
_tls_index
);
git_mutex_free
(
&
git__mwindow_mutex
);
}
int
git_libgit2_shutdown
(
void
)
{
int
ret
;
...
...
@@ -264,14 +179,12 @@ int git_libgit2_shutdown(void)
/* Only do work on a 1 -> 0 transition of the refcount */
if
((
ret
=
git_atomic_dec
(
&
git__n_inits
))
==
0
)
{
s
ynchronized_threads_shutdow
n
();
s
hutdown_commo
n
();
#if defined(GIT_MSVC_CRTDBG)
git_win32__crtdbg_stacktrace_cleanup
();
git_win32__stack_cleanup
();
#endif
git__free_tls_data
();
git__free
(
git__user_agent
);
TlsFree
(
_tls_index
);
git_mutex_free
(
&
git__mwindow_mutex
);
}
/* Exit the lock */
...
...
@@ -331,17 +244,10 @@ static void init_once(void)
{
if
((
init_error
=
git_mutex_init
(
&
git__mwindow_mutex
))
!=
0
)
return
;
pthread_key_create
(
&
_tls_key
,
&
cb__free_status
);
pthread_key_create
(
&
_tls_key
,
&
cb__free_status
);
/* Initialize any other subsystems that have global state */
if
((
init_error
=
git_hash_global_init
())
>=
0
)
init_error
=
git_sysdir_global_init
();
/* OpenSSL needs to be initialized from the main thread */
init_ssl
();
GIT_MEMORY_BARRIER
;
init_error
=
init_common
();
}
int
git_libgit2_init
(
void
)
...
...
@@ -364,15 +270,13 @@ int git_libgit2_shutdown(void)
return
ret
;
/* Shut down any subsystems that have global state */
git__shutdown
();
uninit_ssl
();
shutdown_common
();
ptr
=
pthread_getspecific
(
_tls_key
);
pthread_setspecific
(
_tls_key
,
NULL
);
git__global_state_cleanup
(
ptr
);
git__free
(
ptr
);
git__free
(
git__user_agent
);
pthread_key_delete
(
_tls_key
);
git_mutex_free
(
&
git__mwindow_mutex
);
...
...
@@ -405,15 +309,16 @@ static git_global_st __state;
int
git_libgit2_init
(
void
)
{
static
int
ssl_inited
=
0
;
int
ret
;
if
(
!
ssl_inited
)
{
init_ssl
();
ssl_inited
=
1
;
}
/* Only init SSL the first time */
if
((
ret
=
git_atomic_inc
(
&
git__n_inits
))
!=
1
)
return
ret
;
git_buf_init
(
&
__state
.
error_buf
,
0
);
return
git_atomic_inc
(
&
git__n_inits
);
if
((
ret
=
init_common
())
<
0
)
return
ret
;
return
1
;
}
int
git_libgit2_shutdown
(
void
)
...
...
@@ -421,15 +326,12 @@ int git_libgit2_shutdown(void)
int
ret
;
/* Shut down any subsystems that have global state */
if
((
ret
=
git_atomic_dec
(
&
git__n_inits
))
!=
0
)
return
ret
;
git__shutdown
();
if
((
ret
=
git_atomic_dec
(
&
git__n_inits
))
==
0
)
{
shutdown_common
();
git__global_state_cleanup
(
&
__state
);
uninit_ssl
();
git__free
(
git__user_agent
);
}
return
0
;
return
ret
;
}
git_global_st
*
git__global_state
(
void
)
...
...
This diff is collapsed.
Click to expand it.
src/openssl_stream.c
View file @
78e16c34
...
...
@@ -31,6 +31,115 @@
#include <openssl/x509v3.h>
#include <openssl/bio.h>
SSL_CTX
*
git__ssl_ctx
;
#ifdef GIT_THREADS
static
git_mutex
*
openssl_locks
;
static
void
openssl_locking_function
(
int
mode
,
int
n
,
const
char
*
file
,
int
line
)
{
int
lock
;
GIT_UNUSED
(
file
);
GIT_UNUSED
(
line
);
lock
=
mode
&
CRYPTO_LOCK
;
if
(
lock
)
{
git_mutex_lock
(
&
openssl_locks
[
n
]);
}
else
{
git_mutex_unlock
(
&
openssl_locks
[
n
]);
}
}
static
void
shutdown_ssl_locking
(
void
)
{
int
num_locks
,
i
;
num_locks
=
CRYPTO_num_locks
();
CRYPTO_set_locking_callback
(
NULL
);
for
(
i
=
0
;
i
<
num_locks
;
++
i
)
git_mutex_free
(
openssl_locks
);
git__free
(
openssl_locks
);
}
#endif
/* GIT_THREADS */
/**
* This function aims to clean-up the SSL context which
* we allocated.
*/
static
void
shutdown_ssl
(
void
)
{
if
(
git__ssl_ctx
)
{
SSL_CTX_free
(
git__ssl_ctx
);
git__ssl_ctx
=
NULL
;
}
}
int
git_openssl_stream_global_init
(
void
)
{
#ifdef GIT_OPENSSL
long
ssl_opts
=
SSL_OP_NO_SSLv2
|
SSL_OP_NO_SSLv3
;
/* Older OpenSSL and MacOS OpenSSL doesn't have this */
#ifdef SSL_OP_NO_COMPRESSION
ssl_opts
|=
SSL_OP_NO_COMPRESSION
;
#endif
SSL_load_error_strings
();
OpenSSL_add_ssl_algorithms
();
/*
* Load SSLv{2,3} and TLSv1 so that we can talk with servers
* which use the SSL hellos, which are often used for
* compatibility. We then disable SSL so we only allow OpenSSL
* to speak TLSv1 to perform the encryption itself.
*/
git__ssl_ctx
=
SSL_CTX_new
(
SSLv23_method
());
SSL_CTX_set_options
(
git__ssl_ctx
,
ssl_opts
);
SSL_CTX_set_mode
(
git__ssl_ctx
,
SSL_MODE_AUTO_RETRY
);
SSL_CTX_set_verify
(
git__ssl_ctx
,
SSL_VERIFY_NONE
,
NULL
);
if
(
!
SSL_CTX_set_default_verify_paths
(
git__ssl_ctx
))
{
SSL_CTX_free
(
git__ssl_ctx
);
git__ssl_ctx
=
NULL
;
return
-
1
;
}
#endif
git__on_shutdown
(
shutdown_ssl
);
return
0
;
}
int
git_openssl_set_locking
(
void
)
{
#ifdef GIT_THREADS
int
num_locks
,
i
;
num_locks
=
CRYPTO_num_locks
();
openssl_locks
=
git__calloc
(
num_locks
,
sizeof
(
git_mutex
));
GITERR_CHECK_ALLOC
(
openssl_locks
);
for
(
i
=
0
;
i
<
num_locks
;
i
++
)
{
if
(
git_mutex_init
(
&
openssl_locks
[
i
])
!=
0
)
{
giterr_set
(
GITERR_SSL
,
"failed to initialize openssl locks"
);
return
-
1
;
}
}
CRYPTO_set_locking_callback
(
openssl_locking_function
);
git__on_shutdown
(
shutdown_ssl_locking
);
return
0
;
#else
giterr_set
(
GITERR_THREAD
,
"libgit2 as not built with threads"
);
return
-
1
;
#endif
}
static
int
bio_create
(
BIO
*
b
)
{
b
->
init
=
1
;
...
...
@@ -472,6 +581,17 @@ int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
#include "stream.h"
int
git_openssl_stream_global_init
(
void
)
{
return
0
;
}
int
git_openssl_set_locking
(
void
)
{
giterr_set
(
GITERR_SSL
,
"libgit2 was not built with OpenSSL support"
);
return
-
1
;
}
int
git_openssl_stream_new
(
git_stream
**
out
,
const
char
*
host
,
const
char
*
port
)
{
GIT_UNUSED
(
out
);
...
...
This diff is collapsed.
Click to expand it.
src/openssl_stream.h
View file @
78e16c34
...
...
@@ -9,6 +9,8 @@
#include "git2/sys/stream.h"
extern
int
git_openssl_stream_global_init
(
void
);
extern
int
git_openssl_stream_new
(
git_stream
**
out
,
const
char
*
host
,
const
char
*
port
);
#endif
This diff is collapsed.
Click to expand it.
src/thread-utils.h
View file @
78e16c34
...
...
@@ -275,7 +275,7 @@ GIT_INLINE(int) git_atomic_get(git_atomic *a)
extern
int
git_online_cpus
(
void
);
#if defined(GIT_THREADS) && defined(
GIT_WIN32
)
#if defined(GIT_THREADS) && defined(
_MSC_VER
)
# define GIT_MEMORY_BARRIER MemoryBarrier()
#elif defined(GIT_THREADS)
# define GIT_MEMORY_BARRIER __sync_synchronize()
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment