Home | History | Annotate | Download | only in mongo
      1 //
      2 //  A simple symlink test
      3 //
      4 
      5 #define _GNU_SOURCE
      6 
      7 #include <sys/stat.h>
      8 #include <unistd.h>
      9 #include <stdlib.h>
     10 #include <errno.h>
     11 #include <stdio.h>
     12 #include <string.h>
     13 
     14 //
     15 // Creates symlink [new-path] to [old-path], checks it,
     16 // returnes  0 - if everything looks fine and
     17 //  1 - otherwise.
     18 // mongo_slinks reads arguments from stdin.
     19 
     20 int main(int argc, char *argv[])
     21 {
     22 	char *old_path;
     23 	char *new_path;
     24 
     25 	struct stat statbuf;
     26 
     27 	int num;
     28 	char *buffer = NULL;
     29 	char *line_buffer = NULL;
     30 	size_t line_buffer_size = 0;
     31 	int size = 1;
     32 
     33 	if ((buffer = malloc(size + 1)) == NULL) {
     34 		perror("checklink: malloc failed");
     35 		return 1;
     36 	}
     37 
     38 	while (getline(&line_buffer, &line_buffer_size, stdin) != -1) {
     39 
     40 		old_path = strtok(line_buffer, "\t ");
     41 		new_path = strtok(NULL, "\t\n ");
     42 
     43 		if (!old_path || !new_path)	/* empty lines at the end of file */
     44 			break;
     45 
     46 		// Create symlink
     47 		if (symlink(old_path, new_path) != 0) {
     48 			perror("checklink : symlink failed ");
     49 			return 1;
     50 		}
     51 		// stat data of symlink itself
     52 		if (lstat(new_path, &statbuf) == -1) {
     53 			perror("checklink: lstat failed");
     54 			return 1;
     55 		}
     56 
     57 		if (!(S_ISLNK(statbuf.st_mode))) {
     58 			printf("checklink : file %s is not a symbol link\n",
     59 			       new_path);
     60 			return 1;
     61 		}
     62 		// Test readlink
     63 		//
     64 		// Increase size of buffer to readlink untile whole symlink body will be read.
     65 		// Check readlink result on every iteration.
     66 
     67 		while (1) {
     68 			memset(buffer, 0, size + 1);
     69 			num = readlink(new_path, buffer, size);
     70 			if (num < 1 || num > size) {
     71 				perror("checklink: readlink failed");
     72 				free(buffer);
     73 				return 1;
     74 			}
     75 			// Make sure that readlink did not break things
     76 			if (buffer[num] != 0) {
     77 				printf
     78 				    ("checklink : readlink corrupts memory\n");
     79 				free(buffer);
     80 				return 1;
     81 			}
     82 			// Whole expected symlink body is read
     83 			if (num < size)
     84 				break;
     85 
     86 			// Only part of symlink body was read. So we  make a bigger buffer
     87 			// and call `readlink' again.
     88 			size *= 2;
     89 			if ((buffer = realloc(buffer, size + 1)) == NULL) {
     90 				perror("checklink: realloc failed");
     91 				return 1;
     92 			}
     93 		}
     94 	}
     95 	free(buffer);
     96 	free(line_buffer);
     97 	return 0;
     98 }
     99