Thread: Issue on reading from flash with flash.....

  1. #1
    Registered User
    Join Date
    Apr 2009
    Posts
    145

    Issue on reading from flash with flash.....

    Hi,

    Problem statement:
    I have to retain a value....Hence i am storing the same to flash using fwrite and fread operations(Os Linux).

    Observarion:
    1. As soon as the data is written(fwrite) i am reading(fread) the value.
    I am able to read the value and it is intact.
    2. Problem begins when i have switched the Hardware OFF and once every thing is set. Now i do an fopen() which suceeds but fread() fails all the time with error "ENOENT"
    3. I am writing to jffs1..........Strange is this stuff used to work some time back now it doesn't.....What could be wrong here?


    Following is the code: I am really frustrated with this


    Code:
    static Bool mWritetoFlashFreqInt(void)
    {
    	FILE *fptr;
    	Bool Sucess = FALSE;
    	memset(mStoredFreqIntervalDetails,'\0',(MAX_URISIZE));
    	str_strcpy(mStoredFreqIntervalDetails,mHtvClnSvcDirPath);
    	str_strcat(mStoredFreqIntervalDetails,"/htvclnsvc/");
    	mkdir(mStoredFreqIntervalDetails,(S_IROTH | S_IWOTH | S_IXOTH));
        str_strcat(mStoredFreqIntervalDetails,STOREPATH_FREQINTERVAL);		 
    	
    	//unlink(mStoredFreqIntervalDetails);
    	fptr = fopen(mStoredFreqIntervalDetails,"w");
    	if(fptr)
    	{
    		size = fwrite(&sAutoUpgFreqInterval, sizeof(tsAutoUpgFreqInterval), 1, fptr);
    		fclose(fptr);
    	}
    	else
    	{
    		Sucess = FALSE;
    	}	
    	
    	mReadFlashFreqInt();
    	return Sucess;
    }
    
    
    static Bool mReadFlashFreqInt(void)
    {
    	FILE *fptr;
    	Bool Sucess = FALSE;
    	int i;
    
    	memset(mStoredFreqIntervalDetails,'\0',(MAX_URISIZE));
    	str_strcpy(mStoredFreqIntervalDetails,mHtvClnSvcDirPath);
    	str_strcat(mStoredFreqIntervalDetails,"/htvclnsvc/");
        str_strcat(mStoredFreqIntervalDetails,STOREPATH_FREQINTERVAL);		 
    	fptr = fopen(mStoredFreqIntervalDetails,"r");
    	
    	if(fptr)
    	{
    		size = fread(&sAutoUpgFreqInterval, sizeof(tsAutoUpgFreqInterval), 1, fptr);			
    		if(size == 1)
    		{
    			Sucess = TRUE;
    		}			
    		fclose(fptr);
    	}
    	else
    	{
    		Sucess = FALSE;
    	}	
    	return Sucess;
    }
    Thanks in advance

  2. #2
    Registered User
    Join Date
    Apr 2009
    Posts
    145
    can anyone help me debug the problem?

  3. #3
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    If you modify your code to
    Code:
    #define FREQINTDIR "/htvclnsvc/"
    
    static Bool mWritetoFlashFreqInt(void)
    {
    	FILE *fptr;
    
    	memset(mStoredFreqIntervalDetails, '\0', MAX_URISIZE);
    	str_strcpy(mStoredFreqIntervalDetails, mHtvClnSvcDirPath);
    	str_strcat(mStoredFreqIntervalDetails, FREQINTDIR);
    
    	if (mkdir(mStoredFreqIntervalDetails, S_IROTH | S_IWOTH | S_IXOTH))
    		return FALSE;
    
    	str_strcat(mStoredFreqIntervalDetails,STOREPATH_FREQINTERVAL);		 
    	
    	fptr = fopen(mStoredFreqIntervalDetails, "w");
    	if (!fptr)
    		return FALSE;
    
    	if (fwrite(&sAutoUpgFreqInterval, sizeof(tsAutoUpgFreqInterval), 1, fptr) != 1) {
    		fclose(fptr);
    		return FALSE;
    	}
    
    	if (fflush(fptr)) {
    		fclose(fptr);
    		return FALSE;
    	}
    
    	if (fsync(fileno(fptr)) {
    		fclose(fptr);
    		return FALSE;
    	}
    
    	if (fclose(fptr))
    		return FALSE;
    		fclose(fptr);
    	}
    
    	return TRUE;
    }
    
    static Bool mReadFlashFreqInt(void)
    {
    	FILE *fptr;
    	int i;
    
    	memset(mStoredFreqIntervalDetails, '\0', MAX_URISIZE);
    
    	str_strcpy(mStoredFreqIntervalDetails, mHtvClnSvcDirPath);
    	str_strcat(mStoredFreqIntervalDetails, FREQINTDIR);
    	str_strcat(mStoredFreqIntervalDetails, STOREPATH_FREQINTERVAL);
    
    	fptr = fopen(mStoredFreqIntervalDetails, "r");
    	if (!fptr)
    		return FALSE;
    
    	if (fread(&sAutoUpgFreqInterval, sizeof(tsAutoUpgFreqInterval), 1, fptr) != 1) {
    		fclose(fptr);
    		return FALSE;
    	}
    
    	if (fclose(fptr))
    		return FALSE;
    
    	return TRUE;
    }
    and run it and verify both functions really return TRUE when called?

    Aside from correct status and error checking, the write part contains
    Code:
    	if (fflush(fptr)) {
    		fclose(fptr);
    		return FALSE;
    	}
    
    	if (fsync(fileno(fptr)) {
    		fclose(fptr);
    		return FALSE;
    	}
    The first part causes the C library to actually save the data into the underlying file, instead of just caching it in internal buffers. It may fail just like fwrite() can. (Because fclose() does an implicit fflush(), fclose() can also fail!)

    The second part is a POSIX.1-2001 extension, see man 2 fsync. It asks the kernel to make sure the data hits the actual device.

    In fact, to ensure the data and metadata has been completely written to the device, you'd need to follow the above with dir = opendir([I]directory containing the file referred to by fptr) to open the directory containing the file, then call fsync(dirfd(dir)) , and finally closedir(dir). This would make sure that the updates to the directory metadata, specifying the file you just updated, have hit the device too. (Otherwise it is possible that the directory updates are lost because you just yank power out from the flash device. The file data is on the device, but you cannot access it, since the directory data was not written to flash.)

    None of this should be necessary if you unmount the device prior to powering it off.

    EDIT:

    Quote Originally Posted by sanddune008 View Post
    As soon as the data is written(fwrite) i am reading(fread) the value.
    I am able to read the value and it is intact.
    You're only accessing page cache, not the actual device.

    Quote Originally Posted by sanddune008 View Post
    Now i do an fopen() which suceeds but fread() fails all the time with error "ENOENT"
    fread() does not set errno.

    I personally prefer to use low-level I/O (unistd.h) for this, as the error reporting is so much more detailed there. May I show you how I'd read and write to the file myself?
    Last edited by Nominal Animal; 12-06-2012 at 07:54 PM.

  4. #4
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Just realized that this:
    Quote Originally Posted by sanddune008 View Post
    Code:
    	mkdir(mStoredFreqIntervalDetails,(S_IROTH | S_IWOTH | S_IXOTH));
    creates a directory with access mode d------rwx, which denies access to both the user and the group. Please use
    Code:
    mkdir(mStoredFreqIntervalDetails, 0777);
    The 0777 means access is granted to everybody. Since the umask is applied, the actual access mode will be something sensible, typically drwxrwxr-x or drwxr-xr-x.

    Note that fopen() sets similar access mode internally, when it ends up creating a file.

    Perhaps this was the first occasion the code ended up creating the directory, and although the directory exists, the code cannot create a file in it.

  5. #5
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Here are the three POSIX.1-2008 C functions I would use for something like this:

    error = verify_directory(parent, directory);
    This function verifies that directory exists, relative to parent.
    If it does not, it will attempt to create it. The parent directory will be fsync()'d, so that the metadata should have hit the storage when the function returns.
    If successful, the function returns zero. Otherwise it returns a nonzero errno error code.

    error = read_carefully(directory, filename, data, length);
    This function reads length bytes from the start of file filename in directory directory, with an interface symmetric to write_carefully().
    If successful, the function returns zero. Otherwise it returns a nonzero errno error code.

    error = write_carefully(directory, filename, data, length);
    This function replaces the contents of file filename in directory directory with length bytes of data.
    If the file does not exist, it will be created. (The directory will not be automatically created.)
    The function will attempt to overwrite the file. If it fails, it will try to remove the file altogether, and fsync() the directory. This way either the contents of the file are in storage when the function returns, or if it cannot guarantee consistent file contents, it will have tried its best to remove the file from storage.
    If successful, the function returns zero, and both the file and the directory will have been fsync()'d to storage. Otherwise the function returns a nonzero errno error code.

    Code:
    #define  _POSIX_C_SOURCE 200809L
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <errno.h>
    
    static inline int opendirfd(const char *const directory)
    {
        int  descriptor;
    
        do {
            descriptor = open(directory, O_RDONLY | O_DIRECTORY);
        } while (descriptor == -1 && errno == EINTR);
    
        return descriptor;
    }
    
    static inline int closefd(const int descriptor)
    {
        int  result;
    
        do {
            result = close(descriptor);
        } while (result == -1 && errno == EINTR);
        if (result == -1)
            return errno;
        else
            return 0;
    }
    
    static inline int fsyncfd(const int descriptor)
    {
        int  result;
    
        do {
            result = fsync(descriptor);
        } while (result == -1 && errno == EINTR);
    
        if (result == -1)
            return errno;
        else
            return 0;
    }
    
    static inline int ftruncatefd(const int descriptor, off_t length)
    {
        int  result;
    
        do {
            result = ftruncate(descriptor, length);
        } while (result == -1 && errno == EINTR);
    
        if (result == -1)
            return errno;
        else
            return 0;
    }
    
    static inline int readfd(const int descriptor, void *const ptr, const size_t len)
    {
        unsigned char       *head = (unsigned char *)ptr;
        unsigned char *const tail = len + (unsigned char *)ptr;
        ssize_t              n;
    
        while (head < tail) {
    
            n = read(descriptor, head, (size_t)(tail - head));
    
            if (n > (ssize_t)0)
                head += n;
    
            else
            if (n == (ssize_t)0)
                return errno = ENOMSG; /* Not enough data available */
    
            else
            if (n != (ssize_t)-1)
                return errno = EIO;
    
            else
            if (errno != EINTR)
                return errno;
        }
    
        return 0;
    }
    
    static inline int writefd(const int descriptor, const void *const ptr, const size_t len)
    {
        const unsigned char       *head = (const unsigned char *)ptr;
        const unsigned char *const tail = len + (const unsigned char *)ptr;
        ssize_t                    n;
    
        while (head < tail) {
    
            n = write(descriptor, head, (size_t)(tail - head));
    
            if (n > (ssize_t)0)
                head += n;
    
            else
            if (n != (ssize_t)-1)
                return errno = EIO;
    
            else
            if (errno != EINTR)
                return errno;
        }
    
        return 0;
    }
    
    /* Make sure directory exists, creating it if necessary.
     * Returns 0 if successful, errno error code otherwise.
    */
    int verify_directory(const char *const parent,
                         const char *const directory)
    {
        int parentd, dird, saved_errno, result;
    
        /* NULL or empty parent directory name? */
        if (!parent || !*parent)
            return errno = EINVAL;
    
        /* NULL or empty directory name? */
        if (!directory || !*directory)
            return errno = EINVAL;
    
        saved_errno = errno;
    
        /* Open the parent directory. */
        parentd = opendirfd(parent);
        if (parentd == -1)
            return errno;
    
        /* Try opening the target directory, too. */
        do {
            dird = openat(parentd, directory, O_RDONLY | O_DIRECTORY);
        } while (dird == -1 && errno == EINTR);
        if (dird != -1) {
    
            /* Success; all done. */
            closefd(dird);
            closefd(parentd);
    
            errno = saved_errno;
            return 0;
        }
    
        /* Create the target directory. */
        do {
            result = mkdirat(parentd, directory, 0777);
        } while (result == -1 && errno == EINTR);
        if (result == -1) {
            saved_errno = errno;
            closefd(parentd);
            return errno = saved_errno;
        }
    
        /* Sync the parent directory. */
        result = fsyncfd(parentd);
        if (result) {
            closefd(parentd);
            return errno = result;
        }
    
        /* Close the parent directory. */
        if (closefd(parentd))
            return errno;
    
        /* Success. */
        errno = saved_errno;
        return 0;
    }
    
    /* Read data from a file in a specific directory.
     * Returns 0 if successful, errno error code otherwise.
    */
    int read_carefully(const char *const directory,
                       const char *const filename,
                       void *const data, const size_t size)
    {
        int  dird, fd, saved_errno;
    
        /* No directory specified? */
        if (!directory || !*directory)
            return errno = EINVAL;
    
        /* No filename specified? */
        if (!filename || !*filename)
            return errno = EINVAL;
    
        saved_errno = errno;
    
        /* Open the directory. */
        dird = opendirfd(directory);
        if (dird == -1)
            return errno;
    
        /* Open the file. */
        do {
            fd = openat(dird, filename, O_RDONLY | O_NOCTTY);
        } while (fd == -1 && errno == EINTR);
        if (fd == -1) {
            saved_errno = errno;
            closefd(dird);
            return errno = saved_errno;
        }
    
        /* Read the data. */
        if (readfd(fd, data, size)) {
            saved_errno = errno;
            closefd(fd);
            closefd(dird);
            return errno = saved_errno;
        }        
    
        /* Close file. */
        if (closefd(fd))
            return errno;
    
        /* Close directory. */
        if (closefd(dird))
            return errno;
    
        /* Success. */
        errno = saved_errno;
        return 0;
    }
    
    /* Write data to a file in a specific directory.
     * Returns 0 if successful, errno error code otherwise.
    */
    int write_carefully(const char *const directory,
                        const char *const filename,
                        const void *const data, const size_t size)
    {
        int  dird, fd;
        int  result, saved_errno;
    
        /* No directory specified? */
        if (!directory || !*directory)
            return errno = EINVAL;
    
        /* No filename specified? */
        if (!filename || !*filename)
            return errno = EINVAL;
    
        saved_errno = errno;
    
        /* Open the directory. */
        dird = opendirfd(directory);
        if (dird == -1)
            return errno;
    
        /* Open the file. Create if necessary. Do not truncate the file. */
        do {
            fd = openat(dird, filename, O_WRONLY | O_CREAT | O_NOCTTY, 0666);
        } while (fd == -1 && errno == EINTR);
        if (fd == -1) {
            saved_errno = errno;
            closefd(dird);
            return errno = saved_errno;
        }
    
        /* Write the new contents. */
        result = writefd(fd, data, size);
    
        /* Truncate to new size. */
        if (!result)
            result = ftruncatefd(fd, (off_t)size);
    
        /* Sync contents. */
        if (!result)
            result = fsyncfd(fd);
    
        /* Close file. */
        if (!result)
            result = closefd(fd);
        else
            closefd(fd);
    
        /* Failed? */
        if (result) {
            saved_errno = result;
    
            /* Remove partially overwritten file. */
            do {
                result = unlinkat(dird, filename, 0);
            } while (result == -1 && errno == EINTR);
    
            /* Make sure directory metadata is up to date. */
            fsyncfd(dird);
    
            /* Close directory. */
            closefd(dird);
    
            /* Return failure. */
            return errno = saved_errno;
        }
    
        /* Sync directory. */
        result = fsyncfd(dird);
        if (result) {
            closefd(dird);
            return errno = result;
        }
    
        /* Close directory. */
        if (closefd(dird))
            return errno;
    
        /* Success. */
        errno = saved_errno;
        return 0;
    }
    Questions?

  6. #6
    Registered User
    Join Date
    Apr 2009
    Posts
    145
    Thanks to all for your time and prompt reply......Let me digest all your comments and come back on this.......

  7. #7
    Registered User
    Join Date
    Apr 2009
    Posts
    145
    Thanks Nominal Animal for your time!!!!!

    Its working without creating an directory under the root(using mkdir).Now I am creating the file directly under the root directory and it is working.
    I had missed passing an fileno "fsync(fileno(fptr))" as i have been using it like this "fsync(fptr)" in my code could this had been the problem?

  8. #8
    Registered User
    Join Date
    Apr 2009
    Posts
    145
    I may have to investigate why the directory is not getting created........

    What i don't get is how come it was working these days and all of a sudden it stop? anyways i will try to figure this out.

  9. #9
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by sanddune008 View Post
    I may have to investigate why the directory is not getting created........ What i don't get is how come it was working these days and all of a sudden it stop?
    Check the directory and parent directory access mode, and mount options for the flash (just run mount). Linux will remount the filesystem read-only if there are problems writing to it; if that has happened, you'll see ro in the line corresponding to your flash media in the last column (in parentheses).

    I suspect one or more of the directories have just bad modes, something like d------rwx which allows everybody else but the owner user to modify the directory entries (create new files and so on). (If you habitually do stuff as root, you won't notice, because root is not bound by such trivialities.)

    In particular, if you have
    Code:
    dr-xrwxrwx  3 nominal animal 4096 Dec  7 00:00 /path/to/directory/
    drwxr-----  3 nominal animal    5 Dec  7 00:00 /path/to/directory/file
    then user nominal can modify the contents of the file, but not delete, rename or create a new file. Other users belonging to group animal can read the contents of the file, but not modify it; they can also delete or rename the file, and create a new one. Other users (not nominal, and not belonging to group animal) can delete or rename the file, and create new ones, but not read or write the existing one.

    Since everybody except user nominal is allowed to modify the directory, they can also change the access mode on the file. So this kind of setup is not really secure. But it does explain the symptoms you are seeing.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Using Flash with C++.
    By kakayoma in forum C++ Programming
    Replies: 17
    Last Post: 08-01-2009, 07:53 AM
  2. Get Flash
    By Queatrix in forum Tech Board
    Replies: 1
    Last Post: 09-04-2006, 07:19 PM
  3. Flash and PHP
    By ChadJohnson in forum Tech Board
    Replies: 2
    Last Post: 01-28-2006, 01:16 AM
  4. Flash Flash Revolution
    By Esparno in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 12-09-2002, 12:43 PM
  5. Flash <--> c++
    By c-- in forum C++ Programming
    Replies: 7
    Last Post: 09-13-2002, 11:26 PM