I have 2 files and i want each core read its own file ( each file has 5 lines ) and display its content
in this code I have 2 cores ( core0 , core1) the output core 0 read the content of core1 ( 5 lines ). and core1 read 4 lines from his content.
I tried to make it as if else conditions and each file has its own reader but the same problem still exist.what should i do ?
#include <vector>
#include <stdio.h>
#include <time.h>
#include <mpi.h>
#include <omp.h>
#include <fstream>
#include <iostream>
using namespace std;
void func2(int CoreID )
{
int iFace;
int iFaces=0;
if (CoreID==0)
{
FILE* imgListFile = 0;
char imgFilename[5012];
char actualPath[90]="C:\\DaliaDaliaSh\\TrainingFiles\\File10img_0_C";
strcat(actualPath , "0.txt");
imgListFile= freopen(actualPath , "r",stdin);
while (fgets(imgFilename, 5012, imgListFile))
{
++iFaces;
printf( "** Core = %d , Path = %s\n" , CoreID , imgFilename );
}
rewind(imgListFile);
}
else if (CoreID==1)
{
FILE* imgListFile2 = 0;
char imgFilename2[5012];
char actualPath2[90]="C:\\DaliaDaliaSh\\TrainingFiles\\File10img_0_C";
strcat(actualPath2 , "1.txt");
imgListFile2= freopen(actualPath2 , "r",stdin);
while (fgets(imgFilename2, 5012, imgListFile2))
{
++iFaces;
printf( "** Core = %d , Path = %s\n" , CoreID , imgFilename2 );
}
rewind(imgListFile2);
}
//printf ("*ID = %d open actualPath= %s\n" , myId , actualPath);
printf("core %d , iFaces= %d \n", CoreID , iFaces);
}
void main(int argc,char **argv)
{
MPI::Init(argc,argv);
int threadnum=2;
omp_set_num_threads(threadnum);
#pragma omp parallel
{
int CoreID = omp_get_thread_num();
int x ;
func2(CoreID);
cout <<"####after call func inside pragma \n" ;
}
MPI ::Finalize();
}
You are doing freopen on stdin. Thus, both cores will use the same stream and the file read will depend upon which core opened the stream first/last [which is a race condition].
Do a regular fopen instead and they won't conflict [as they're doing now]
Related
The code below was written for Linux and uses open, read, write and close. I am working on a Windows computer where I normally use fopen, fgets, fputs, fclose. Right now I get a no prototype error for open, read, write and close. Is there a header file I can include to make this work on a Windows computer or do I need to convert the code? Can you show how to convert it so it works the same on Windows or at least point me to an online document which shows how to convert it?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef unix
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define NB 8192
char buff[NB];
int
main(argc,argv)
int argc;
char **argv;
{
int fdi, fdo, i, n, m;
char *p, *q;
char c;
if( argc > 0 )
printf( "%s: Reverse bytes in 8-byte values \n", argv[0] );
if( argc > 1 )
strcpy( buff, argv[1] );
else
{
printf( "Input file name ? " );
gets( buff );
}
fdi = open( buff, O_BINARY | O_RDONLY, S_IREAD );
if( fdi <= 0 )
{
printf( "Can't open <%s>\n", buff );
exit(2);
}
if( argc > 2 )
strcpy( buff, argv[2] );
else
{
printf( "Output file name ? " );
gets( buff );
}
fdo = open( buff, O_BINARY | O_RDWR | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE );
if( fdo <= 0 )
{
printf( "Can't open <%s>\n", buff );
exit(2);
}
while( (n = read( fdi, buff, NB )) > 0 )
{
m = n / 8;
p = buff;
q = buff+7;
for( i=0; i<m; i++ )
{
c = *p;
*p++ = *q;
*q-- = c;
c = *p;
*p++ = *q;
*q-- = c;
c = *p;
*p++ = *q;
*q-- = c;
c = *p;
*p++ = *q;
*q-- = c;
p += 4;
q += 12;
}
write( fdo, buff, n );
}
close( fdo );
close( fdi );
exit(0);
}
Microsoft directly supports POSIX-style low-level IO calls such as open(), read(), , write(), and close(); although with what appears to be a misleading "deprecated" characterization.
The required header is <io.h>.
The calls correspond to functions named with a preceeding underscore, so open() maps to _open().
The full list of supported "low-level" IO functions Microsoft supports are:
Low-Level I/O
Low-Level I/O Functions
Function Use
_close Close file
_commit Flush file to disk
_creat, _wcreat Create file
_dup Return next available file descriptor for given file
_dup2 Create second descriptor for given file
_eof Test for end of file
_lseek, _lseeki64 Reposition file pointer to given location
_open, _wopen Open file
_read Read data from file
_sopen, _wsopen, _sopen_s, _wsopen_s Open file for file sharing
_tell, _telli64 Get current file-pointer position
_umask, _umask_s Set file-permission mask
_write Write data to file
Some of the low-level functions may not have a non-underscore, POSIX-style equivalent name.
The corresponding functions in Windows use the same name but with an underscore (_) prepended to the name.
open -> _open
close -> _close
etc.
They are declared in the header io.h. See https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx for the list of all supported functions.
Borland C++ Builder encapsulated binary file access functions into:
FileOpen
FileCreate
FileRead
FileWrite
FileSeek
FileClose
Here simple example of loading text file:
BYTE *txt=NULL; int hnd=-1,siz=0;
hnd = FileOpen("textfile.txt",fmOpenRead);
if (hnd!=-1)
{
siz=FileSeek(hnd,0,2); // position to end of file (0 bytes from end) and store the offset to siz which means size of file
FileSeek(hnd,0,0); // position to start of file (0 bytes from start)
txt = new BYTE[siz];
FileRead(hnd,txt,siz); // read siz bytes to txt buffer
FileClose(hnd);
}
if (txt!=NULL)
{
// here do your stuff with txt[siz] I save it to another file
hnd = FileCreate("output.txt");
if (hnd!=-1)
{
FileWrite(hnd,txt,siz); // write siz bytes to txt buffer
FileClose(hnd);
}
delete[] txt;
}
IIRC All these are part of VCL so in case you are using console you need to set VCL include check during the project creation or include it manually.
Pseudo code:
for(int i=0;i<m_iNumOfClass;i++) {
char str[200];
if(iterk doesn't exist)
sprintf(str, "iterk\\HMMtransiMean%d.txt", i);
iter(iterk exist)
mkdir(iterk+1)
sprintf(str, "iterk+1\\HMMtransiMean%d.txt", i);
}
This is pseudo code what i want to do.
I want to create a folder named iterk1 if it doesn't exist. But if it exist, I create a folder named iterk2. and then, create a txt file named HMMtransiMean%d in that folder created just now.
How can i do it? please help me.
If you can use boost::filesystem (as πάντα ῥεῖ advice) then :
#include <string>
#include <fstream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main()
{
int m_iNumOfClass(2);
path path_template("/tmp"); //Maybe you should use "C:\\tmp" instead
path_template /= "iter";
path directory;
for(int i=0; i<m_iNumOfClass; i++) {
int directory_index = 0;
do
{
directory_index++;
directory = path_template;
directory += std::to_string(directory_index);
} while (!create_directory(directory));
directory /= "HMMtransiMean";
directory += std::to_string(i) + ".txt";
std::string filename(directory.string());
std::ofstream outfile (filename);
outfile.close();
}
return 0;
}
Note: This solution does not require boost...
I assume you're using windows platform (because you use "\\"):
The first useful function to consider is _mkdir (doc).
You can use the non-zero value to determine whether the folder was created.
To create a file you can use fopen (doc)
This works for me on Windows but should work on Linux as well(with a minor include change from direct.h to #include <sys/stat.h>
and #include <sys/types.h> to have mkdir):
#include <iostream>
#include <sstream>
#include <direct.h>
#include <cstdio>
#include <string>
using namespace std;
int main() {
const string pref = "iterk";
string path = pref;
stringstream suffix;
int i=0;
int res = -1;
do{
res = mkdir(path.c_str());
if( res == 0){
path = path + "/HMMtransiMean" + suffix.str() + ".txt";
break;
}
else{
++i;
suffix.str(string());
suffix << i;
path = pref + suffix.str();
}
} while (EEXIST == errno);
FILE * stream;
if( (stream = fopen(path.c_str(), "w+" )) == NULL ) // C4996
printf( "The file was not opened\n" );
else
printf( "The file was opened\n" );
string data = "Hi";
int numwritten = fwrite( data.c_str() , sizeof( char ), data.length() , stream );
printf( "Wrote %d items\n", numwritten );
fclose( stream );
return 0;
}
If you use it on windows only you should probably use the _mkdir function (as I noted before).
I need a C/C++ API that allows me to list the running processes on a Linux system, and list the files each process has open.
I do not want to end up reading the /proc/ file system directly.
Can anyone think of a way to do this?
http://procps.sourceforge.net/
http://procps.cvs.sourceforge.net/viewvc/procps/procps/proc/readproc.c?view=markup
Is the source of ps and other process tools. They do indeed use proc (indicating it is probably the conventional and best way). Their source is quite readable. The file
/procps-3.2.8/proc/readproc.c
May be useful. Also a useful suggestion as posted by ephemient is linking to the API provided by libproc, which should be available in your repo (or already installed I would say) but you will need the "-dev" variation for the headers and what-not.
Good Luck
If you do not want to read from '/proc. Then you can consider writing a Kernel module which will implement your own system call. And your system call should be written so that it can obtain the list of current processes, such as:
/* ProcessList.c
Robert Love Chapter 3
*/
#include < linux/kernel.h >
#include < linux/sched.h >
#include < linux/module.h >
int init_module(void) {
struct task_struct *task;
for_each_process(task) {
printk("%s [%d]\n",task->comm , task->pid);
}
return 0;
}
void cleanup_module(void) {
printk(KERN_INFO "Cleaning Up.\n");
}
The code above is taken from my article here at http://linuxgazette.net/133/saha.html.Once you have your own system call, you can call it from your user space program.
Here you go (C/C++):
You could have found it here:
http://ubuntuforums.org/showthread.php?t=657097
Essentially, what it does is loop through all numeric folders in /proc/<pid>, and then it does a readlink on /proc/<pid>/exe, or if you want the command-line-arguments cat /proc/<pid>/cmdline
The file-descriptors open by the process are in /proc/<pid>/fd/<descriptor>, and you get the file name by doing a readlink on each symlink, e.g. readlink /proc/<pid>/fd/<descriptor>. fd can be a device, such as /dev/null, a socket, or a file, and potentially more.
#include <unistd.h>
ssize_t readlink(const char *path, char *buf, size_t bufsiz);
On success, readlink() returns the number of bytes placed in buf.
On error, -1 is returned and errno is set to indicate the error.
This is, by the way, the same that readproc.c does (or at least did).
Of course, hopefully they did it without buffer overflow possiblity.
#ifndef __cplusplus
#define _GNU_SOURCE
#endif
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h> // for opendir(), readdir(), closedir()
#include <sys/stat.h> // for stat()
#ifdef __cplusplus
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdarg>
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#endif
#define PROC_DIRECTORY "/proc/"
#define CASE_SENSITIVE 1
#define CASE_INSENSITIVE 0
#define EXACT_MATCH 1
#define INEXACT_MATCH 0
int IsNumeric(const char* ccharptr_CharacterList)
{
for ( ; *ccharptr_CharacterList; ccharptr_CharacterList++)
if (*ccharptr_CharacterList < '0' || *ccharptr_CharacterList > '9')
return 0; // false
return 1; // true
}
int strcmp_Wrapper(const char *s1, const char *s2, int intCaseSensitive)
{
if (intCaseSensitive)
return !strcmp(s1, s2);
else
return !strcasecmp(s1, s2);
}
int strstr_Wrapper(const char* haystack, const char* needle, int intCaseSensitive)
{
if (intCaseSensitive)
return (int) strstr(haystack, needle);
else
return (int) strcasestr(haystack, needle);
}
#ifdef __cplusplus
pid_t GetPIDbyName(const char* cchrptr_ProcessName, int intCaseSensitiveness, int intExactMatch)
#else
pid_t GetPIDbyName_implements(const char* cchrptr_ProcessName, int intCaseSensitiveness, int intExactMatch)
#endif
{
char chrarry_CommandLinePath[100] ;
char chrarry_NameOfProcess[300] ;
char* chrptr_StringToCompare = NULL ;
pid_t pid_ProcessIdentifier = (pid_t) -1 ;
struct dirent* de_DirEntity = NULL ;
DIR* dir_proc = NULL ;
int (*CompareFunction) (const char*, const char*, int) ;
if (intExactMatch)
CompareFunction = &strcmp_Wrapper;
else
CompareFunction = &strstr_Wrapper;
dir_proc = opendir(PROC_DIRECTORY) ;
if (dir_proc == NULL)
{
perror("Couldn't open the " PROC_DIRECTORY " directory") ;
return (pid_t) -2 ;
}
// Loop while not NULL
while ( (de_DirEntity = readdir(dir_proc)) )
{
if (de_DirEntity->d_type == DT_DIR)
{
if (IsNumeric(de_DirEntity->d_name))
{
strcpy(chrarry_CommandLinePath, PROC_DIRECTORY) ;
strcat(chrarry_CommandLinePath, de_DirEntity->d_name) ;
strcat(chrarry_CommandLinePath, "/cmdline") ;
FILE* fd_CmdLineFile = fopen (chrarry_CommandLinePath, "rt") ; // open the file for reading text
if (fd_CmdLineFile)
{
fscanf(fd_CmdLineFile, "%s", chrarry_NameOfProcess) ; // read from /proc/<NR>/cmdline
fclose(fd_CmdLineFile); // close the file prior to exiting the routine
if (strrchr(chrarry_NameOfProcess, '/'))
chrptr_StringToCompare = strrchr(chrarry_NameOfProcess, '/') +1 ;
else
chrptr_StringToCompare = chrarry_NameOfProcess ;
//printf("Process name: %s\n", chrarry_NameOfProcess);
//printf("Pure Process name: %s\n", chrptr_StringToCompare );
if ( CompareFunction(chrptr_StringToCompare, cchrptr_ProcessName, intCaseSensitiveness) )
{
pid_ProcessIdentifier = (pid_t) atoi(de_DirEntity->d_name) ;
closedir(dir_proc) ;
return pid_ProcessIdentifier ;
}
}
}
}
}
closedir(dir_proc) ;
return pid_ProcessIdentifier ;
}
#ifdef __cplusplus
pid_t GetPIDbyName(const char* cchrptr_ProcessName)
{
return GetPIDbyName(cchrptr_ProcessName, CASE_INSENSITIVE, EXACT_MATCH) ;
}
#else
// C cannot overload functions - fixed
pid_t GetPIDbyName_Wrapper(const char* cchrptr_ProcessName, ... )
{
int intTempArgument ;
int intInputArguments[2] ;
// intInputArguments[0] = 0 ;
// intInputArguments[1] = 0 ;
memset(intInputArguments, 0, sizeof(intInputArguments) ) ;
int intInputIndex ;
va_list argptr;
va_start( argptr, cchrptr_ProcessName );
for (intInputIndex = 0; (intTempArgument = va_arg( argptr, int )) != 15; ++intInputIndex)
{
intInputArguments[intInputIndex] = intTempArgument ;
}
va_end( argptr );
return GetPIDbyName_implements(cchrptr_ProcessName, intInputArguments[0], intInputArguments[1]);
}
#define GetPIDbyName(ProcessName,...) GetPIDbyName_Wrapper(ProcessName, ##__VA_ARGS__, (int) 15)
#endif
int main()
{
pid_t pid = GetPIDbyName("bash") ; // If -1 = not found, if -2 = proc fs access error
printf("PID %d\n", pid);
return EXIT_SUCCESS ;
}
If you don't do it, then I guess whatever API you will use will end up reading the /proc filesystem. Here are some examples of program doing this:
qps
htop
procps
But unfortunately, that does not constitute an API.
PS and every other tool(EXCEPT for Kernel Modules) read from /proc. /proc is a special filesystem created on the fly by the kernel so that user mode processes can read data that will otherwise only be available for the kernel.
The recommended way is therefore, reading from /proc.
You can quickly intuitively look at the /proc filesystem to see how its structured.
For every process there is a /proc/pid where pid is the process id number. Inside this folder there are several files which include different data about the current process.
If you run
strace ps -aux
you will see how the program ps reads this data from /proc.
The only way to do this without reading /proc would be to call "ps aux", go through every line, read the second column (the PID) and call lsof -p [PID] with it.
...I'd suggest reading /proc ;)
There's a library libprocps from the procps-ng project. On Ubuntu 13.04, if you do strace ps, then you can see that ps uses libprocps.
Reading proc is not too bad. I can't show you in C++, but the following D code should point you in the right direction:
import std.stdio;
import std.string;
import std.file;
import std.regexp;
import std.c.linux.linux;
alias std.string.split explode;
string srex = "^/proc/[0-9]+$";
string trex = "State:[ \t][SR]";
RegExp rex;
RegExp rext;
string[] scanPidDirs(string target)
{
string[] result;
bool callback(DirEntry* de)
{
if (de.isdir)
{
if (rex.find(de.name) >= 0)
{
string[] a = explode(de.name, "/");
string pid = a[a.length-1];
string x = cast(string) std.file.read(de.name ~ "/status");
int n = rext.find(x);
if (n >= 0)
{
x = cast(string) std.file.read(de.name ~ "/cmdline");
// This is null terminated
if (x.length) x.length = x.length-1;
a = explode(x, "/");
if (a.length)
x = a[a.length-1];
else
x = "";
if (x == target)
{
result ~= pid ~ "/" ~x;
}
}
}
}
return true;
}
listdir("/proc", &callback);
return result.dup;
}
void main(string[] args)
{
rex= new RegExp(srex);
rext= new RegExp(trex);
string[] a = scanPidDirs(args[1]);
if (!a.length)
{
writefln("Not found");
return;
}
writefln("%d matching processes", a.length);
foreach (s; a)
{
string[] p = explode(s, "/");
int pid = atoi(p[0]);
writef("Stop %s (%d)? ", s, pid);
string r = readln();
if (r == "Y\n" || r == "y\n")
kill(pid, SIGUSR1);
}
}
Easy way to fin pid of any process by name
pid_t GetPIDbyName(char* ps_name)
{
FILE *fp;
char *cmd=(char*)calloc(1,200);
sprintf(cmd,"pidof %s",ps_name);
fp=popen(cmd,"r");
fread(cmd,1,200,fp);
fclose(fp);
return atoi(cmd);
}
i need to print events on a folder with multiple subfolders. how to do it recursivly? Please print a c++ code. I am stucked!! Every time the evet is poped i need to open the subfolder, take the file and copy it into another directory. I don't want to list all the subfolders in every 2 seconds and find the files if there are any. Is not efficient. I need to use a monitor folder. Please help
The director that i want to monitor has multiple subfolders. Each subfolder has another subfolder that could contain in a moment of time a file. MainFolder->Subfolders->each subfolder-> subfolder -> file.
Here is the code I have for he moment:
/*
*/
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <sys/inotify.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
using namespace std;
vector<string> SS;
void *print_message_function( void *ptr );
int main(int argc, char **argv ){
pthread_t t1;
int fd,fd1,wd,wd1,i=0,i1=0,len=0,len1=0;
int length;
char pathname[100],buf[1024],buf1[1024];
int data;
struct inotify_event *event;
char *message1 = "Thread 1";
FILE *fr;
// fd=inotify_init1(IN_NONBLOCK);//--rewrite
fd = inotify_init();
/* watch /test directory for any activity and report it back to me */
wd=inotify_add_watch(fd,"/home/MainFoder/",IN_ALL_EVENTS);
// int flag=0;
// char*ev="";
//wd=inotifytools_watch_recursively_with_exclude("/home/MainFolder/",IN_ALL_EVENTS);
while(1)
{
//sleep(30);
//read 1024 bytes of events from fd into buf
i=0;
len=read(fd,buf,1024);
while(i<len){
event=(struct inotify_event *) &buf[i];
/* watch /test directory for any activity and report it back to me */
/* check for changes */
{
if((event->mask & IN_OPEN) ||(event->mask & IN_CREATE))
{
printf("\n %s :was opened\n",event->name);
SS.push_back(event->name);
}
}
/* update index to start of next event */
i+=sizeof(struct inotify_event)+event->len;
}
vector<string>::const_iterator cii;
for(cii=SS.begin(); cii!=SS.end(); cii++)
{
wd1 = watch_from_filename(*ci);
}
/*
vector<string>::const_iterator cii;
for(cii=SS.begin(); cii!=SS.end(); cii++)
{
cout <<"HERE:"<< *cii << endl;
}
*/
int iret1, iret2;
/* Create independent threads each of which will execute function */
iret1 = pthread_create( &t1, NULL, print_message_function, (void*) message1);
}
}
void *print_message_function( void *ptr )
{
vector<string>::const_iterator cii;
for(cii=SS.begin(); cii!=SS.end(); cii++)
{
cout <<"HERE:"<< *cii << endl;
std::string path=exec
}
}
This working sample on Github does what you're looking for: inotify-example.cpp
On CREATE events, the current wd (watch descriptor), plus the inotify_event wd and name components, are added to a Watch object (see sample).
The class includes methods to lookup wd and names in several ways.
This snippet shows how CREATE/DELETE events are handled:
if ( event->mask & IN_CREATE ) {
current_dir = watch.get(event->wd);
if ( event->mask & IN_ISDIR ) {
new_dir = current_dir + "/" + event->name;
wd = inotify_add_watch( fd, new_dir.c_str(), WATCH_FLAGS );
watch.insert( event->wd, event->name, wd );
total_dir_events++;
printf( "New directory %s created.\n", new_dir.c_str() );
} else {
total_file_events++;
printf( "New file %s/%s created.\n", current_dir.c_str(), event->name );
}
} else if ( event->mask & IN_DELETE ) {
if ( event->mask & IN_ISDIR ) {
new_dir = watch.erase( event->wd, event->name, &wd );
inotify_rm_watch( fd, wd );
total_dir_events--;
printf( "Directory %s deleted.\n", new_dir.c_str() );
} else {
current_dir = watch.get(event->wd);
total_file_events--;
printf( "File %s/%s deleted.\n", current_dir.c_str(), event->name );
}
}
You can do it in two steps:
Detect all the changes you're interested in on the root directory, plus (if not already included) creations (IN_CREATE).
If the creation is a directory, do the whole algorithm on it.
I have written the code for you. Now, you have to do only one change in this code. Just give path of your directory in main function.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <limits.h>
#include<sys/stat.h>
#include<dirent.h>
#include<time.h>
#include<string.h>
#include<unistd.h>
#define MAX_EVENTS 1024 /*Max. number of events to process at one go*/
#define LEN_NAME 16 /*Assuming that the length of the filename won't exceed 16 bytes*/
#define EVENT_SIZE ( sizeof (struct inotify_event) ) /*size of one event*/
#define BUF_LEN ( MAX_EVENTS * ( EVENT_SIZE + LEN_NAME )) /*buffer to store the data of events*/
void monitor(char *);
int evnt_mon(char *);
void main()
{
if(fork()==0)
evnt_mon("./usssb");// give path of your directory which you want to monitor
monitor("./usssb");// give path of your directory which you want to monitor
while(1);
}
void monitor(char * rt_dir)
{
struct stat st;
DIR *dirp;
struct dirent *dp;
char str[100][100]={ };
char temp[100];
char str1[500]=" ";
int i=0,j=0,src_ret=9,src_ret1=9;
strcpy(str1,rt_dir);
dirp=opendir(str1);
if(dirp==NULL)
{
perror("opendir");
return;
}
while(1)
{
dp=readdir(dirp);
if(dp==NULL)
break;
if((strcmp(dp->d_name,".\0")==0) || (strcmp(dp->d_name,"..")==0))
continue;
if((dp->d_type==DT_DIR)&&((strcmp(dp->d_name,".")!=0)&&(strcmp(dp->d_name,"..")!=0)))
{
strcat(str[i],str1);
strcat(str[i],"/");
strcat(str[i],dp->d_name);
if(fork()==0)
{
evnt_mon(str[i]);
}
i++;
}
}
closedir(dirp);
if(i>0)
{
for(j=0;j<i;j++)
{
monitor(str[j]);
}
}
}
int evnt_mon(char *argv)
{
int length, i = 0, wd;
int fd;
char buffer[BUF_LEN];
/* Initialize Inotify*/
fd = inotify_init();
if ( fd < 0 )
{
perror( "Couldn't initialize inotify");
}
/* add watch to starting directory */
wd = inotify_add_watch(fd, argv, IN_CREATE | IN_MODIFY | IN_DELETE);
if (wd == -1)
{
printf("Couldn't add watch to %s\n",argv);
}
else
{
printf("Watching:: %s\n",argv);
}
/* do it forever*/
while(1)
{
i = 0;
length = read( fd, buffer, BUF_LEN );
if ( length < 0 )
{
perror( "read" );
}
while ( i < length )
{
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
if ( event->len )
{
if ( event->mask & IN_CREATE)
{
if (event->mask & IN_ISDIR)
{
printf( "The directory %s was Created in %s.\n", event->name,argv );
if(fork()==0)
{
char p[100]=" ";
strcpy(p,argv);
strcat(p,"/");
strcat(p,event->name);
evnt_mon(p);
}
}
else
printf( "The file %s was Created with WD %d\n", event->name, event->wd );
}
if ( event->mask & IN_MODIFY)
{
if (event->mask & IN_ISDIR)
printf( "The directory %s was modified.\n", event->name );
else
printf( "The file %s was modified with WD %d\n", event->name, event->wd );
}
if ( event->mask & IN_DELETE)
{
if (event->mask & IN_ISDIR)
printf( "The directory %s was deleted from %s.\n", event->name,argv );
else
printf( "The file %s was deleted with WD %d\n", event->name, event->wd );
}
i += EVENT_SIZE + event->len;
}
}
}
/* Clean up*/
inotify_rm_watch( fd, wd );
close( fd );
return 0;
}
You might use the fanotify API. It allows you to monitor a complete mount. The only drawback is that you need to be root.
To address the problem stated by ribram (the 'hole':)). one possible solution i can think of is that we can do a combination of 'polling the directory' and 'using inotify'... i.e. Each time a directory is detected (directory only, don't do it for files):
add a watchpoint for the newly detected directory to inotify
'poll' (or 'scan') the newly detected directory (man readdir()) to see if there're already items (files, directories) created. Those are possibly the ones that are missing.
Note that to build an 'air-tight' case, the above steps' order is important. you need to add the watchpoint first than scan ... This will guarantee that an item is picked up by either 'scan' or inotify or both. In that case you may also need to aware of the dups. i.e. the same item can be both yielded by the scan and the inotify
In this program, I am reading "key.pc.db" file and printing its mid value.
#include <fstream>
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
using namespace std;
int main( int argc, char *argv[] )
{
ifstream fp;
int mval;
int sizek;
struct stat filek;
int min, max, mid;
if(stat("key.pc.db", &filek) ==0 )
sizek=filek.st_size;
sizek=sizek/sizeof(int);
min=0;
max=sizek-1;
mid=(min+max)/2;
printf("mid %d ",mid);
fp.open( "key.pc.db", ios::in | ios::binary );
fp.seekg(mid, ios::beg);
fp.read( (char *) &mval, (int) sizeof( int ) );
printf("%d mval ", mval);
getch();
return 1;
}
In this program also I am reading the same file but I am storing the value of the file in an array and then printing the mid value. The mid index for both the program shows the same but the value comes out to be different. Why so?
#include <fstream>
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
using namespace std;
int main( int argc, char *argv[] )
{
ifstream fp;
int index;
int sizek;
int kval;
struct stat filek;
int min, max, mid;
int i=0;
if(stat("key.pc.db", &filek) ==0 )
sizek=filek.st_size;
sizek=sizek/sizeof(int);
int k[sizek];
fp.open( "key.pc.db", ios::in | ios::binary );
fp.read( (char *) &kval, (int) sizeof( int ) );
while( !fp.eof() )
{
k[i++]=kval;
fp.read( (char *) &kval, (int) sizeof( int ) );
}
min=0;
max=sizek-1;
mid=(min+max)/2;
printf(" index %d ", mid);
printf(" kmid %d ", k[mid]);
getch();
return 1;
}
You're seeking to the wrong point in the file in the first case. You should be seeking to mid*sizeof(int) rather than mid.