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