1

Here is my code. I'm assuming this has something to do with improper use of pointers or maybe I'm not mapping and unmapping my memory correctly.

Could anyone please provide me with some insight into the issue?

#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h> 
#include <sys/mman.h>
#include <ftw.h>
#include <sys/stat.h>
#include <string.h>

int size;
int map1, map2;
void *tar, *temp;

int callback(const char *filename,
             const struct stat *sb2,
             int filetype,
             struct FTW *ftw)
{           
    printf("test");
    if(sb2->st_size == sb1->st_size){
        temp = mmap(NULL, sb2->st_size, PROT_NONE, 0, map2, 0);
        int cmp = memcmp(tar, temp, sb2->st_size);
        printf("%d\n", cmp);
        if(cmp == 0){
            printf("%s\n", filename);
        }  
        if(munmap(temp,sb2->st_size) == -1){
            fprintf(stderr, "Error in unmapping in callback function");
            exit(EXIT_FAILURE);
        }  
    }  

    return 0;   //continue to walk the tree
}  

int main(int argc, char *argv[])
{
    //check for correct arguments
    if (argc == 1 || argc > 3) {
        fprintf(stderr, "Syntax: %s filename dirname\n", argv[0]);
        exit(EXIT_FAILURE);
    }  


    //use stat to get size of filename
    struct stat sb1;
    if(stat(argv[1],&sb1) != 0){
        fprintf(stderr, "Error in stat().");
        exit(EXIT_FAILURE);
    }
    size = sb1.st_size;

    //fd = mmap filename
    tar = mmap(NULL,sb1->st_size, PROT_WRITE, MAP_SHARED, map1, 0);
    if(tar == 0){
        fprintf(stderr, "Main() mmap failed");
        exit(EXIT_FAILURE);
    }  


    //walk through the directory with callback function
    nftw(argv[2], callback, 20, 0);

    // use munmap to clear fd
    if (munmap(tar,sb1->st_size) == -1) {
        fprintf(stderr, "Error in unmapping");
        exit(EXIT_FAILURE);
    }  
}

EDIT

I now declare my struct stat sb1 right before I use the stat function. After doing that I receieved a segmentation error again. I then commented out my nftw() call and and printed out the size variable (which has a reasonable number so I believe that's working). The new error is:

Error in unmapping.

Frank
  • 155
  • 1
  • 2
  • 9
  • On which line does it seg fault? – FatalError Apr 02 '13 at 04:14
  • Please do not just post code here and expect us to debug it for you. We'd be more than happy to help out, but you need to show that you've made an effort first. What does the debugger report? What line is the problem on? What do *you* think is going wrong? If you give us this information, we can do a much better job helping out. – templatetypedef Apr 02 '13 at 04:14
  • I understand. I'll try and do a more thorough job in the future. I really am thankful for the help I receive on here, though. – Frank Apr 02 '13 at 05:12

2 Answers2

4

You declare:

struct stat *sb1;

You use:

stat(argv[1],sb1);

You crash and burn because sb1 is a null pointer (since the variable is defined at file scope, it is initialized with 0).

You need to declare (at file scope):

struct stat sb1;

And then in main() you can use:

if (stat(argv[1], &sb1) != 0)
    ...oops...

You'll have to review all uses of sb1 to fix the status change from pointer to object, adding an & where necessary, and changing -> to . where necessary.

mmap() by example

This is a mildly edited version of a function I wrote that uses mmap() to map a file into memory:

/* Map named file into memory and validate that it is a MSG file */
static int msg_mapfile(const char *file)
{
    int         fd;
    void       *vp;
    struct stat sb;

    if (file == 0)
        return(MSG_NOMSGFILE);
    if ((fd = open(file, O_RDONLY, 0)) < 0)
        return(MSG_OPENFAIL);
    if (fstat(fd, &sb) != 0)
    {
        close(fd);
        return(MSG_STATFAIL);
    }
    vp = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    close(fd);
    if (vp == MAP_FAILED)
        return(MSG_MMAPFAIL);

The MSG_xxxx constants are distinct error numbers applicable to the program it came from. It was only needing to read the file, hence the PROT_READ; I think you may be OK with that too.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I understand what you're saying and I believe I've changed it. I'm still getting a segmentation error, though. I moved the struct stat sb1; to right above the stat() call but in doing so I had to make a file scope int that my callback method could reference. I set the int to sb1.st_size. Any idea what th eproblem could be? – Frank Apr 02 '13 at 04:28
  • My intention was that you replace `struct stat *sb1;` with `struct stat sb1;` at file scope. In `main()`, you'd then write the call, including the check that `stat()` succeeded. – Jonathan Leffler Apr 02 '13 at 04:32
  • Stat definitely succeeded and I'm no longer using a pointer. So thank you for that. Now I get new errors. – Frank Apr 02 '13 at 04:39
  • You might also note that your `printf("test");` in `callback()` will be no help whatsoever; you need a newline at the end to see the output. I'm not clear what your `mmap()` is meant to do; it allocates enough space for the file named by `argv[1]`, but you don't map the file into it. You then use the memory for comparison purposes in `callback()`. Similar comments apply to the `mmap()` operations in `callback()`. Both `map1` and `map2` are initialized to 0 (because they're file scope), so you're mapping standard input to the memory? – Jonathan Leffler Apr 02 '13 at 04:39
  • OH! that's totally the issue. Huge oversight. I think I don't understand mmap. Which parameter do I put my file? Do I need to open the file and use that as the file descriptor? – Frank Apr 02 '13 at 04:40
  • I'd need to go check the details, but something along those lines, or you have to open the file and map the open file descriptor (which is what you might be doing with `map1` and `map2`, except that you're not opening the files first). – Jonathan Leffler Apr 02 '13 at 04:42
  • You are the best! Besides the errors in using file descriptors correctly, I believe some of my errors came from using incorrect flags or other parameters in my mmap() call. For instance, I switched "NULL" to "0" like yours, although I'm not sure if that really makes a difference. In any case, it all looks to be working as exptected now! Thanks a ton! Is there anything I can do to give you stack overflow honors? – Frank Apr 02 '13 at 05:11
0
if (argc == 1 || argc > 3) {
    fprintf(stderr, "Syntax: %s filename dirname\n", argv[0]);
    exit(EXIT_FAILURE);
}

/* ... */

nftw(argv[2], callback, 20, 0);

I see a possibility for argv[2] to be NULL. Perhaps you meant:

if (argc != 3) {
    fprintf(stderr, "Syntax: %s filename dirname\n", argv[0]);
    exit(EXIT_FAILURE);
}

Which book are you reading?

autistic
  • 1
  • 3
  • 35
  • 80
  • Thanks for the heads-up. I misread the assignment description and changed a bit of my code to account for the directory name not being named. If it isn't I just use "." – Frank Apr 02 '13 at 05:20