| // |
| // A simple symlink test |
| // |
| |
| #define _GNU_SOURCE |
| |
| #include <sys/stat.h> |
| #include <unistd.h> |
| #include <stdlib.h> |
| #include <errno.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| // |
| // Creates symlink [new-path] to [old-path], checks it, |
| // returnes 0 - if everything looks fine and |
| // 1 - otherwise. |
| // mongo_slinks reads arguments from stdin. |
| |
| int main (int argc, char * argv []) |
| { |
| char * old_path; |
| char * new_path; |
| |
| struct stat statbuf; |
| |
| int num; |
| char * buffer = NULL; |
| char *line_buffer = NULL; |
| size_t line_buffer_size = 0; |
| int size = 1; |
| |
| if ((buffer = (char *) malloc (size+1)) == NULL) { |
| perror ("checklink: malloc failed"); |
| return 1; |
| } |
| |
| while (getline(&line_buffer, &line_buffer_size, stdin) != -1) { |
| |
| old_path = strtok(line_buffer, "\t "); |
| new_path = strtok(NULL, "\t\n "); |
| |
| if (!old_path || !new_path) /* empty lines at the end of file */ |
| break; |
| |
| // Create symlink |
| if (symlink(old_path, new_path) != 0) { |
| perror ("checklink : symlink failed "); |
| return 1; |
| } |
| |
| // stat data of symlink itself |
| if (lstat(new_path, &statbuf)== -1) { |
| perror ("checklink: lstat failed"); |
| return 1; |
| } |
| |
| if (! (S_ISLNK (statbuf.st_mode))) { |
| printf ("checklink : file %s is not a symbol link\n", new_path); |
| return 1; |
| } |
| |
| // Test readlink |
| // |
| // Increase size of buffer to readlink untile whole symlink body will be read. |
| // Check readlink result on every iteration. |
| |
| while (1) { |
| memset (buffer, 0, size+1); |
| num = readlink (new_path, buffer, size); |
| if (num < 1 || num > size) { |
| perror ("checklink: readlink failed"); |
| free (buffer); |
| return 1; |
| } |
| |
| // Make sure that readlink did not break things |
| if (buffer [num] != 0) { |
| printf ("checklink : readlink corrupts memory\n"); |
| free (buffer); |
| return 1; |
| } |
| |
| // Whole expected symlink body is read |
| if (num < size) |
| break; |
| |
| // Only part of symlink body was read. So we make a bigger buffer |
| // and call `readlink' again. |
| size *= 2; |
| if ((buffer = realloc(buffer, size+1)) == NULL) { |
| perror("checklink: realloc failed"); |
| return 1; |
| } |
| } |
| } |
| free (buffer); |
| free (line_buffer); |
| return 0; |
| } |