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