dav/main.c

branch
feature/dav-edit
changeset 709
857330e1e3f4
parent 703
2e3a24b9896a
child 710
7384da29c2b4
equal deleted inserted replaced
708:3fc7f813b53d 709:857330e1e3f4
33 #include <stdbool.h> 33 #include <stdbool.h>
34 #include <errno.h> 34 #include <errno.h>
35 #include <unistd.h> 35 #include <unistd.h>
36 #include <time.h> 36 #include <time.h>
37 #include <sys/types.h> 37 #include <sys/types.h>
38 #include <sys/wait.h>
38 #include <ucx/string.h> 39 #include <ucx/string.h>
39 #include <ucx/utils.h> 40 #include <ucx/utils.h>
40 #include <dirent.h> 41 #include <dirent.h>
41 42
42 #include <libidav/utils.h> 43 #include <libidav/utils.h>
156 } else if(!strcasecmp(cmd, "get")) { 157 } else if(!strcasecmp(cmd, "get")) {
157 ret = cmd_get(args, FALSE); 158 ret = cmd_get(args, FALSE);
158 } else if(!strcasecmp(cmd, "cat")) { 159 } else if(!strcasecmp(cmd, "cat")) {
159 ucx_map_cstr_put(args->options, "output", "-"); 160 ucx_map_cstr_put(args->options, "output", "-");
160 ret = cmd_get(args, FALSE); 161 ret = cmd_get(args, FALSE);
162 } else if(!strcasecmp(cmd, "edit")) {
163 ret = cmd_edit(args);
161 } else if(!strcasecmp(cmd, "put")) { 164 } else if(!strcasecmp(cmd, "put")) {
162 ret = cmd_put(args, FALSE); 165 ret = cmd_put(args, FALSE);
163 } else if( 166 } else if(
164 !strcasecmp(cmd, "remove") || 167 !strcasecmp(cmd, "remove") ||
165 !strcasecmp(cmd, "rm") || 168 !strcasecmp(cmd, "rm") ||
245 248
246 static char *cmdusageinfo[] = { 249 static char *cmdusageinfo[] = {
247 "list [-altdepcR] [-u <date>] <url>", 250 "list [-altdepcR] [-u <date>] <url>",
248 "get [-pcRK] [-o <file>] [-u <date>] [-V <version>] <url>", 251 "get [-pcRK] [-o <file>] [-u <date>] [-V <version>] <url>",
249 "put [-pcR] [-k <key>] [-L <lock>] <url> <file...>", 252 "put [-pcR] [-k <key>] [-L <lock>] <url> <file...>",
253 "edit [-V <version>] <url>",
250 "mkdir [-pc] [-k <key>] [-L <lock>] <url> [file...]", 254 "mkdir [-pc] [-k <key>] [-L <lock>] <url> [file...]",
251 "remove [-pc] [-L <lock>] <url> [file...]", 255 "remove [-pc] [-L <lock>] <url> [file...]",
252 "copy [-pcO] [-L <lock>] <url> <url>", 256 "copy [-pcO] [-L <lock>] <url> <url>",
253 "move [-pcO] [-L <lock>] <url> <url>", 257 "move [-pcO] [-L <lock>] <url> <url>",
254 "rename [-pcO] [-L <lock>] <url> <name>", 258 "rename [-pcO] [-L <lock>] <url> <name>",
1113 fclose(pdata.out); 1117 fclose(pdata.out);
1114 } 1118 }
1115 return ret; 1119 return ret;
1116 } 1120 }
1117 1121
1122 static int file_seek(FILE *f, curl_off_t offset, int origin) {
1123 int ret = fseek(f, offset, origin);
1124 return ret == 0 ? CURL_SEEKFUNC_OK : CURL_SEEKFUNC_CANTSEEK;
1125 }
1126
1127 int cmd_edit(CmdArgs *a) {
1128 if(a->argc != 1) {
1129 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few":"many");
1130 fprintf(stderr, "Usage: dav %s\n", find_usage_str("edit"));
1131 return -1;
1132 }
1133
1134 char *url = a->argv[0];
1135 char *path = NULL;
1136 Repository *repo = url2repo(url, &path);
1137 DavSession *sn = connect_to_repo(repo, path, a);
1138
1139 if(set_session_config(sn, a)) {
1140 return -1;
1141 }
1142
1143 char *version = cmd_getoption(a, "version");
1144 DavResource *res;
1145
1146 res = dav_resource_new(sn, path);
1147 int fresh_resource = !dav_exists(res);
1148 if(fresh_resource) {
1149 // create the resource to check if the resource can be created
1150 // we don't want the user to invest time in editing and fail afterwards
1151 if(dav_create(res)) {
1152 fprintf(stderr, "Resource does not exist and cannot be created.\n");
1153 return -1;
1154 }
1155 } else {
1156 if(!res) {
1157 print_resource_error(sn, path);
1158 return -1;
1159 }
1160 if(res->iscollection) {
1161 fprintf(stderr, "Resource %s is a collection "
1162 "and cannot be opened in an editor.\n", res->path);
1163 return -1;
1164 }
1165
1166 if(version) {
1167 DavResource *vres = find_version(res, version);
1168 if(!vres) {
1169 fprintf(stderr, "Cannot find version '%s' for resource.\n", version);
1170 return -1;
1171 }
1172 dav_resource_free_all(res);
1173 res = vres;
1174 }
1175 }
1176
1177 // open temporary file
1178 // TODO: look up the location of the temp directory, maybe add sys_* funcs
1179 char outfile[24];
1180 strncpy(outfile, ".dav-edit-XXXXXX", 24);
1181 int tmp_fd = mkstemp(outfile);
1182 if(tmp_fd < 0) {
1183 perror("Cannot open temporary file");
1184 return -1;
1185 }
1186
1187 // get resource
1188 if(!fresh_resource) {
1189 FILE* tmp_stream = sys_fopen(outfile, "wb");
1190 if(!tmp_stream) {
1191 perror("Cannot open temporary file");
1192 close(tmp_fd);
1193 return -1;
1194 }
1195 if(dav_get_content(res, tmp_stream, (dav_write_func)fwrite)) {
1196 print_resource_error(sn, path);
1197 close(tmp_fd);
1198 unlink(outfile);
1199 return -1;
1200 }
1201 fclose(tmp_stream);
1202 }
1203
1204 // remember time s.t. we can later check if the file has changed
1205 SYS_STAT tmp_stat;
1206 // TODO: maybe add sys_fstat
1207 if(sys_stat(outfile, &tmp_stat)) {
1208 perror("Cannot stat temporary file");
1209 close(tmp_fd);
1210 unlink(outfile);
1211 return -1;
1212 }
1213 time_t dl_mtime = tmp_stat.st_mtime;
1214
1215 // open in editor
1216 char* default_editor = "vi";
1217 char* editor = getenv("EDITOR");
1218 if(!editor) editor = default_editor;
1219 char* viargs[3] = {editor, outfile, NULL};
1220
1221 int ret = 0;
1222 // TODO: solution for windows
1223 pid_t pid = fork();
1224 if(pid < 0) {
1225 perror("Cannot create process for editor");
1226 ret = 1;
1227 } else if(pid == 0) {
1228 if(execvp(viargs[0], viargs)) {
1229 perror("Opening the editor failed");
1230 return 1;
1231 }
1232 } else {
1233 int status = -1;
1234 ret = waitpid(pid, &status, 0);
1235 if(ret < 0) {
1236 perror("Error waiting for editor");
1237 } else if(WEXITSTATUS(status)) {
1238 fprintf(stderr,
1239 "Editor closed abnormally - file will not be uploaded.\n");
1240 ret = 1;
1241 } else {
1242 // check if the file has changed
1243 if (sys_stat(outfile, &tmp_stat)) {
1244 perror("Cannot stat temporary file");
1245 ret = 1;
1246 } else if (dl_mtime < tmp_stat.st_mtime) {
1247 // upload changed file
1248 FILE* tmp_stream = sys_fopen(outfile, "rb");
1249 if(!tmp_stream) {
1250 perror("Cannot open temporary file");
1251 close(tmp_fd);
1252 return -1;
1253 }
1254 dav_set_content(res, tmp_stream,
1255 (dav_read_func)fread,
1256 (dav_seek_func)file_seek);
1257 dav_set_content_length(res, tmp_stat.st_size);
1258 ret = dav_store(res);
1259 fclose(tmp_stream);
1260 if(ret) {
1261 print_resource_error(sn, path);
1262 }
1263 } else {
1264 printf("No changes by user - file will not be uploaded.\n");
1265 }
1266 }
1267 }
1268
1269 close(tmp_fd);
1270 unlink(outfile);
1271 free(path);
1272
1273 return ret;
1274 }
1275
1118 int get_resource(Repository *repo, GetResource *getres, CmdArgs *a, void *unused) { 1276 int get_resource(Repository *repo, GetResource *getres, CmdArgs *a, void *unused) {
1119 DavResource *res = getres->res; 1277 DavResource *res = getres->res;
1120 char *out = getres->path; 1278 char *out = getres->path;
1121 1279
1122 if(res->iscollection) { 1280 if(res->iscollection) {
1499 if(!isstdin) { 1657 if(!isstdin) {
1500 fclose(in); 1658 fclose(in);
1501 } 1659 }
1502 1660
1503 return ret; 1661 return ret;
1504 }
1505
1506 static int file_seek(FILE *f, curl_off_t offset, int origin) {
1507 int ret = fseek(f, offset, origin);
1508 return ret == 0 ? CURL_SEEKFUNC_OK : CURL_SEEKFUNC_CANTSEEK;
1509 } 1662 }
1510 1663
1511 int put_file( 1664 int put_file(
1512 Repository *repo, 1665 Repository *repo,
1513 CmdArgs *a, 1666 CmdArgs *a,

mercurial