Mercurial > repos > david-hoover > local_file_tools
comparison cpy.c @ 0:c772c8912663
Uploaded
| author | david-hoover |
|---|---|
| date | Tue, 28 Feb 2012 12:36:45 -0500 |
| parents | |
| children | e5a905df7e0b |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:c772c8912663 |
|---|---|
| 1 #include <sys/stat.h> | |
| 2 #include <sys/types.h> | |
| 3 #include <unistd.h> | |
| 4 #include <stdio.h> | |
| 5 #include <errno.h> | |
| 6 #include <stdlib.h> | |
| 7 #include <pwd.h> | |
| 8 #include <grp.h> // declares struct group | |
| 9 #include <libgen.h> // for dirname | |
| 10 #include <string.h> // for strcpy | |
| 11 | |
| 12 /* cpy.c David Hoover 1/20/12 | |
| 13 usage: | |
| 14 cpy from.file to.file login | |
| 15 | |
| 16 cpy copies a file from one location to another, and then sets the ownership to a given user. The | |
| 17 program is expected to be setuid and owned by root. | |
| 18 | |
| 19 */ | |
| 20 | |
| 21 int notWriteable(char *file, char *user) | |
| 22 /* Returns 1 if file not writeable by given user */ | |
| 23 { | |
| 24 struct stat fileStat; | |
| 25 struct passwd *own,*usr; | |
| 26 struct group *grp; | |
| 27 int i=0; | |
| 28 | |
| 29 usr = getpwnam(user); | |
| 30 | |
| 31 /* does user exist? */ | |
| 32 if (! usr) | |
| 33 { | |
| 34 fprintf(stderr,"%s: No such user\n",user); | |
| 35 exit(1); | |
| 36 } | |
| 37 | |
| 38 /* must be able to stat file */ | |
| 39 if (stat(file, &fileStat) < 0) | |
| 40 { | |
| 41 fprintf(stderr,"%s: No such directory\n",file); | |
| 42 exit(1); | |
| 43 } | |
| 44 | |
| 45 /* get the owner and group information for the file */ | |
| 46 own = getpwuid(fileStat.st_uid); | |
| 47 grp = getgrgid(fileStat.st_gid); | |
| 48 | |
| 49 /* does the file owner match the argument? */ | |
| 50 // if (!strcmp(own->pw_name,user)) | |
| 51 if (usr->pw_uid == fileStat.st_uid) | |
| 52 { | |
| 53 // printf("owners match!\n"); | |
| 54 | |
| 55 /* is file writeable? */ | |
| 56 if (fileStat.st_mode & S_IWUSR) | |
| 57 { | |
| 58 // printf("%s is writeable by %s\n",file,user); | |
| 59 return 0; | |
| 60 } | |
| 61 else | |
| 62 { | |
| 63 // printf("%s is not writeable by %s\n",file,user); | |
| 64 } | |
| 65 } | |
| 66 else { | |
| 67 // printf("owners don't match!\n"); | |
| 68 } | |
| 69 | |
| 70 /* is the file group readable by the given group? */ | |
| 71 if (fileStat.st_mode & S_IWGRP) | |
| 72 { | |
| 73 // printf("%s is writeable by group %s\n",file,grp->gr_name); | |
| 74 | |
| 75 | |
| 76 /* is the user's gid the same as the file? */ | |
| 77 // printf("%d\n",usr->pw_gid); | |
| 78 // printf("%d\n",fileStat.st_gid); | |
| 79 if (usr->pw_gid == fileStat.st_gid) | |
| 80 { | |
| 81 // printf("groups match!\n"); | |
| 82 | |
| 83 /* if the path a directory is it executable? */ | |
| 84 if (S_ISDIR(fileStat.st_mode)) | |
| 85 { | |
| 86 if (fileStat.st_mode & S_IXGRP) | |
| 87 { | |
| 88 return 0; | |
| 89 } | |
| 90 } | |
| 91 else { | |
| 92 return 0; | |
| 93 } | |
| 94 } | |
| 95 else | |
| 96 { | |
| 97 | |
| 98 /* is the user a member of the group that owns the file? */ | |
| 99 while(grp->gr_mem[i] != NULL) | |
| 100 { | |
| 101 if(!strcmp(grp->gr_mem[i],user)) | |
| 102 { | |
| 103 // printf("%s is a member of the %s group\n",user,grp->gr_name); | |
| 104 /* if the path a directory is it executable? */ | |
| 105 if (S_ISDIR(fileStat.st_mode)) | |
| 106 { | |
| 107 if (fileStat.st_mode & S_IXGRP) | |
| 108 { | |
| 109 return 0; | |
| 110 } | |
| 111 } | |
| 112 else { | |
| 113 return 0; | |
| 114 } | |
| 115 } | |
| 116 i++; | |
| 117 } | |
| 118 | |
| 119 // printf("%s is not a member of the %s group\n",user,grp->gr_name); | |
| 120 | |
| 121 } | |
| 122 } | |
| 123 else | |
| 124 { | |
| 125 // printf("%s is not writeable by group %s\n",file,grp->gr_name); | |
| 126 } | |
| 127 | |
| 128 /* is the e world writeable? */ | |
| 129 if (fileStat.st_mode & S_IWOTH) | |
| 130 { | |
| 131 // printf("%s is world writeable\n",file); | |
| 132 return 0; | |
| 133 } | |
| 134 else | |
| 135 { | |
| 136 // printf("%s is not world writeable\n",file); | |
| 137 } | |
| 138 | |
| 139 return 1; | |
| 140 } | |
| 141 | |
| 142 int notReadable(char *file, char *user) | |
| 143 /* Returns 1 if file not readable by given user */ | |
| 144 { | |
| 145 struct stat fileStat; | |
| 146 struct passwd *own,*usr; | |
| 147 struct group *grp; | |
| 148 int i=0; | |
| 149 | |
| 150 usr = getpwnam(user); | |
| 151 | |
| 152 /* does user exist? */ | |
| 153 if (! usr) | |
| 154 { | |
| 155 fprintf(stderr,"%s: No such user\n",user); | |
| 156 exit(1); | |
| 157 } | |
| 158 | |
| 159 /* must be able to stat file */ | |
| 160 if (stat(file, &fileStat) < 0) | |
| 161 { | |
| 162 fprintf(stderr,"%s: No such directory\n",file); | |
| 163 exit(1); | |
| 164 } | |
| 165 | |
| 166 /* get the owner and group information for the file */ | |
| 167 own = getpwuid(fileStat.st_uid); | |
| 168 grp = getgrgid(fileStat.st_gid); | |
| 169 | |
| 170 /* does the file owner match the argument? */ | |
| 171 // if (!strcmp(own->pw_name,user)) | |
| 172 if (usr->pw_uid == fileStat.st_uid) | |
| 173 { | |
| 174 // printf("owners match!\n"); | |
| 175 | |
| 176 /* is file readable? */ | |
| 177 if (fileStat.st_mode & S_IRUSR) | |
| 178 { | |
| 179 // printf("%s is readable by %s\n",file,user); | |
| 180 return 0; | |
| 181 } | |
| 182 else | |
| 183 { | |
| 184 // printf("%s is not readable by %s\n",file,user); | |
| 185 } | |
| 186 } | |
| 187 else { | |
| 188 // printf("owners don't match!\n"); | |
| 189 } | |
| 190 | |
| 191 /* is the file group readable by the given group? */ | |
| 192 if (fileStat.st_mode & S_IRGRP) | |
| 193 { | |
| 194 // printf("%s is readable by group %s\n",file,grp->gr_name); | |
| 195 | |
| 196 | |
| 197 /* is the user's gid the same as the file? */ | |
| 198 // printf("%d\n",usr->pw_gid); | |
| 199 // printf("%d\n",fileStat.st_gid); | |
| 200 if (usr->pw_gid == fileStat.st_gid) | |
| 201 { | |
| 202 // printf("groups match!\n"); | |
| 203 | |
| 204 /* if the path a directory is it executable? */ | |
| 205 if (S_ISDIR(fileStat.st_mode)) | |
| 206 { | |
| 207 if (fileStat.st_mode & S_IXGRP) | |
| 208 { | |
| 209 return 0; | |
| 210 } | |
| 211 } | |
| 212 else { | |
| 213 return 0; | |
| 214 } | |
| 215 } | |
| 216 else | |
| 217 { | |
| 218 | |
| 219 /* is the user a member of the group that owns the file? */ | |
| 220 while(grp->gr_mem[i] != NULL) | |
| 221 { | |
| 222 if(!strcmp(grp->gr_mem[i],user)) | |
| 223 { | |
| 224 // printf("%s is a member of the %s group\n",user,grp->gr_name); | |
| 225 /* if the path a directory is it executable? */ | |
| 226 if (S_ISDIR(fileStat.st_mode)) | |
| 227 { | |
| 228 if (fileStat.st_mode & S_IXGRP) | |
| 229 { | |
| 230 return 0; | |
| 231 } | |
| 232 } | |
| 233 else { | |
| 234 return 0; | |
| 235 } | |
| 236 } | |
| 237 i++; | |
| 238 } | |
| 239 | |
| 240 // printf("%s is not a member of the %s group\n",user,grp->gr_name); | |
| 241 | |
| 242 } | |
| 243 } | |
| 244 else | |
| 245 { | |
| 246 // printf("%s is not readable by group %s\n",file,grp->gr_name); | |
| 247 } | |
| 248 | |
| 249 /* is the e world readable? */ | |
| 250 if (fileStat.st_mode & S_IROTH) | |
| 251 { | |
| 252 // printf("%s is world readable\n",file); | |
| 253 return 0; | |
| 254 } | |
| 255 else | |
| 256 { | |
| 257 // printf("%s is not world readable\n",file); | |
| 258 } | |
| 259 | |
| 260 return 1; | |
| 261 } | |
| 262 | |
| 263 int copyFile(char *src, char *dst) | |
| 264 { | |
| 265 // printf("Copying %s to %s\n",src,dst); | |
| 266 | |
| 267 int c; | |
| 268 FILE *fs,*ft; | |
| 269 struct stat fileStat; | |
| 270 | |
| 271 /* must be able to stat file */ | |
| 272 if (stat(src, &fileStat) < 0) | |
| 273 { | |
| 274 fprintf(stderr,"%s: No such file\n",src); | |
| 275 exit(1); | |
| 276 } | |
| 277 | |
| 278 /* is path a regular file? */ | |
| 279 if (S_ISDIR(fileStat.st_mode)) | |
| 280 { | |
| 281 fprintf(stderr,"%s: Is a directory\n",src); | |
| 282 exit(1); | |
| 283 } | |
| 284 | |
| 285 fs = fopen(src,"r"); | |
| 286 if (fs==NULL) { | |
| 287 fprintf(stderr,"Can't read from file %s!\n",src); | |
| 288 exit(1); | |
| 289 } | |
| 290 ft = fopen(dst,"w"); | |
| 291 if (ft==NULL) { | |
| 292 fprintf(stderr,"Can't write to file %s!\n",dst); | |
| 293 exit(1); | |
| 294 } | |
| 295 | |
| 296 c = getc(fs); | |
| 297 while (c != EOF) { | |
| 298 putc(c,ft); | |
| 299 c = getc(fs); | |
| 300 } | |
| 301 | |
| 302 fclose(fs); | |
| 303 fclose(ft); | |
| 304 | |
| 305 return 0; | |
| 306 | |
| 307 } | |
| 308 | |
| 309 int chownToGivenUser(char *file, char *user) | |
| 310 /* chown a file to the given user */ | |
| 311 { | |
| 312 struct passwd *usr; | |
| 313 | |
| 314 usr = getpwnam(user); | |
| 315 | |
| 316 // printf("UID = %d\n",usr->pw_uid); | |
| 317 // printf("GID = %d\n",usr->pw_gid); | |
| 318 | |
| 319 // printf("chown %s %d,%d\n",file,usr->pw_uid,usr->pw_gid); | |
| 320 if (chown(file,usr->pw_uid,usr->pw_gid)) | |
| 321 { | |
| 322 fprintf(stderr,"Can't chown %s\n",file); | |
| 323 exit(1); | |
| 324 } | |
| 325 return 0; | |
| 326 } | |
| 327 | |
| 328 int explodePath(char *file, char *user) | |
| 329 /* Returns 1 if file not readable by given user */ | |
| 330 { | |
| 331 char **path; | |
| 332 char *dir; | |
| 333 char newfile[10000]; | |
| 334 int i; | |
| 335 | |
| 336 strcpy(newfile,file); | |
| 337 if (!notReadable(newfile,user)) | |
| 338 { | |
| 339 dir = dirname(newfile); | |
| 340 if (strcmp(dir,"/")) | |
| 341 explodePath(dir,user); | |
| 342 } | |
| 343 else | |
| 344 { | |
| 345 fprintf(stderr,"%s: Permission denied.\n",file); | |
| 346 exit(1); | |
| 347 } | |
| 348 | |
| 349 return 0; | |
| 350 } | |
| 351 | |
| 352 main(int argc, char **argv) | |
| 353 { | |
| 354 char *dir; | |
| 355 char newfile[10000]; | |
| 356 struct stat fileStat; | |
| 357 | |
| 358 /* must have two arguments */ | |
| 359 if (argc != 4) | |
| 360 { | |
| 361 fprintf(stderr,"usage: cpy source dest user\n"); | |
| 362 exit(1); | |
| 363 } | |
| 364 | |
| 365 /* is filepath writeable by given user? */ | |
| 366 strcpy(newfile,argv[2]); | |
| 367 dir = dirname(newfile); | |
| 368 if (!notWriteable(dir,argv[3])) | |
| 369 { | |
| 370 | |
| 371 /* is filepath readable by given user? */ | |
| 372 explodePath(dir,argv[3]); | |
| 373 | |
| 374 /* dest file must not exist yet */ | |
| 375 if (!(stat(argv[2], &fileStat) < 0)) | |
| 376 { | |
| 377 fprintf(stderr,"%s: File already exists.\n",argv[2]); | |
| 378 exit(1); | |
| 379 } | |
| 380 | |
| 381 /* copy the file and change the owner */ | |
| 382 copyFile(argv[1],argv[2]); | |
| 383 chownToGivenUser(argv[2],argv[3]); | |
| 384 } | |
| 385 else | |
| 386 { | |
| 387 fprintf(stderr,"%s: Permission denied.\n",argv[2]); | |
| 388 exit(1); | |
| 389 } | |
| 390 | |
| 391 exit(0); | |
| 392 } |
