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 
main(int argc,char * argv[])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