Skip to content

Commit

Permalink
Constrain mkdir calls to avoid extra mkdirs
Browse files Browse the repository at this point in the history
This updates the calls that make the subdirectories for objects
to use a base directory above which git_futils_mkdir won't walk
any higher.  This prevents attempts to mkdir all the way up to
the root of the filesystem.

Also, this moves the objects_dir into the loose backend structure
and removes the separate allocation, plus does some preformatting
of the objects_dir value to guarantee a trailing slash, etc.
  • Loading branch information
arrbee committed Jun 23, 2013
1 parent 5d669f0 commit 8294e8c
Showing 1 changed file with 30 additions and 16 deletions.
46 changes: 30 additions & 16 deletions src/odb_loose.c
Expand Up @@ -33,7 +33,9 @@ typedef struct loose_backend {

int object_zlib_level; /** loose object zlib compression level. */
int fsync_object_files; /** loose object file fsync flag. */
char *objects_dir;

size_t objects_dirlen;
char objects_dir[GIT_FLEX_ARRAY];
} loose_backend;

/* State structure for exploring directories,
Expand All @@ -56,24 +58,30 @@ typedef struct {
*
***********************************************************/

static int object_file_name(git_buf *name, const char *dir, const git_oid *id)
static int object_file_name(
git_buf *name, const loose_backend *be, const git_oid *id)
{
git_buf_sets(name, dir);

/* expand length for 40 hex sha1 chars + 2 * '/' + '\0' */
if (git_buf_grow(name, git_buf_len(name) + GIT_OID_HEXSZ + 3) < 0)
/* expand length for object root + 40 hex sha1 chars + 2 * '/' + '\0' */
if (git_buf_grow(name, be->objects_dirlen + GIT_OID_HEXSZ + 3) < 0)
return -1;

git_buf_set(name, be->objects_dir, be->objects_dirlen);
git_path_to_dir(name);

/* loose object filename: aa/aaa... (41 bytes) */
git_oid_pathfmt(name->ptr + git_buf_len(name), id);
git_oid_pathfmt(name->ptr + name->size, id);
name->size += GIT_OID_HEXSZ + 1;
name->ptr[name->size] = '\0';

return 0;
}

static int object_mkdir(const git_buf *name, const loose_backend *be)
{
return git_futils_mkdir(
name->ptr + be->objects_dirlen, be->objects_dir, GIT_OBJECT_DIR_MODE,
GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR);
}

static size_t get_binary_object_header(obj_hdr *hdr, git_buf *obj)
{
Expand Down Expand Up @@ -457,7 +465,7 @@ static int locate_object(
loose_backend *backend,
const git_oid *oid)
{
int error = object_file_name(object_location, backend->objects_dir, oid);
int error = object_file_name(object_location, backend, oid);

if (!error && !git_path_exists(object_location->ptr))
return GIT_ENOTFOUND;
Expand Down Expand Up @@ -769,8 +777,8 @@ static int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream)
int error = 0;

if (git_filebuf_hash(oid, &stream->fbuf) < 0 ||
object_file_name(&final_path, backend->objects_dir, oid) < 0 ||
git_futils_mkpath2file(final_path.ptr, GIT_OBJECT_DIR_MODE) < 0)
object_file_name(&final_path, backend, oid) < 0 ||
object_mkdir(&final_path, backend) < 0)
error = -1;
/*
* Don't try to add an existing object to the repository. This
Expand Down Expand Up @@ -880,8 +888,8 @@ static int loose_backend__write(git_oid *oid, git_odb_backend *_backend, const v
git_filebuf_write(&fbuf, header, header_len);
git_filebuf_write(&fbuf, data, len);

if (object_file_name(&final_path, backend->objects_dir, oid) < 0 ||
git_futils_mkpath2file(final_path.ptr, GIT_OBJECT_DIR_MODE) < 0 ||
if (object_file_name(&final_path, backend, oid) < 0 ||
object_mkdir(&final_path, backend) < 0 ||
git_filebuf_commit_at(&fbuf, final_path.ptr, GIT_OBJECT_FILE_MODE) < 0)
error = -1;

Expand All @@ -898,7 +906,6 @@ static void loose_backend__free(git_odb_backend *_backend)
assert(_backend);
backend = (loose_backend *)_backend;

git__free(backend->objects_dir);
git__free(backend);
}

Expand All @@ -909,13 +916,20 @@ int git_odb_backend_loose(
int do_fsync)
{
loose_backend *backend;
size_t objects_dirlen;

assert(backend_out && objects_dir);

objects_dirlen = strlen(objects_dir);

backend = git__calloc(1, sizeof(loose_backend));
backend = git__calloc(1, sizeof(loose_backend) + objects_dirlen + 2);
GITERR_CHECK_ALLOC(backend);

backend->parent.version = GIT_ODB_BACKEND_VERSION;
backend->objects_dir = git__strdup(objects_dir);
GITERR_CHECK_ALLOC(backend->objects_dir);
backend->objects_dirlen = objects_dirlen;
memcpy(backend->objects_dir, objects_dir, objects_dirlen);
if (backend->objects_dir[backend->objects_dirlen - 1] != '/')
backend->objects_dir[backend->objects_dirlen++] = '/';

if (compression_level < 0)
compression_level = Z_BEST_SPEED;
Expand Down

0 comments on commit 8294e8c

Please sign in to comment.