File Handling in Linux 3


2.6 How do I find out if a file has been updated by another process?

This is close to being a Frequently Unanswered Question, because people asking it are often looking for some notification from the system when a file or directory is changed, and there is no portable way of getting this. (IRIX has a non-standard facility for monitoring file accesses, but I've never heard of it being available in any other flavour.)
In general, the best you can do is to use fstat() on the file. (Note: the overhead on fstat() is quite low, usually much lower than the overhead of stat().) By watching the mtime and ctime of the file, you can detect when it is modified, or deleted/linked/renamed. This is a bit kludgy, so you might want to rethink why you want to do it.

2.7 How does the `du' utility work?

du simply traverses the directory structure calling stat() (or more accurately, lstat()) on every file and directory it encounters, adding up the number of blocks consumed by each.
If you want more detail about how it works, then the simple answer is:
Use the source, Luke!
Source for BSD systems (FreeBSD, NetBSD and OpenBSD) is available as unpacked source trees on their FTP distribution sites; source for GNU versions of utilities is available from any of the GNU mirrors, but you have to unpack the archives yourself.

2.8 How do I find the size of a file?

Use stat(), or fstat() if you have the file open.
These calls fill in a data structure containing all the information about the file that the system keeps track of; that includes the owner, group, permissions, size, last access time, last modification time, etc.
The following routine illustrates how to use stat() to get the file size.
#include <stdlib.h>
#include <stdio.h>
 
#include <sys/types.h>
#include <sys/stat.h>
 
int get_file_size(char *path,off_t *size)
{
  struct stat file_stats;
 
  if(stat(path,&file_stats))
    return -1;
 
  *size = file_stats.st_size;
  return 0;
}

2.9 How do I expand `~' in a filename like the shell does?

The standard interpretation for `~' at the start of a filename is: if alone or followed by a `/', then substitute the current user's home directory; if followed by the name of a user, then substitute that user's home directory. If no valid expansion can be found, then shells will leave the filename unchanged.
Be wary, however, of filenames that actually start with the `~' character. Indiscriminate tilde-expansion can make it very difficult to specify such filenames to a program; while quoting will prevent the shell from doing the expansion, the quotes will have been removed by the time the program sees the filename. As a general rule, do not try and perform tilde-expansion on filenames that have been passed to the program on the command line or in environment variables. (Filenames generated within the program, obtained by prompting the user, or obtained from a configuration file, are good candidates for tilde-expansion.)
Here's a piece of C++ code (using the standard string class) to do the job:
string expand_path(const string& path)
{
    if (path.length() == 0 || path[0] != '~')
      return path;
 
    const char *pfx = NULL;
    string::size_type pos = path.find_first_of('/');
 
    if (path.length() == 1 || pos == 1)
    {
        pfx = getenv("HOME");
        if (!pfx)
        {
            // Punt. We're trying to expand ~/, but HOME isn't set
            struct passwd *pw = getpwuid(getuid());
            if (pw)
              pfx = pw->pw_dir;
        }
    }
    else
    {
        string user(path,1,(pos==string::npos) ? string::npos : pos-1);
        struct passwd *pw = getpwnam(user.c_str());
        if (pw)
          pfx = pw->pw_dir;
    }
 
    // if we failed to find an expansion, return the path unchanged.
 
    if (!pfx)
      return path;
 
    string result(pfx);
 
    if (pos == string::npos)
      return result;
 
    if (result.length() == 0 || result[result.length()-1] != '/')
      result += '/';
 
    result += path.substr(pos+1);
 
    return result;
}
 
 

To Look for similar posts on File handling in Linux explore the following links from the same blog as well.
 

Post a Comment

Previous Post Next Post