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
Feb 19, 2016
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
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
370 additions
and
304 deletions
+370
-304
include/git2/sys/filter.h
+34
-25
src/filter.c
+155
-124
src/filter.h
+2
-0
src/global.c
+56
-154
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
;
};
...
...
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
;
}
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
;
static
void
git_filter_global_shutdown
(
void
);
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,21 +322,18 @@ 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
);
return
error
;
if
(
!
fdef
->
initialized
&&
fdef
->
filter
&&
fdef
->
filter
->
initialize
)
{
if
((
error
=
fdef
->
filter
->
initialize
(
fdef
->
filter
))
<
0
)
return
error
;
}
fdef
->
initialized
=
true
;
...
...
@@ -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
;
...
...
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
(
...
...
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
);
/* 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
();
pthread_key_create
(
&
_tls_key
,
&
cb__free_status
);
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
;
if
((
ret
=
init_common
())
<
0
)
return
ret
;
git_buf_init
(
&
__state
.
error_buf
,
0
);
return
git_atomic_inc
(
&
git__n_inits
);
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
();
git__global_state_cleanup
(
&
__state
);
uninit_ssl
();
git__free
(
git__user_agent
);
if
((
ret
=
git_atomic_dec
(
&
git__n_inits
))
==
0
)
{
shutdown_common
();
git__global_state_cleanup
(
&
__state
);
}
return
0
;
return
ret
;
}
git_global_st
*
git__global_state
(
void
)
...
...
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
);
...
...
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
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()
...
...
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