Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

splitting a full filename into parts

I am creating a function that will split a full unix filename(like /home/earlz/test.bin) into its individual parts. I have got a function, and it works for the first two parts perfect, but after that it produces erroneous output...

strlcpy_char will copy a string using term as the terminator, as well as 0. If it is terminated with term, then term will be the last character of the string, then null.

returns trg string length...

int strlcpy_char(char *trg,const char *src,int max,char term){
    int i;
    if(max==0){return 0;}
    for(i=0;i<max-1;i++){
            if(*src==0){
                    *trg=0;
                    return i;
            }
            if(*src==term){
                    *trg=term;
                    trg++;
                    *trg=0; //null terminate
                    return i+1;
            }
            *trg=*src;
            src++;
            trg++;
    }
    *trg=0;
    return max; 
}

.

int get_path_part(char *file,int n,char *buf){
    int i;
    int current_i=0;
    //file is assumed to start with '/'so it skips the first character.
    for(i=0;i<=n;i++){
            current_i++;
            current_i=strlcpy_char(buf,&file[current_i],MAX_PATH_PART_SIZE,'/');
            if(current_i<=1){ //zero length string..
                    kputs("!"); //just a debug message. This never happens with the example
                    return -1; //not enough parts to the path
            }
    }
    if(buf[current_i-1]=='/'){
            return 1; //is not the last part
    }else{
            return 0; //is the last part(the file part)
    }
}

I use this code to test it:

        kputs("test path: ");
        kgets(cmd);
        kputs("\n");
        char *tmp=malloc(256);
        int i=0;
        get_path_part(cmd,i,tmp);
        kputs(tmp);
        kputs("\n");
        i=1;
        get_path_part(cmd,i,tmp);
        kputs(tmp);
        kputs("\n");
        i=2;
        get_path_part(cmd,i,tmp);
        kputs(tmp);
        kputs("\n");

When I try something like "/home/test.bin" it works right outputting

/home
/test.bin

But when I try "/home/earlz/test.bin" I get

/home
/earlz
/arlz

Anyone see the problem in my code, as I've been looking but I just can't see any problem.

Also, before you say "but there is a library for that" I am doing this in an operating system kernel, so I barely have a standard library. I only have parts of string.h and really that's about it for standard.

like image 353
Earlz Avatar asked Mar 01 '23 15:03

Earlz


2 Answers

You overwrite current_i instead of adding it up as you walk through the path.

So

current_i++;
current_i=strlcpy_char(buf,&file[current_i],MAX_PATH_PART_SIZE,'/');

should really be

current_i += strlcpy_char(buf,&file[current_i+1],MAX_PATH_PART_SIZE,'/');
like image 132
Tobiesque Avatar answered Mar 06 '23 03:03

Tobiesque


I think you need to track your current_i for i>1 since the max value returned from the strlcpy has no idea of where you are in the overall file string. does it make sense?

current_i=strlcpy_char(buf,&file[current_i],MAX_PATH_PART_SIZE,'/');
like image 30
Ryan Oberoi Avatar answered Mar 06 '23 05:03

Ryan Oberoi