where fcntl saves locking information - linux

I wonder to understand where fcntl c++ function saves information about locked files. I know that it saves some information on /proc/locks , but fcntl identify lock even if it locked by another host
In my first host I locked some file By F_WRLCK.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include<iostream>
main() {
int fd;
struct flock lock;
lock.l_type=F_WRLCK;
lock.l_start=0;
lock.l_whence= SEEK_SET;
lock.l_len=0;
printf("open %d\n",fd=open("/u/embedit/places/scratch/gtevos/ts16nxq42p11assrl16kaa03/ts16nxq42p11assrl16kaa.cpj", O_RDWR ));
int rc = fcntl(fd, F_SETLK, &lock);
std::cout<<rc<<std::endl;
std::cin>>fd;
}
When I am traying to lock the same file on my second host by F_RDONLY it doesn't work.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include<iostream>
main() {
int fd;
struct flock lock;
lock.l_type=F_RDLCK;
lock.l_start=0;
lock.l_whence= SEEK_SET;
lock.l_len=0;
printf("open %d\n",fd=open("/u/embedit/places/scratch/gtevos/ts16nxq42p11assrl16kaa03/ts16nxq42p11assrl16kaa.cpj", O_RDONLY ));
int rc = fcntl(fd, F_SETLK, &lock);
std::cout<<rc<<std::endl;
std::cin>>fd;
}
I just want to understand which mechanism is used that provide ability to right identify locks.

Related

Inter process communication using FIFO

Client server must pass to the Server process a filename and the Server process must return the number of lines in the file. My problem is that the received variable only contains 6 characters of the filename and it ends up by throwing segmentation fault dump core error. Do you know why this happens? This is my code:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(){
int fd1,fd2;
const char *fifo1="./fifo1Channel";
const char *fifo2="./fifo2Channel";
mkfifo(fifo1,0666);
mkfifo(fifo2,0666);
char filename[30];
printf("Give me a filename:\n");
fgets(filename,30,stdin);
strtok(filename,"\n");
int pid=fork();
if(pid>0){
char received[30], ch;
FILE *fp;
fd1=open(fifo1, O_RDONLY);
read(fd1,received,strlen(received));
close(fd1);
printf("From server process:%s\n",received);
fp=fopen(received,"r");
int nrOfLines=0;
for(ch=getc(fp);ch!=EOF;ch=getc(fp))
if(ch=='\n')
nrOfLines++;
fd2=open(fifo2, O_WRONLY);
write(fd2,&nrOfLines,sizeof(nrOfLines));
close(fd2);
return 0;
}
if(pid==0){
int receivedNumber;
fd1=open(fifo1,O_WRONLY);
write(fd1,filename,strlen(filename));
close(fd1);
fd2=open(fifo2,O_RDONLY);
read(fd2,&receivedNumber,sizeof(receivedNumber));
close(fd2);
printf("From client process: %d\n",receivedNumber);
return 0;
}
return 0;
}
I think the problem was in server process. I replaced strlen(received) with 30, the maximum number of characters of filename, in function read and it works now!

inotify_add_watch relative to O_PATH dirfd

I am trying to call inotify_add_watch to watch a file. I would like to specify the file relative to an O_PATH | O_DIRECTORY file descriptor, a la symlinkat, fstatat, or openat.
Is this possible? It doesn't look like it is. Anyone know of a workaround?
EDIT
The closest thing seems to be the "trick" described at man 2 open under "Rationale for openat". See the answer by user1643723 for an example.
You can use symlinks, provided by procfs to achieve the functionality of most *at calls. Open a directory descriptor and use /proc/self/fd/<dir descriptor>/filename instead of the full path to filename:
#define _GNU_SOURCE
#include <sys/stat.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main() {
int inotify = inotify_init();
mkdir("tmp", 0777);
mknod("tmp/foo", 0777 | S_IFREG, 0);
int dirFd = open("tmp", O_DIRECTORY | O_PATH);
char buf[40] = { '\0' };
sprintf(buf, "/proc/self/fd/%d/foo", dirFd);
int watchd = inotify_add_watch(inotify, buf, IN_MOVE | IN_ATTRIB);
if (watchd < 0) {
printf("Failed: %s", strerror(errno));
} else {
printf("ok");
}
}
The program above prints "ok" on Linux 4.4.x.

