Bug 129026 - rename(2) system function does not work properly
Summary: rename(2) system function does not work properly
Keywords:
Status: CLOSED NEXTRELEASE
Alias: None
Product: Fedora
Classification: Fedora
Component: kernel
Version: 2
Hardware: i386
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Dave Jones
QA Contact: Brian Brock
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2004-08-03 06:34 UTC by Evgeny Baskakov
Modified: 2015-01-04 22:08 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2005-04-16 04:17:52 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)

Description Evgeny Baskakov 2004-08-03 06:34:46 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7)
Gecko/20040616

Description of problem:
Sometimes when I need to rename a lot of files, a few files are unable
to be renamed. I.e., the destination file appears, but the source does
not.

Below is a simple program reproducing the behavior:

// tree_create.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char **argv) {
    FILE *list, *out;
    char buffer1[1024];
    char buffer2[1024];
    char *part, *c0;
    char *mem;
    char ch;
    unsigned long count = 0;
    long size;
    int len;
    
    if(argc != 2) {
        printf("usage: tree_creat <list>\n");
        return 0;
    }

    if((list = fopen(argv[1], "r")) == NULL) {
        perror("Bad input file");
        return 1;
    }

    if(fseek(list, 0, SEEK_SET) != 0) {
        perror("Unable to fseek");
        return 1;
    }

    while(fgets(buffer1, sizeof(buffer1)-1, list) &&
          fgets(buffer2, sizeof(buffer2)-1, list) &&
          strlen(buffer1) > 0 &&
          (len = strlen(buffer2)) > 0) 
    {
        size = atol(buffer1);

        if(size < 0) {
            printf("Bad size\n");
            return 1;
        }

        while(len-- && (buffer2[len] == '\n' || buffer2[len] == '\r'))
            buffer2[len] = '\0';

        if(len == 0) {
            printf("Bad fname reached\n");
            return 1;
        }
        
        c0 = buffer2;

        while(*c0 && ((part = strchr(c0, '/')) != NULL)) {
            if(*(part+1) != '/') { // avoid '//' cases
                *part = '\0';

                if(access(buffer2, F_OK) != 0) {
                    if(mkdir(buffer2, 0755) != 0) {
                        printf("Unable to create directory '%s':
%s\n", buffer2, strerror(errno));
                        return 1;
                    }
                }

                *part = '/';
            }

            c0 = part+1;
        }        

        if(*c0 == '\0') {
            printf("Bad fname reached - not a regular file: '%s'\n",
buffer2);
            return 1;
        }
             
        ch = *c0;
        *c0 = '\0';

        sprintf(buffer1, "%sxtmp_my.%d", buffer2, count++);
        
        *c0 = ch;

        if((out = fopen(buffer1, "w")) == NULL) {
            printf("Cannot create file %s: %s\n", buffer1,
strerror(errno));
            return 1;
        }

        if((mem = (char *)malloc(size)) == NULL) {
            perror("Cannot create memory buffer");
            return 1;
        }

        if(fwrite(mem, size, 1, out) < 0) {
            perror("fwrite");
            return 1;
        }

        if(fclose(out) != 0) {
            perror("fclose");
            return 1;
        }

        free(mem);

        if(rename(buffer1, buffer2) != 0) {
            printf("Rename(%s, %s) failed: %s\n", buffer1, buffer2,
strerror(errno));
            return 1;
        }
    }
        
    return 0;
}


Version-Release number of selected component (if applicable):


How reproducible:
Always

Steps to Reproduce:
1. Compile the program: gcc tree_creat.c -o tree_creat
2. Download the following file:
http://www.excelsior-usa.com/download/tmp/file_list.zip
3. Unzip it: unzip file_list.zip. The file 'file_list.txt' shall appear.
5. Place the files 'tree_creat' and 'file_list.txt' to an empty dir.
4. Run the following command: ./tree_creat file_list.txt from that dir.

    

Actual Results:  The file/directory tree appears, and there is a few
files with names like 'xtmp_my.XXX' deeply in the directory tree.
These are temporaly files had to be renamed in the proper names. But
they are NOT renamed. The image of the tree is given in the file
'file_list.txt', there is no such files.


Expected Results:  The directory/file tree must appear. There must be
no additional files.


Additional info:

BTW, after the test, some file system errors may appear.

Comment 1 Jakub Jelinek 2004-08-12 08:40:50 UTC
rename goes straight to the kernel, so I don't see how this could be
a glibc bug.

Comment 2 Alexander Viro 2004-08-12 10:22:05 UTC
which filesystem, what kind of fs errors and BTW, could you post the
strace of actual execution on your box?

Comment 3 Evgeny Baskakov 2004-09-03 08:48:33 UTC
The fs type is ext3. Here is a sample output of the e2fsck program
(command line is 'e2fsck -ycfv /dev/hda11'):

Inode 218081 ref count is 2, should be 1
Inode 231585 ref count is 2, should be 1
Unattached inode 247918
Connect to /lost+found? <YES>
Inode 264534 ref count is 2, should be 1
Inode 278235 ref count is 2, should be 1



Comment 4 Evgeny Baskakov 2004-09-03 09:20:01 UTC
The strace log is quite large (22 Mb).
There is nothing unusal about rename calls: grepped list shows that
all rename() calls return zero.

Comment 5 Dave Jones 2005-04-16 04:17:52 UTC
Fedora Core 2 has now reached end of life, and no further updates will be
provided by Red Hat.  The Fedora legacy project will be producing further kernel
updates for security problems only.

If this bug has not been fixed in the latest Fedora Core 2 update kernel, please
try to reproduce it under Fedora Core 3, and reopen if necessary, changing the
product version accordingly.

Thank you.



Note You need to log in before you can comment on or make changes to this bug.