b43fa231821a3cc12d181002f348768d97c4edcd
[gapil.git] / sources / test_linkat.c
1 /* test_linkat.c
2  * 
3  * Copyright (C) 2019 Simone Piccardi
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /****************************************************************
20  *
21  * Program test_linkat.c: 
22  * Program to test use of linkat and O_TMPFILE and other combinations 
23  *
24  * Author: Simone Piccardi
25  * Oct. 2018
26  *
27  * Usage: testlinkat -h give all info's
28  *
29  ****************************************************************/
30 /* 
31  * Include needed headers
32  */
33 #define _GNU_SOURCE
34 #include <errno.h>       /* error definitions and routines */ 
35 #include <stdlib.h>      /* C standard library */
36 #include <unistd.h>      /* unix standard library */
37 #include <stdio.h>       /* standard I/O library */
38 #include <string.h>      /* C strings library */
39 #include <limits.h>
40 #include <libgen.h>      /* needed for dirname e basename */
41 #include <sys/stat.h>
42 #include <sys/types.h>
43 #include <fcntl.h>
44
45 /* Help printing routine */
46 void usage(void);
47
48 int main(int argc, char *argv[])
49 {
50 /* 
51  * Variables definition  
52  */
53     int i;
54     int wait=0;
55     char *srcfile = NULL;
56     /*
57      * Input section: decode command line parameters 
58      * Use getopt function
59      */
60     opterr = 0;  /* don't want writing to stderr */
61     while ( (i = getopt(argc, argv, "hw:f:")) != -1) {
62         switch (i) {
63         /* 
64          * Handling options 
65          */ 
66         case 'h':   /* help option */
67             printf("Wrong -h option use\n");
68             usage();
69             return -1;
70             break;
71         case 'w':      /* time to wait in s */
72             wait = strtol(optarg, NULL, 10);    /* convert input */
73             break;
74         case 'f':      /* using a source file */
75             srcfile = optarg;
76             break;
77         case '?':   /* unrecognized options */
78             printf("Unrecognized options -%c\n",optopt);
79             usage();
80         default:    /* should not reached */
81             usage();
82         }
83     }
84     /* ***********************************************************
85      * 
86      *           Options processing completed
87      *
88      *                Main code beginning
89      * 
90      * ***********************************************************/
91     /* There must be 1 remaing parameters */
92     if ( (argc-optind) != 1 )  {
93         printf("From %d arguments, removed %d options\n", argc, optind);
94         usage();
95     }
96     char *path, *dir, *file;
97     char pattern[] = "prova prova prova\n";
98     path = strdup(argv[optind]);
99     file = basename(argv[optind]);
100     dir = dirname(argv[optind]);
101     printf("Working on dir %s file: %s\nwith path: %s\n",
102            dir, file, path);
103     int fd, newfd;
104     if ( ! srcfile ) {
105         fd = open(dir, O_TMPFILE|O_RDWR,S_IRUSR|S_IWUSR);
106         if ( fd <= 0 )
107             perror("cannot open TMPFILE");
108         if ( (i = write(fd, pattern, sizeof(pattern))) < 0 )   
109             perror("cannot write on TMPFILE");
110         else
111             printf("saved %d chars on fd %d\n", i, fd);
112     } else {
113         printf("source is %s\n", srcfile);
114         if ( (fd = open(srcfile, O_RDONLY)) < 0 ) {
115             perror("cannot open source");
116             exit(1);
117         }
118     }
119     newfd = open(dir, O_PATH|O_RDWR);
120     int err;
121     err = linkat(fd, "", newfd, file, AT_EMPTY_PATH);
122     if ( err < 0  ) {
123         perror("error on creating TMPFILE");
124         printf("cannot link fd %d on fd %d, %s with AT_EMPTY_PATH\n",
125                fd, newfd, file);
126         char fdpath[PATH_MAX];
127         snprintf(fdpath, PATH_MAX, "/proc/self/fd/%d", fd);
128         printf("fd path %s\n", fdpath);
129         err = linkat(AT_FDCWD, fdpath, newfd, file, AT_SYMLINK_FOLLOW);
130         if ( err < 0  ) {
131             perror("still error creating TMPFILE");
132             sleep(wait);
133             exit(1);
134         }
135         if ( fchmodat(newfd, file,S_IRUSR|S_IWUSR,0) < 0 )
136             perror("Cannot change permission to new file");
137     }
138     free(path);
139     return 0;
140 }
141 /*
142  * routine to print usage info and exit
143  */
144 void usage(void) {
145     printf("Program testlinkat : test fopen for a file  \n");
146     printf("Usage:\n");
147     printf("  testfopen [-h] file mode \n");
148     printf("  -h           print this help\n");
149     
150     exit(1);
151 }
152