summaryrefslogtreecommitdiff
path: root/src/signature.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/signature.c')
-rw-r--r--src/signature.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/src/signature.c b/src/signature.c
index 0c99755d4..e8014620a 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -65,14 +65,47 @@ git_signature *git_signature_dup(const git_signature *sig)
return git_signature_new(sig->name, sig->email, sig->when.time, sig->when.offset);
}
+git_signature *git_signature_now(const char *name, const char *email)
+{
+ time_t now;
+ time_t offset;
+ struct tm *utc_tm, *local_tm;
+
+#ifndef GIT_WIN32
+ struct tm _utc, _local;
+#endif
+
+ time(&now);
+
+ /**
+ * On Win32, `gmtime_r` doesn't exist but
+ * `gmtime` is threadsafe, so we can use that
+ */
+#ifdef GIT_WIN32
+ utc_tm = gmtime(&now);
+ local_tm = localtime(&now);
+#else
+ utc_tm = gmtime_r(&now, &_utc);
+ local_tm = localtime_r(&now, &_local);
+#endif
+
+ offset = mktime(local_tm) - mktime(utc_tm);
+ offset /= 60;
+
+ /* mktime takes care of setting tm_isdst correctly */
+ if (local_tm->tm_isdst)
+ offset += 60;
+
+ return git_signature_new(name, email, now, (int)offset);
+}
-static int parse_timezone_offset(const char *buffer, int *offset_out)
+static int parse_timezone_offset(const char *buffer, long *offset_out)
{
- int offset, dec_offset;
+ long offset, dec_offset;
int mins, hours;
- const char* offset_start;
- char* offset_end;
+ const char *offset_start;
+ const char *offset_end;
offset_start = buffer + 1;
@@ -84,7 +117,8 @@ static int parse_timezone_offset(const char *buffer, int *offset_out)
if (offset_start[0] != '-' && offset_start[0] != '+')
return GIT_EOBJCORRUPTED;
- dec_offset = strtol(offset_start + 1, &offset_end, 10);
+ if (git__strtol32(&dec_offset, offset_start + 1, &offset_end, 10) < GIT_SUCCESS)
+ return GIT_EOBJCORRUPTED;
if (offset_end - offset_start != 5)
return GIT_EOBJCORRUPTED;
@@ -117,7 +151,7 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
int name_length, email_length;
const char *buffer = *buffer_out;
const char *line_end, *name_end, *email_end;
- int offset = 0;
+ long offset = 0, time;
memset(sig, 0x0, sizeof(git_signature));
@@ -139,6 +173,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
name_length = name_end - buffer - 1;
sig->name = git__malloc(name_length + 1);
+ if (sig->name == NULL)
+ return GIT_ENOMEM;
+
memcpy(sig->name, buffer, name_length);
sig->name[name_length] = 0;
buffer = name_end + 1;
@@ -152,6 +189,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
email_length = email_end - buffer;
sig->email = git__malloc(email_length + 1);
+ if (sig->name == NULL)
+ return GIT_ENOMEM;
+
memcpy(sig->email, buffer, email_length);
sig->email[email_length] = 0;
buffer = email_end + 1;
@@ -159,11 +199,11 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
if (buffer >= line_end)
return GIT_EOBJCORRUPTED;
- sig->when.time = strtol(buffer, (char **)&buffer, 10);
-
- if (sig->when.time == 0)
+ if (git__strtol32(&time, buffer, &buffer, 10) < GIT_SUCCESS)
return GIT_EOBJCORRUPTED;
+ sig->when.time = (time_t)time;
+
if (parse_timezone_offset(buffer, &offset) < GIT_SUCCESS)
return GIT_EOBJCORRUPTED;