www.pudn.com > efs.rar > fs_ext_linux.c
/* Linux based external filesystem for EFS2.
*
* Copyright (C) 2004, 2005, 2006 Qualcomm, Inc.
*
* NOTE: Currently, this code is more of an example of how to use the EFS2
* extfs functionality. The only reason this is somewhat Linux specific is
* that the values for the definitions are assumed to match between Linux
* and EFS2.
*/
/* This is SAMPLE source code only. This file is not to be compiled
* into any Qualcomm build. */
#if 0 /* EXAMPLE ONLY */
/*===========================================================================
EDIT HISTORY FOR MODULE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
$$Header: //depot/asic/MSMSHARED/services/efs/MSM_EFS.01.02/fs_ext_linux.c#5 $$ $$DateTime: 2006/05/08 11:49:02 $$ $$Author: davidb $$
when who what, where, why
---------- --- ---------------------------------------------------------
2006-05-07 sh Fixed hardalloc vs -1 compiler warning
2006-01-11 nrs Fixed Copyright header
2005-12-22 dlb Extensions to statvfs results.
2005-12-09 sh Clarified status of Example Code
2005-06-06 dlb Create
===========================================================================*/
#include "fs_extfs.h"
#include "fs_errno.h"
#include "fs_err.h"
/* Headers needed to get prototypes. */
#include
#include
#include
#include
#include
#include
/* This only works because these are defined with the same values. */
#include
/* Can't bring in errno, since the definitions conflict with ours. This is
* very Linux specific. */
extern int *__errno_location (void) __attribute__ ((__const__));
#define errno (*__errno_location ())
/* These routines are all expected to return EFS2 error codes. The return
* result should either be 0 for success, or a negative error value. */
static int
e_linux_init (const char *name)
{
(void) name;
return 0;
}
/* base_stat:
* Used to determine the fundamental type of the file. For regular files,
* it should also fill in the size of the file. */
static int
e_linux_base_stat (const char *name, fs_mode_t *mode, fs_size_t *size)
{
struct stat sbuf;
int result;
result = lstat (name, &sbuf);
if (result != 0)
return -errno; /* Remap... */
*mode = sbuf.st_mode;
*size = sbuf.st_size;
return 0;
}
static int
e_linux_open (const char *name, int mode)
{
int result;
switch (mode) {
case O_RDONLY:
case O_RDWR:
result = open (name, mode);
break;
case (O_CREAT | O_EXCL | O_RDWR):
result = open (name, mode, 0644);
break;
default:
FS_ERR_FATAL ("Invalid internal mode used", 0, 0, 0);
}
if (result < 0)
result = -errno;
return result;
}
static int
e_linux_lseek (int fd, fs_off_t pos)
{
int result;
result = lseek (fd, pos, SEEK_SET);
if (result == (off_t) -1)
result = -errno;
return 0;
}
static int
e_linux_read (int fd, void *buf, fs_size_t count)
{
int result;
result = read (fd, buf, count);
if (result < 0)
result = -errno;
return result;
}
static int
e_linux_write (int fd, const void *buf, fs_size_t count)
{
int result;
result = write (fd, buf, count);
if (result < 0)
result = -errno;
return result;
}
static int
e_linux_close (int fd)
{
int result;
result = close (fd);
if (result != 0)
result = -errno;
return result;
}
static int
e_linux_mkdir (const char *name)
{
int result;
result = mkdir (name, 0755);
if (result != 0)
result = -errno;
return result;
}
static int
e_linux_rmdir (const char *name)
{
int result;
result = rmdir (name);
if (result != 0)
result = -errno;
return result;
}
static int
e_linux_unlink (const char *name)
{
int result;
result = unlink (name);
if (result != 0)
result = -errno;
return result;
}
static int
e_linux_rename (const char *oldname, const char *newname)
{
int result;
result = rename (oldname, newname);
if (result != 0)
result = -errno;
return result;
}
static int
e_linux_statvfs (const char *name, struct fs_statvfs *buf)
{
int result;
struct statvfs pbuf;
static uint32 avail_offset = 0;
result = statvfs (name, &pbuf);
if (result == 0) {
/* Offset the size so that we don't try filling up the entire
* filesystem. */
if (avail_offset == 0) {
avail_offset = pbuf.f_bavail - (120*1024*1024 / pbuf.f_bsize);
}
/* Copy the appropriate fields over. */
buf->f_bsize = pbuf.f_bsize;
buf->f_blocks = 128*1024*1024 / pbuf.f_bsize;
buf->f_bfree = pbuf.f_bfree - avail_offset;
buf->f_bavail = pbuf.f_bavail - avail_offset;
buf->f_files = pbuf.f_files;
buf->f_ffree = pbuf.f_ffree;
buf->f_favail = pbuf.f_favail;
buf->f_fsid = pbuf.f_fsid;
buf->f_flag = pbuf.f_flag;
buf->f_namemax = pbuf.f_namemax;
buf->f_balloc = 0;
buf->f_hardalloc = FS_INVALID_HARDALLOC;
} else {
/* Translate errno. */
/* ... */
result = -errno;
}
return result;
}
/* Directory operations. */
static void *
e_linux_opendir (const char *name)
{
return opendir (name);
}
static int
e_linux_readdir (void *dir, char *name, int max_name)
{
struct dirent *dent;
dent = readdir (dir);
if (dent != NULL) {
if (strlen (dent->d_name) + 1 > (unsigned) max_name)
/* Ideally, we want to be able to iterate past the name that is too
* long. */
return -ENAMETOOLONG;
strcpy (name, dent->d_name);
return 0;
} else {
return -EEOF;
}
}
static int
e_linux_closedir (void *dir)
{
int result;
result = closedir (dir);
if (result != 0)
result = -errno;
return result;
}
static int
e_linux_getstat (const char *name, struct fs_stat *buf)
{
struct stat sbuf;
int result;
uint32 atime, ctime, mtime;
result = lstat (name, &sbuf);
if (result != 0) {
return -errno;
} else {
/* Note that 'dev' and 'inum' aren't filled in. They have already been
* set to valid values, and can be left alone if they don't make sense.
* Also, dev shouldn't be set, since we want the EFS2 internal value,
* not the local filesystem's concept. */
buf->st_mode = sbuf.st_mode;
buf->st_nlink = sbuf.st_nlink;
buf->st_size = sbuf.st_size;
buf->st_blksize = sbuf.st_blksize;
buf->st_blocks = sbuf.st_blocks;
/* Ugh, the linux headers are annoying here. */
atime = sbuf.st_atime;
mtime = sbuf.st_mtime;
ctime = sbuf.st_ctime;
#undef st_atime
#undef st_mtime
#undef st_ctime
buf->st_atime = atime;
buf->st_mtime = mtime;
buf->st_ctime = ctime;
return 0;
}
}
struct fs_extfs_ops fs_linux_ops = {
e_linux_init,
e_linux_base_stat,
e_linux_getstat,
e_linux_open,
e_linux_lseek,
e_linux_read,
e_linux_write,
e_linux_close,
e_linux_mkdir,
e_linux_rmdir,
e_linux_unlink,
e_linux_rename,
e_linux_statvfs,
e_linux_opendir,
e_linux_readdir,
e_linux_closedir,
};
#else
extern int unused_filler_for_empty_file;
#endif /* EXAMPLE CODE ONLY */