Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 231 lines (196 sloc) 5.686 kB
b0b267f trivial change
Patrick Haller authored
1 /*
2 * fuse + libgit2 = read-only mounting of bare repos
3 */
4
ebd97ad init
Patrick Haller authored
5 #include <fuse.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <fcntl.h>
917c3ab added debugging cleanup
Patrick Haller authored
10 #include <stdarg.h>
ebd97ad init
Patrick Haller authored
11 #include <git2.h>
12
9b4c5b8 pedantic includes issues
Patrick Haller authored
13 /* http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
14 */
15 #ifndef PATH_MAX
16 #include <linux/limits.h>
17 #endif
18
cec85b4 read-only appears to work
Patrick Haller authored
19 git_repository *g_repo = NULL;
20 git_tree *g_tree = NULL;
21 git_index *g_index = NULL;
22 git_odb *g_odb;
ebd97ad init
Patrick Haller authored
23
917c3ab added debugging cleanup
Patrick Haller authored
24 void debug(const char* format, ...) {
25 va_list args;
26 if (getenv("DEBUG") == NULL)
27 return;
28 va_start(args,format);
29 vfprintf(stderr, format, args);
30 va_end(args);
31 }
32
ebd97ad init
Patrick Haller authored
33 git_index_entry *git_index_entry_by_file(const char *path) {
34 unsigned int i, ecount;
917c3ab added debugging cleanup
Patrick Haller authored
35 debug( "git_index_entry_by_file for %s\n", path);
cec85b4 read-only appears to work
Patrick Haller authored
36 ecount = git_index_entrycount(g_index);
ebd97ad init
Patrick Haller authored
37 for (i = 0; i < ecount; ++i) {
cec85b4 read-only appears to work
Patrick Haller authored
38 git_index_entry *e = git_index_get(g_index, i);
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
39 //debug( " git_index_entry_by_file iterating over %s\n", e->path);
cec85b4 read-only appears to work
Patrick Haller authored
40
ebd97ad init
Patrick Haller authored
41 if (! strcmp(e->path, path) == 0)
42 continue;
43 return e;
44 }
45 return NULL;
46 }
47
3c2c6a4 added subdir handling
Patrick Haller authored
48 int is_dir(const char *path) {
49 int ecount, i;
50
51 debug("is_dir looking for '%s'\n", path);
52
53 if (strcmp(path, "") == 0) {
54 debug(" empty path is a dir, '%s'\n", path);
55 return 1;
56 }
57
58 ecount = git_index_entrycount(g_index);
59 for (i = 0; i < ecount; ++i) {
60 git_index_entry *e = git_index_get(g_index, i);
61 if (strncmp(path, e->path, strlen(path)) != 0) {
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
62 //debug(" path '%s' not a substring of '%s'\n", path, e->path);
3c2c6a4 added subdir handling
Patrick Haller authored
63 continue;
64 }
65 if (e->path[ strlen(path) ] == '/') {
66 debug(" prefix same, next char is slash for '%s' in '%s'\n", path, e->path);
67 return 1;
68 }
69 if (strcmp(path, e->path) == 0) {
70 debug("is_dir found file '%s'\n", e->path);
71 return 0;
72 }
73 }
74 debug("is_dir could not find path '%s'\n", path);
75 return 0;
76 }
77
ebd97ad init
Patrick Haller authored
78 int git_getattr(const char *path, struct stat *stbuf)
79 {
3c2c6a4 added subdir handling
Patrick Haller authored
80 path++;
cec85b4 read-only appears to work
Patrick Haller authored
81 memset(stbuf, 0, sizeof(struct stat));
3c2c6a4 added subdir handling
Patrick Haller authored
82 debug("getattr stripped to '%s'\n", path);
83 if ( is_dir(path) ) {
84 debug( "git_getattr for dir -> %s\n", path);
cec85b4 read-only appears to work
Patrick Haller authored
85 stbuf->st_mode = 0040755;
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
86 stbuf->st_nlink = 2;
cec85b4 read-only appears to work
Patrick Haller authored
87 stbuf->st_gid = 0;
88 stbuf->st_uid = 0;
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
89 stbuf->st_size = 4096;
cec85b4 read-only appears to work
Patrick Haller authored
90 return 0;
91 }
3c2c6a4 added subdir handling
Patrick Haller authored
92 debug( " get_attr not a dir %s\n", path);
ebd97ad init
Patrick Haller authored
93 git_index_entry *e;
94 if ( (e = git_index_entry_by_file(path)) == NULL)
917c3ab added debugging cleanup
Patrick Haller authored
95 return debug("path no exist? %s\n", path),-ENOENT;
ebd97ad init
Patrick Haller authored
96
97 stbuf->st_mode = e->mode;
98 stbuf->st_gid = e->gid;
99 stbuf->st_uid = e->uid;
100 stbuf->st_nlink = 1;
101 stbuf->st_size = e->file_size;
102 return 0;
103 }
104
105 int git_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
106 off_t offset, struct fuse_file_info *fi)
107 {
108 (void) offset;
109 (void) fi;
3c2c6a4 added subdir handling
Patrick Haller authored
110 int i, ecount = 0;
111 char dir[PATH_MAX], file[PATH_MAX], *p, *basename;
ebd97ad init
Patrick Haller authored
112
3c2c6a4 added subdir handling
Patrick Haller authored
113 path++; // drop initial slash
917c3ab added debugging cleanup
Patrick Haller authored
114 debug( "git_readdir for %s\n", path);
3c2c6a4 added subdir handling
Patrick Haller authored
115 memset(dir, 0, sizeof(dir));
cec85b4 read-only appears to work
Patrick Haller authored
116 ecount = git_index_entrycount(g_index);
117 for (i = 0; i < ecount; ++i) {
118 git_index_entry *e = git_index_get(g_index, i);
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
119 memset(file, 0, sizeof(file));
3c2c6a4 added subdir handling
Patrick Haller authored
120 strncpy(file, e->path, strlen(e->path)+1);
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
121 //debug( " readdir for '%s' got '%s' from epath '%s'\n",path, file, e->path);
3c2c6a4 added subdir handling
Patrick Haller authored
122 if (strncmp(path, file, strlen(path)) != 0 && strlen(path) != 0) {
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
123 //debug( " readdir path '%s' not init substring of '%s'\n",path, file);
3c2c6a4 added subdir handling
Patrick Haller authored
124 continue;
125 }
126 basename = (char *)file + strlen(path);
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
127
128 if ( strlen(path) > 0 && *basename != '/')
129 continue;
130 if ( strlen(path) > 0 && *basename == '/')
3c2c6a4 added subdir handling
Patrick Haller authored
131 basename++;
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
132
3c2c6a4 added subdir handling
Patrick Haller authored
133 debug( " readdir using basename '%s'\n", basename);
134 if ( (p = strchr(basename, '/')) == NULL) {
135 debug( " readdir path '%s' and obj '%s' is basename, adding\n", path, basename);
136 filler(buf, basename, NULL, 0);
137 continue;
138 }
139 if (strncmp(dir, basename, p - basename) != 0) {
52509c1 trivial change
Patrick Haller authored
140 memset(dir, 0, sizeof(dir));
141 strncpy(dir, basename, p - basename );
142 debug( " readdir path '%s' with basename '%s' and obj '%s' is new dir, adding\n", path, basename, dir);
3c2c6a4 added subdir handling
Patrick Haller authored
143 filler(buf, dir, NULL, 0);
144 }
ebd97ad init
Patrick Haller authored
145 }
146
147 return 0;
148 }
149
150 int git_open(const char *path, struct fuse_file_info *fi)
151 {
3c2c6a4 added subdir handling
Patrick Haller authored
152 path++;
ebd97ad init
Patrick Haller authored
153 return 0;
154 }
155
156 int git_read(const char *path, char *buf, size_t size, off_t offset,
157 struct fuse_file_info *fi)
158 {
159 (void) fi;
cec85b4 read-only appears to work
Patrick Haller authored
160 git_index_entry *e;
161 git_odb_object *obj;
162 git_oid oid;
163
3c2c6a4 added subdir handling
Patrick Haller authored
164 path++;
917c3ab added debugging cleanup
Patrick Haller authored
165 debug("git_read for -> %s with offset %d size %d\n", path, (int)offset, (int)size );
cec85b4 read-only appears to work
Patrick Haller authored
166
167 if ( (e = git_index_entry_by_file(path)) == NULL)
917c3ab added debugging cleanup
Patrick Haller authored
168 return debug("path no exist? %s\n", path),-ENOENT;
cec85b4 read-only appears to work
Patrick Haller authored
169
170 oid = e->oid;
171 git_odb_read(&obj, g_odb, &oid);
917c3ab added debugging cleanup
Patrick Haller authored
172 debug( "git_read got %ld bytes\n", (long)(git_odb_object_size(obj)));
cec85b4 read-only appears to work
Patrick Haller authored
173
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
174 memset(buf, 0, sizeof(buf));
cec85b4 read-only appears to work
Patrick Haller authored
175 if (offset >= git_odb_object_size(obj)) {
176 size = 0; goto ending;
ebd97ad init
Patrick Haller authored
177 }
cec85b4 read-only appears to work
Patrick Haller authored
178 if (offset + size > git_odb_object_size(obj))
179 size = git_odb_object_size(obj) - offset;
e72e4ec fixed path bug + read offset bug
Patrick Haller authored
180 memcpy(buf, git_odb_object_data(obj) + offset, size);
ebd97ad init
Patrick Haller authored
181
917c3ab added debugging cleanup
Patrick Haller authored
182 debug( "git_read copied %d bytes\n", (int)size);
cec85b4 read-only appears to work
Patrick Haller authored
183 ending:
184 git_odb_object_free(obj);
ebd97ad init
Patrick Haller authored
185 return size;
186 }
187
dd67afa added symlink support
Patrick Haller authored
188 int git_readlink(const char *path, char *buf, size_t size) {
189 struct fuse_file_info fi;
386e86a symlinks now properly terminated
Patrick Haller authored
190 int len = 0;
dd67afa added symlink support
Patrick Haller authored
191
386e86a symlinks now properly terminated
Patrick Haller authored
192 memset(buf, 0, sizeof(buf));
193 if ( (len = git_read(path, buf, size, 0, &fi)) > 0 ) {
194 buf[len] = '\0';
dd67afa added symlink support
Patrick Haller authored
195 return 0;
386e86a symlinks now properly terminated
Patrick Haller authored
196 }
dd67afa added symlink support
Patrick Haller authored
197 return -ENOENT;
198 }
199
ebd97ad init
Patrick Haller authored
200 struct fuse_operations git_oper = {
201 .getattr= git_getattr,
202 .readdir= git_readdir,
203 .open= git_open,
204 .read= git_read,
dd67afa added symlink support
Patrick Haller authored
205 .readlink= git_readlink
ebd97ad init
Patrick Haller authored
206 };
207
208 int main(int argc, char *argv[])
209 {
b0b267f trivial change
Patrick Haller authored
210 char *r,*m;
3c2c6a4 added subdir handling
Patrick Haller authored
211 char *args[]= { argv[0], argv[2] };
212 char *debug_args[] = { argv[0], "-f", argv[2] };
ebd97ad init
Patrick Haller authored
213
917c3ab added debugging cleanup
Patrick Haller authored
214 r = argv[1];
215 m = argv[2];
3c2c6a4 added subdir handling
Patrick Haller authored
216 debug("mounting repo %s on %s\n",r, m);
ebd97ad init
Patrick Haller authored
217
cec85b4 read-only appears to work
Patrick Haller authored
218 if (git_repository_open(&g_repo, r) < 0)
ebd97ad init
Patrick Haller authored
219 return perror("repo"), 1;
220
cec85b4 read-only appears to work
Patrick Haller authored
221 git_repository_index(&g_index, g_repo);
222 git_index_read(g_index);
223 git_repository_odb(&g_odb, g_repo);
ebd97ad init
Patrick Haller authored
224
3c2c6a4 added subdir handling
Patrick Haller authored
225 if (getenv("DEBUG") != NULL)
226 return fuse_main(3, debug_args, &git_oper);
227
228 return fuse_main(2, args, &git_oper);
ebd97ad init
Patrick Haller authored
229 }
230
Something went wrong with that request. Please try again.