You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
4.9 KiB
179 lines
4.9 KiB
--- tdl-1.5.2.orig/main.c
|
|
+++ tdl-1.5.2/main.c
|
|
@@ -80,7 +80,7 @@
|
|
return;
|
|
}
|
|
/*}}}*/
|
|
-static volatile void unlock_and_exit(int code)/*{{{*/
|
|
+static void unlock_and_exit(int code)/*{{{*/
|
|
{
|
|
unlock_database();
|
|
exit(code);
|
|
@@ -237,22 +237,91 @@
|
|
|
|
}
|
|
/*}}}*/
|
|
-static void rename_database(char *path)/*{{{*/
|
|
+static mode_t get_mode(const char *path); /* prototype */
|
|
+/*}}}*/
|
|
+static int copy_file_contents(char *pathsrc, char *pathdest) {
|
|
+ int src, dest;
|
|
+ ssize_t rdsize = 1;
|
|
+ char buf[4096];
|
|
+
|
|
+ src = open(pathsrc, O_RDONLY);
|
|
+ if (src == -1) {
|
|
+ perror("warning, couldn't open database");
|
|
+ return 0;
|
|
+ }
|
|
+ dest = open(pathdest, O_WRONLY | O_CREAT, get_mode(pathsrc));
|
|
+ if (dest == -1) {
|
|
+ perror("warning, couldn't open/create backup database");
|
|
+ close(src);
|
|
+ return 0;
|
|
+ }
|
|
+ if (ftruncate(dest,0) != 0) {
|
|
+ perror("warning, couldn't truncate backup database");
|
|
+ close(src);
|
|
+ close(dest);
|
|
+ return 0;
|
|
+ }
|
|
+ lseek(src,0,SEEK_SET);
|
|
+ lseek(dest,0,SEEK_SET);
|
|
+ while (rdsize > 0) {
|
|
+ rdsize = read(src, buf, 4096);
|
|
+ if (rdsize == -1) {
|
|
+ perror("warning, error reading database");
|
|
+ close(src);
|
|
+ close(dest);
|
|
+ return 0;
|
|
+ }
|
|
+ if (rdsize > 0) {
|
|
+ if (write(dest, buf, rdsize) != rdsize) {
|
|
+ perror("warning, error writing to backup database");
|
|
+ close(src);
|
|
+ close(dest);
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ close(src);
|
|
+ close(dest);
|
|
+ return 1;
|
|
+}
|
|
+/*}}}*/
|
|
+static int path_is_symlink(char *path) {
|
|
+ int i;
|
|
+ struct stat s;
|
|
+ i = lstat(path, &s);
|
|
+ if ((i == 0) && (S_ISLNK(s.st_mode))) {
|
|
+ return 1; /* is a symlink */
|
|
+ }
|
|
+ return 0; /* not a symlink */
|
|
+}
|
|
+/*}}}*/
|
|
+static int rename_database(char *path)/*{{{*/
|
|
{
|
|
- int len;
|
|
+ /* the rename_database function returns 1 if database or/and
|
|
+ * database backup file are symlinks; otherwise returns 0 */
|
|
+ int len, symlinks;
|
|
char *pathbak;
|
|
-
|
|
+
|
|
len = strlen(path);
|
|
pathbak = new_array(char, len + 5);
|
|
strcpy(pathbak, path);
|
|
strcat(pathbak, ".bak");
|
|
- if (rename(path, pathbak) < 0) {
|
|
- if (is_noisy) {
|
|
- perror("warning, couldn't save backup database:");
|
|
+
|
|
+ symlinks = path_is_symlink(path) | path_is_symlink(pathbak);
|
|
+
|
|
+ if (symlinks) {
|
|
+ if (access(path,F_OK) == 0) {
|
|
+ copy_file_contents(path, pathbak);
|
|
+ }
|
|
+ } else {
|
|
+ if (rename(path, pathbak) < 0) {
|
|
+ if (is_noisy) {
|
|
+ perror("warning, couldn't save backup database:");
|
|
+ }
|
|
}
|
|
}
|
|
free(pathbak);
|
|
- return;
|
|
+ return symlinks;
|
|
}
|
|
/*}}}*/
|
|
static char *executable_name(char *argv0)/*{{{*/
|
|
@@ -315,7 +384,7 @@
|
|
/*}}}*/
|
|
static void save_database(char *path)/*{{{*/
|
|
{
|
|
- FILE *out;
|
|
+ FILE *out = NULL;
|
|
int out_fd;
|
|
mode_t database_mode;
|
|
if (is_loaded && currently_dirty) {
|
|
@@ -324,20 +393,34 @@
|
|
/* The next line only used to happen if the command wasn't 'create'.
|
|
* However, it should quietly fail for create, where the existing database
|
|
* doesn't exist */
|
|
- rename_database(path);
|
|
-
|
|
- /* Open database this way so that the permissions from the existing
|
|
- database can be duplicated onto the new one in way free of race
|
|
- conditions. */
|
|
- out_fd = open(path, O_WRONLY | O_CREAT | O_EXCL, database_mode);
|
|
- if (out_fd < 0) {
|
|
- fprintf(stderr, "Could not open new database %s for writing : %s\n",
|
|
- path, strerror(errno));
|
|
- unlock_and_exit(1);
|
|
+ if (rename_database(path) == 0) {
|
|
+ /* database is a regular file */
|
|
+ /* Open database this way so that the permissions from the existing
|
|
+ database can be duplicated onto the new one in way free of race
|
|
+ conditions. */
|
|
+ out_fd = open(path, O_WRONLY | O_CREAT | O_EXCL, database_mode);
|
|
+ if (out_fd < 0) {
|
|
+ fprintf(stderr, "Could not open new database %s for writing : %s\n",
|
|
+ path, strerror(errno));
|
|
+ unlock_and_exit(1);
|
|
+ }
|
|
} else {
|
|
- /* Normal case */
|
|
- out = fdopen(out_fd, "wb");
|
|
+ /* database and/or backup database are symlinks */
|
|
+ /* we should truncate existing file and write its contents */
|
|
+ out_fd = open(path, O_WRONLY | O_CREAT, database_mode);
|
|
+ if (out_fd < 0) {
|
|
+ fprintf(stderr, "Could not open database %s for writing : %s\n",
|
|
+ path, strerror(errno));
|
|
+ unlock_and_exit(1);
|
|
+ } else {
|
|
+ /* Normal case */
|
|
+ if (ftruncate(out_fd, 0) != 0) {
|
|
+ perror("warning, couldn't truncate database:");
|
|
+ unlock_and_exit(1);
|
|
+ }
|
|
+ }
|
|
}
|
|
+ out = fdopen(out_fd, "wb");
|
|
if (!out) {
|
|
fprintf(stderr, "Cannot open database %s for writing\n", path);
|
|
unlock_and_exit(1);
|
|
@@ -728,6 +811,11 @@
|
|
|
|
if (!is_loaded && cmds[index].load_db) {
|
|
load_database(current_database_path);
|
|
+ if (is_interactive && (!is_loaded)) {
|
|
+ fprintf(stderr, "error: could not open database. please create a "
|
|
+ "database with 'tdl create' before using this tdl command\n");
|
|
+ unlock_and_exit(-1);
|
|
+ }
|
|
}
|
|
|
|
pp = is_tdl ? (p + 1) : p;
|