/* Utility program used during pcnfd installation. Adds an export line for /var/spool/pcnfs to /etc/exports, but only if necessary. */ #include #include #include #include char pcnfsdir[] = "/var/spool/pcnfs"; char exports[] = "/etc/exports"; main() { FILE *fp; int error; char exportdir[MAXPATHLEN], buf[1012]; if(!(fp = fopen(exports, "r+"))) { perror("fopen"); return -1; } /* For each exported directory, , loop through /var/spool/pcnfs and it's ancestors, looking for a match with . NOTE that user may enter links in /etc/exports, hence we looks for matches by comparing inodes, rather than symbolically. */ while(fgets(exportdir, sizeof(exportdir), fp)) { if(*exportdir != '#') { struct stat dirst; char *ptr; char tmpbuf[MAXPATHLEN]; /* null terminate first field (which is exported path name) */ for(ptr=exportdir;*ptr && *ptr != '\t' && *ptr != ' ' && *ptr != '\n';ptr++); *ptr = 0; if(stat(exportdir, &dirst)) { perror("stat"); return -1; } /* Special case root directory, because it won't be handled by the directory stripping code below. */ if(!strcmp(exportdir, "/")) return 0; strcpy(tmpbuf, pcnfsdir); while(*tmpbuf) { struct stat st; if(stat(tmpbuf, &st)) { perror("stat"); return -1; } if(st.st_ino == dirst.st_ino) { #ifdef TESTING printf("got it! %s.\n", tmpbuf); printf("%s is on device: %d\n", exportdir, dirst.st_dev); #endif return 0; } /* chop off last directory entry. */ ptr = tmpbuf + strlen(tmpbuf) - 1; while(*ptr && *ptr != '/') ptr--; if(*ptr) *ptr = 0; } } } fprintf(fp, "%s\n", pcnfsdir); fclose(fp); sprintf(buf, "/usr/etc/exportfs %s\n", pcnfsdir); error = system(buf); #ifdef TESTING fprintf(stderr, "system returned 0x%d\n", error); #endif return 0; }