getting CLOCK_TICK_RATE value in linux

I'm trying to print the value of CLOCK_TICK_RATE with the following program:
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/kd.h>
#include <linux/timex.h>
int main() {
printf("%d\n",CLOCK_TICK_RATE);
}
I get an compilation error:
error: ‘CLOCK_TICK_RATE’ undeclared.
I looked for the definition of CLOCK_TICK_RATE, I found that in timex.h, but even after I included timex.h CLOCK_TICK_RATE is still undeclared.
thanks in advance.
Maybe you are looking for this?
#include <stdio.h>
#include <unistd.h>
int main (void) {
printf (
"%ld\n",
sysconf(_SC_CLK_TCK)
);
return 0;
}
It's in hertz and is normally 100.

Linux: unable to retrieve process name from pid via ioctl

I'm trying to retrieve retrieve process name from pid via ioctl, this is the C code:
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/syscall.h>
#include <sys/procfs.h>
#include <stdio.h>
#include <signal.h>
#include <elf.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char **argv) {
char ProcID[50]="/proc/";
int fd;
prpsinfo_t ProcessInfo;
int ioctlResult;
if ( argc != 2 ) {
printf("usage: %s <pid>\n", argv[0]);
return 0;
}
strcat(ProcID,argv[1]);
fd = open(ProcID, O_RDONLY, 0);
if (fd == -1) {
printf("open error: [%d] [%s]\n",errno, strerror(errno));
return 0;
}
ioctlResult = ioctl(fd, NT_PRPSINFO, &ProcessInfo);
if (ioctlResult == -1)
{
printf("Error ioctl: [%d] [%s]\n",errno, strerror(errno));
} else {
printf("Process name: %s\n",ProcessInfo.pr_fname);
}
close(fd);
return 0;
}
When I try to execute it I obtain errno 25 (Inappropriate ioctl for device). I think the file descriptor open on "/proc/" isn't correct; is there another path to consider ?

how to write one entry in /var/run/utmp?

Based on this bug i'm trying to write an entry in /var/run/utmp to simulate the problem http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=528060 , i tryed with this code taken from manpages, but didn't work
#include <string.h>
#include <stdlib.h>
#include <pwd.h>
#include <unistd.h>
#include <utmp.h>
int
main(int argc, char *argv[])
{
struct utmp entry;
system("echo before adding entry:;who");
entry.ut_type = USER_PROCESS;
entry.ut_pid = getpid();
strcpy(entry.ut_line, ttyname(STDIN_FILENO) + strlen("/dev/"));
/* only correct for ptys named /dev/tty[pqr][0-9a-z] */
strcpy(entry.ut_id, ttyname(STDIN_FILENO) + strlen("/dev/tty"));
time(&entry.ut_time);
strcpy(entry.ut_user, getpwuid(getuid())->pw_name);
memset(entry.ut_host, 0, UT_HOSTSIZE);
entry.ut_addr = 0;
setutent();
pututline(&entry);
system("echo after adding entry:;who");
exit(EXIT_SUCCESS);
}
I solved my problem with this code
#include <string.h>
#include <stdlib.h>
#include <pwd.h>
#include <unistd.h>
#include <utmp.h>
int
main(int argc, char *argv[])
{
struct utmp entry;
system("echo before adding entry:;who");
entry.ut_type = USER_PROCESS;
entry.ut_pid = getpid();
strcpy(entry.ut_line, ttyname(STDIN_FILENO) + strlen("/dev/"));
/* only correct for ptys named /dev/tty[pqr][0-9a-z] */
strcpy(entry.ut_id, ttyname(STDIN_FILENO) + strlen("/dev/tty"));
time(&entry.ut_time);
//strcpy(entry.ut_user, getpwuid(getuid())->pw_name);
strcpy(entry.ut_user, "pippo");
memset(entry.ut_host, 0, UT_HOSTSIZE);
entry.ut_addr = 0;
setutent();
pututline(&entry);
system("echo after adding entry:;who");
exit(EXIT_SUCCESS);
}

Resources