/*******************************************************************************
* header file
* int open( const char* filename, int oflag, ... ); O_CREAT->[mode_t mode]
* e.g. open( "~/tmp.dat", O_RDWR|O_CREAT|O_EXCL, 0755 );
* note: return fd >= 0 when success.
* oflag:
* O_RDONLY,O_WRONLY,O_RDWR
*
* O_APPEND: append at tail
* O_CREAT: create when non-exist
* O_EXCL: together with O_CREAT, if exist, open fail, else create
* O_NDELAY: non-block for FIFO or SOCKET
* O_NONBLOCK: rw return without waiting
* O_NOCTTY: flag for TTY
* O_TRUNC: if regular file exists, clear file to 0B even O_RDONLY
*
* O_DSYNC: block when write file
* O_SYNC: block when writing, and update atime, mtime, ctime
* O_RSYNC|O_DSYNC: same with O_DSYNC when writing (set R flag)
* O_RSYNC|O_SYNC: same with O_SYNC when writing (set R flag)
* mode: when create file, mode & (~umask)
* S_IRWX[UGO]: 0700, 0070, 0007
* S_IRUSR[GRP OTH]: 0400, 0040, 0004
* S_IWUSR[GRP OTH]: 0200, 0020, 0002
* S_IXUSR[GRP OTH]: 0100, 0010, 0001
* int fcntl( int fildes, int cmd, ... );
* int fcntl( int fildes, int cmd );
* cmd: F_GETFD, F_GETFL, F_GETOWN.(fd tag, oflag, get SIG pid,gid)
* int fcntl( int fildes, int cmd, int arg );
* cmd: F_SETFD, F_SETFL, F_SETOWN, F_DUPFD.(set arg)
* int fcntl( int fildes, int cmd, struct flock *arg );
* cmd: F_GETLK, F_SETLK, F_SETLKW.(F_SETLKW is blocked F_SETLK)
* struct flock
* {
* short l_type; F_RDLCK, F_WRLCK, F_UNLCK
* short l_whence; SEEK_SET, SEEK_CUR, SEEK_END
* long l_start; offset of lock start position
* long l_len; lock length, 0 means locking to file end
* short l_pid; the pid of lock owner
* }
* header file
* int close( int fides ); return 0(success) or -1
* int unlink( char *path ); only rm file when lnk=0, return 0 or -1
*
* ssize_t read( int fildes, void *buf, size_t nbytes );
* ssize_t write( int fildes, void *buf, size_t nbytes );
* int fsync( int fildes ); similar to fflush(), return 0 or -1(failed)
*
* off_t lseek( int fildes, off_t offset, int whence );
*
* int dup( int fildes ); return new file descriptor, or -1( failed )
* int dup2( int fildes, int fildes2 ); dup2(2,fd), stderr>fd, redirect
* note:
* dup() duplicates fildes to available least file descriptor.
* dup2() duplicates fildes to fildes2, if fildes2 is open, close it.
*
*******************************************************************************/
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <memory.h>
#include <signal.h>
#include <assert.h>
int main( int ac, char *av[] )
{
int fd;
char buf[50], *cmd = "ls -l tmp.dat";
if ( (fd=open("./tmp.dat", O_RDWR|O_CREAT|O_EXCL, 0755)) < 0 )
{
fprintf( stderr, "open file tmp.dat error!\n" );
return 1;
}
memset( buf, 0, sizeof(buf) );
printf( "\nCreate file tmp.dat successfully, Now check it.\n" );
printf( "%s\n", cmd );
system( cmd );
printf( "\nWrite %d bytes.\n\t%s\n", write(fd, cmd, strlen(cmd)), cmd );
printf( "\nWriting finished. Now read from file:\n" );
fsync(1); //fflush(stdout);
sleep(3);
lseek( fd, 0, SEEK_SET );
printf( "\nRead %d bytes.\n", read(fd, buf, sizeof(buf)) );
printf( "\t%s\n\n", buf );
close( fd );
unlink("./tmp.dat");
printf("Remove it after checking.\n\n");
extern void testlck(void);
extern void testrw(void);
testlck();
testrw();
return 0;
}
/*******************************************************************************
* file lock functions lib *
*******************************************************************************/
int seelck( int fd, int start, int len )
{
struct flock arg;
arg.l_type = F_WRLCK;
arg.l_whence = SEEK_SET;
arg.l_start = start;
arg.l_len = len;
if ( fcntl(fd, F_GETLK, &arg) == -1 )
{
fprintf( stderr, "See lock failed.\n" );
return 0; /* get lock info failed */
}
else if ( arg.l_type == F_UNLCK )
{
fprintf( stderr, "No lock from %d to %d\n", start, len );
}
else if ( arg.l_type == F_WRLCK )
{
fprintf( stderr, "Write lock from %d to %d by pid = %d.\n",
start, len, arg.l_pid );
}
else if ( arg.l_type == F_RDLCK )
{
fprintf( stderr, "Read lock from %d to %d by pid = %d.\n",
start, len, arg.l_pid );
}
return 1;
}
int readlck( int fd, int start, int len ) /* get read lock, if get, return 1 */
{
struct flock arg;
arg.l_type = F_RDLCK;
arg.l_whence = SEEK_SET;
arg.l_start = start;
arg.l_len = len;
if ( fcntl(fd, F_SETLKW, &arg) == -1 )
{
fprintf( stderr, "[%d] set read lock failed.\n", getpid() );
return 0;
}
else
{
fprintf(stderr, "[%d] set read lock from %d to %d.\n",
getpid(), start, len );
return 1;
}
}
int writelck( int fd, int start, int len ) /* get write lock, failed return 0 */
{
struct flock arg;
arg.l_type = F_WRLCK;
arg.l_whence = SEEK_SET;
arg.l_start = start;
arg.l_len = len;
if ( fcntl(fd, F_SETLKW, &arg) == -1 )
{
fprintf( stderr, "[%d] set write lock failed.\n", getpid() );
return 0;
}
else
{
fprintf(stderr, "[%d] set write lock from %d to %d.\n",
getpid(), start, len );
return 1;
}
}
int releaselck( int fd, int start, int len ) /* release lock, return 1 or 0 */
{
struct flock arg;
arg.l_type = F_UNLCK;
arg.l_whence = SEEK_SET;
arg.l_start = start;
arg.l_len = len;
if ( fcntl(fd, F_SETLKW, &arg) == -1 )
{
fprintf( stderr, "[%d] release lock failed.\n", getpid() );
return 0;
}
else
{
fprintf(stderr, "[%d] release lock from %d to %d.\n",
getpid(), start, len );
return 1;
}
}
void testlck()
{
int fd;
struct flock arg;
if ( (fd = open("./tmp.dat", O_RDWR|O_CREAT|O_EXCL, 0755)) < 0 )
{
fprintf( stderr, "open file ./tmp.dat failed.\n" );
return;
}
seelck( fd, 0, 10 );
readlck( fd, 0, 10 );
seelck( fd, 11, 20 );
writelck( fd, 11, 20 );
sleep(2);
releaselck( fd, 0, 10 );
releaselck( fd, 11, 20 );
close(fd);
remove("./tmp.dat");
return;
}
/*******************************************************************************
* blocked R/W functions lib *
*******************************************************************************/
int readf( int fd, void *buf, int size )
{
int readcnt = 0, leftcnt = size; /* counter of read and left bytes */
char *curbuf = buf; /* pointer of current buffer */
assert( buf != NULL );
while ( leftcnt > 0 )
{ /* if don't read size bytes, block here */
if ( (readcnt = read(fd, curbuf, leftcnt)) < 0 )
{
if ( errno != EINTR )
{
errno = 0;
return -1;
}
errno = 0;
readcnt = 0;
continue;
}
else if ( readcnt == 0 ) /* reach EOF */
return EOF;
leftcnt -= readcnt;
curbuf += readcnt;
}
return 0;
}
int writef( int fd, void * buf, int size)
{
int leftcnt = size, writecnt;
char *curbuf = buf;
assert( buf != NULL );
while ( leftcnt > 0 )
{
if ( (writecnt = write(fd, curbuf, leftcnt)) <= 0 )
{
if ( errno != EINTR )
{
errno = 0;
return -1;
}
errno = 0;
writecnt = 0;
continue;
}
leftcnt -= writecnt;
curbuf += writecnt;
}
return 0;
}
void testrw()
{
char buf[10];
int size = sizeof(buf);
memset(buf, 0, size);
printf("Now test block read/write, please enter some thing\n");
readf(0, buf, size);
writef(1, buf, size);
return;
}
|