The attached test program creates a file, and then some hard links to that file (file0 - fileN). The test program then attempts to rename(fileN, file) for every hard link created. My expectation is that the hard links file0 - fileN would simply disappear, or that rename would respond with an error result and an appropriate errno value indicating the problem. My observation is that the hard links file0 to fileN do not in fact disappear and rename returns 0. Do I have the wrong expectations? If so, why should I have to stat the files to determine if they are the same inode before I rename? Is this a VFS bug? It seems to apply to all file-systems (I have tried only EXT3, XFS, and TMPFS). This also seems to occur on other unixes. Regards, John -- John Muir NORTEL muirj@xxxxxxxxxx
// renameover // ------------------------------------------------------------------ // Simple program which renames hard links over each other. #include <unistd.h> #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #define FILE_BLOCK_SIZE 4096 // main // ------------------------------------------------------------------ int main ( int argc, char **argv ) { int fd; int count = 0; int i; char *buf; struct stat statBuf; if( argc < 2 ) { fprintf( stderr, "renameover <filename> [count]\n" ); return EINVAL; } if( argc >= 3 ) count = atoi( argv[2] ); if( count <= 0 ) count = 10; fd = open( argv[1], O_CREAT | O_RDWR, S_IRUSR | S_IWUSR ); if( fd < 0 ) { perror( "open create" ); return errno; } buf = alloca( FILE_BLOCK_SIZE ); memset( buf, ( count % 26 ) + 'A', FILE_BLOCK_SIZE ); buf[ FILE_BLOCK_SIZE - 1 ] = '\n'; write( fd, buf, FILE_BLOCK_SIZE ); if( close( fd ) < 0 ) { perror( "close" ); return errno; } i = 0; while( i < count ) { snprintf( buf, FILE_BLOCK_SIZE, "%s%d", argv[1], i ); if( link( argv[1], buf ) < 0 ) { perror( "link" ); return errno; } ++i; } if( stat( argv[1], &statBuf ) < 0 ) { perror( "stat" ); return errno; } printf( "Hard link count for '%s': %u (expecting %d).\n", argv[1], statBuf.st_nlink, count + 1 ); i = 0; while( i < count ) { snprintf( buf, FILE_BLOCK_SIZE, "%s%d", argv[1], i ); if( rename( buf, argv[1] ) < 0 ) { perror( "rename" ); return errno; } else { if( stat( buf, &statBuf ) < 0 ) { if( errno != ENOENT ) perror( "stat" ); } else { printf( "Unexpected: '%s' still exists. " "Hard link count: %u, expected %d.\n", buf, statBuf.st_nlink, count - i ); } } ++i; } return 0; }