/* * mountd now keeps an open fd for the etab at all times to make sure that the * inode number changes when the xtab_export_write is done. If you change the * routine below such that the files are edited in place, then you'll need to * fix the auth_reload logic as well... */ static int xtab_write(char *xtab, char *xtabtmp, char *lockfn, int is_export) { struct exportent xe; nfs_export *exp; int lockid, i; if ((lockid = xflock(lockfn, "w")) < 0) { xlog(L_ERROR, "can't lock %s for writing", xtab); return 0; } setexportent(xtabtmp, "w"); for (i = 0; i < MCL_MAXTYPES; i++) { for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { if (is_export && !exp->m_xtabent) continue; if (!is_export && ! exp->m_exported) continue; /* write out the export entry using the FQDN */ xe = exp->m_export; xe.e_hostname = exp->m_client->m_hostname; putexportent(&xe); } } endexportent(); cond_rename(xtabtmp, xtab); xfunlock(lockid); return 1; }
void xtab_append(nfs_export *exp) { struct exportent xe; int lockid; if ((lockid = xflock(_PATH_XTABLCK, "w")) < 0) return; setexportent(_PATH_XTAB, "a"); xe = exp->m_export; xe.e_hostname = exp->m_client->m_hostname; putexportent(&xe); endexportent(); xfunlock(lockid); exp->m_xtabent = 1; }
int rmtab_read(void) { struct rmtabent *rep; setrmtabent("r"); while ((rep = getrmtabent(1, NULL)) != NULL) { int htype; htype = client_gettype(rep->r_client); if (htype == MCL_FQDN || htype == MCL_SUBNETWORK) rmtab_read_wildcard(rep); } if (errno == EINVAL) { /* Something goes wrong. We need to fix the rmtab file. */ int lockid; FILE *fp; if ((lockid = xflock(_PATH_RMTABLCK, "w")) < 0) return -1; rewindrmtabent(); if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) { endrmtabent (); xfunlock(lockid); return -1; } while ((rep = getrmtabent(0, NULL)) != NULL) { fputrmtabent(fp, rep, NULL); } if (rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) { xlog(L_ERROR, "couldn't rename %s to %s", _PATH_RMTABTMP, _PATH_RMTAB); } endrmtabent(); fendrmtabent(fp); xfunlock(lockid); } else { endrmtabent(); } return 0; }
void mountlist_del_all(const struct sockaddr *sap) { char *hostname; struct rmtabent *rep; FILE *fp; int lockid; if ((lockid = xflock(_PATH_RMTABLCK, "w")) < 0) return; hostname = host_canonname(sap); if (hostname == NULL) { char buf[INET6_ADDRSTRLEN]; xlog(L_ERROR, "can't get hostname of %s", host_ntop(sap, buf, sizeof(buf))); goto out_unlock; } if (!setrmtabent("r")) goto out_free; if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) goto out_close; while ((rep = getrmtabent(1, NULL)) != NULL) { if (strcmp(rep->r_client, hostname) == 0 && auth_authenticate("umountall", sap, rep->r_path) != NULL) continue; fputrmtabent(fp, rep, NULL); } if (slink_safe_rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) { xlog(L_ERROR, "couldn't rename %s to %s", _PATH_RMTABTMP, _PATH_RMTAB); } fendrmtabent(fp); out_close: endrmtabent(); /* close & unlink */ out_free: free(hostname); out_unlock: xfunlock(lockid); }
static int xtab_read(char *xtab, char *lockfn, int is_export) { /* is_export == 0 => reading /proc/fs/nfs/exports - we know these things are exported to kernel * is_export == 1 => reading /var/lib/nfs/etab - these things are allowed to be exported * is_export == 2 => reading /var/lib/nfs/xtab - these things might be known to kernel */ struct exportent *xp; nfs_export *exp; int lockid; if ((lockid = xflock(lockfn, "r")) < 0) return 0; setexportent(xtab, "r"); if (is_export == 1) v4root_needed = 1; while ((xp = getexportent(is_export==0, 0)) != NULL) { if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) && !(exp = export_create(xp, is_export!=1))) { continue; } switch (is_export) { case 0: exp->m_exported = 1; break; case 1: exp->m_xtabent = 1; exp->m_mayexport = 1; if ((xp->e_flags & NFSEXP_FSID) && xp->e_fsid == 0) v4root_needed = 0; break; case 2: exp->m_exported = -1;/* may be exported */ break; } } endexportent(); xfunlock(lockid); return 0; }
void mountlist_add(char *host, const char *path) { struct rmtabent xe; struct rmtabent *rep; int lockid; long pos; if ((lockid = xflock(_PATH_RMTABLCK, "a")) < 0) return; setrmtabent("r+"); while ((rep = getrmtabent(1, &pos)) != NULL) { if (strcmp (rep->r_client, host) == 0 && strcmp(rep->r_path, path) == 0) { rep->r_count++; /* PRC: do the HA callout: */ ha_callout("mount", rep->r_client, rep->r_path, rep->r_count); putrmtabent(rep, &pos); endrmtabent(); xfunlock(lockid); return; } } endrmtabent(); strncpy(xe.r_client, host, sizeof (xe.r_client) - 1); xe.r_client [sizeof (xe.r_client) - 1] = '\0'; strncpy(xe.r_path, path, sizeof (xe.r_path) - 1); xe.r_path [sizeof (xe.r_path) - 1] = '\0'; xe.r_count = 1; if (setrmtabent("a")) { /* PRC: do the HA callout: */ ha_callout("mount", xe.r_client, xe.r_path, xe.r_count); putrmtabent(&xe, NULL); endrmtabent(); } xfunlock(lockid); }
void mountlist_del(char *hname, const char *path) { struct rmtabent *rep; FILE *fp; int lockid; int match; if ((lockid = xflock(_PATH_RMTABLCK, "w")) < 0) return; if (!setrmtabent("r")) { xfunlock(lockid); return; } if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) { endrmtabent(); xfunlock(lockid); return; } while ((rep = getrmtabent(1, NULL)) != NULL) { match = !strcmp (rep->r_client, hname) && !strcmp(rep->r_path, path); if (match) { rep->r_count--; /* PRC: do the HA callout: */ ha_callout("unmount", rep->r_client, rep->r_path, rep->r_count); } if (!match || rep->r_count) fputrmtabent(fp, rep, NULL); } if (slink_safe_rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) { xlog(L_ERROR, "couldn't rename %s to %s", _PATH_RMTABTMP, _PATH_RMTAB); } endrmtabent(); /* close & unlink */ fendrmtabent(fp); xfunlock(lockid); }
int spool_file(char *spoolFile, int pass, NewslinkInfo *li, int flags) { char seqFile[256]; char newFile[256]; char obIpBuf[256]; char *outboundIpStr = OutboundIpStr; int begSeq = 0; int endSeq = 0; long newTime = 0; char portBuf[32]; char logartsStr[MAXLOGARTS+2]; int fd; struct stat st; char txBufSizeStr[32]; char rxBufSizeStr[32]; char TOSStr[32]; char maxStreamStr[32]; char compressStr[32]; char delayStr[32]; if (VerboseOpt) printf("spool_file(%s, %d, %s, %d)\n", spoolFile, pass, li->li_HostName, flags); /* * Initialize rx/txBufSizeStr */ sprintf(txBufSizeStr, "-nop"); sprintf(rxBufSizeStr, "-nop"); sprintf(TOSStr, "-nop"); sprintf(maxStreamStr, "-nop"); sprintf(compressStr, "-nop"); sprintf(delayStr, "-nop"); if (li->li_TransmitBuf > 0 && li->li_TransmitBuf < 16 * 1024 * 1024) sprintf(txBufSizeStr, "-T%d", li->li_TransmitBuf); if (li->li_ReceiveBuf > 0 && li->li_ReceiveBuf < 16 * 1024 * 1024) sprintf(rxBufSizeStr, "-R%d", li->li_ReceiveBuf); if (li->li_TOS > 0 && li->li_TOS <= 0xff ) sprintf(TOSStr, "-Q%d", li->li_TOS); if (li->li_MaxStream > 0) sprintf(maxStreamStr, "-M%d", li->li_MaxStream); if (li->li_Compress > 0) sprintf(compressStr, "-Z%d", li->li_Compress); if (li->li_DelayFeed > 0) sprintf(delayStr, "-W%d", li->li_DelayFeed); /* * Outbound article logging. */ sprintf(logartsStr, "-nop"); if (li->li_LogArts && *li->li_LogArts) { strcpy(logartsStr, "-A"); StrnCpyNull(logartsStr+2, li->li_LogArts, MAXLOGARTS); } /* * Override outbound IP */ if (li->li_BindAddress != NULL && strlen(li->li_BindAddress) < sizeof(obIpBuf) - 8) { sprintf(obIpBuf, "-B%s", li->li_BindAddress); outboundIpStr = obIpBuf; } if (li->li_Port <= 0) li->li_Port = 119; sprintf(portBuf, "%d", li->li_Port); sprintf(seqFile, ".%s.seq", spoolFile); /* * Get beginning and ending sequence numbers */ fd = open(seqFile, O_RDWR|O_CREAT, 0600); if (fd >= 0) { char buf[64]; xflock(fd, XLOCK_EX); /* lock and leave locked */ memset(buf, 0, sizeof(buf)); read(fd, buf, sizeof(buf) - 1); sscanf(buf, "%d %d %lx", &begSeq, &endSeq, &newTime); } /* * Discard beginning sequence numbers that are now deleted, or * delete queue files that are too old. */ while (begSeq < endSeq) { sprintf(newFile, "%s.S%05d", spoolFile, begSeq); if (li->li_MaxQueueFile > 0 && begSeq < endSeq - li->li_MaxQueueFile) remove(newFile); if (stat(newFile, &st) == 0) break; ++begSeq; } /* * If primary spool file exists, shift to primary * queue */ if (pass == 1) { { int tries = 100; int32 dt; struct stat st; while (tries > 0) { sprintf(newFile, "%s.S%05d", spoolFile, endSeq); if (stat(newFile, &st) < 0) break; --tries; ++endSeq; } /* * Only create a new spool file if: * * (1) endSeq == begSeq + 1, or * (2) current time larger then newTime + MinFlushSecs * (3) there is time weirdness */ dt = time(NULL) - ((int32)newTime + MinFlushSecs); if (VerboseOpt) printf("PASS %d: dt=%d tries=%d begSeq=%d endSeq=%d\n", pass, dt, tries, begSeq, endSeq); if (endSeq <= begSeq + 4 || dt > 0 || dt < -MinFlushSecs) { /* * If a dnewslink has a lock on the unsequenced spool file, * clear the SF_REALTIME flag... a realtime dnewslink is * already running so there is no sense trying to start * another one. */ if (flags & SF_REALTIME) { int tfd; if ((tfd = open(spoolFile, O_RDWR)) >= 0) { if (xflock(tfd, XLOCK_EX|XLOCK_NB) < 0) { if (VerboseOpt) printf("%s: realtime already\n", spoolFile); flags &= ~SF_REALTIME; } close(tfd); } } if (stat(spoolFile, &st) == 0 && st.st_size > 0 && rename(spoolFile, newFile) == 0) { ++endSeq; if (!Quiet) printf("dspoolout: add %s\n", newFile); } else { if (VerboseOpt && !Quiet) printf("dspoolout: nofile %s\n", newFile); if (endSeq == begSeq) AddNode(spoolFile); } if (flags & SF_REALTIME) { int fd = xopen(O_RDWR|O_CREAT, 0644, spoolFile); if (fd != -1) { close(fd); } } newTime = time(NULL); } else { AddNode(spoolFile); if (VerboseOpt && !Quiet) printf("dspoolout: wait %s\n", spoolFile); } } /* * Update sequence number file */ if (fd >= 0) { char buf[64]; sprintf(buf, "%5d %5d %08lx\n", begSeq, endSeq, newTime); lseek(fd, 0L, 0); write(fd, buf, strlen(buf)); ftruncate(fd, lseek(fd, 0L, 1)); } } if (fd >= 0) { xflock(fd, XLOCK_UN); close(fd); } /* * Run up to N newslink's/innxmit's, usually set at 2. * * Note that we spool out the queue as a FIFO. This is important as * it reduces article jumble. */ if (pass == 2 && FindNode(spoolFile) == NULL) { int tries = li->li_MaxParallel; int look; /* * Start up to MaxParallel dnewslinks. If the nobatch * flag is set, do not start any. */ if (flags & SF_NOBATCH) tries = 0; for (look = 0; look < 32 && tries && begSeq + look < endSeq - li->li_QueueSkip; ++look) { int use = begSeq + look; int fd; char numBuf[32]; { int left = endSeq - use - li->li_QueueSkip; if (left > 32) left = 32; if (left < 3 && li->li_QueueSkip == 0) left = 3; else if (left < 1) left = 1; sprintf(numBuf, "%d", left); if (VerboseOpt) printf("PASS %d: look=%d tries=%d begSeq=%d endSeq=%d use=%d left=%d\n", pass, look, tries, begSeq, endSeq, use, left); } sprintf(newFile, "%s.S%05d", spoolFile, use); if ((fd = open(newFile, O_RDWR)) >= 0) { if (xflock(fd, XLOCK_EX|XLOCK_NB) == 0) { char seqName[64]; char templateFile[256]; xflock(fd, XLOCK_UN); if (!Quiet) printf("dspoolout: run %s.S%05d\n", spoolFile, use); sprintf(templateFile, "%s.S%%05d", spoolFile); sprintf(seqName, "%d", use); if (VerboseOpt) printf("%s %s%s %s%s %s%s %s%s %s%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", "dnewslink", "-h", li->li_HostName, "-b", templateFile, "-S", seqName, "-N", numBuf, "-P", portBuf, "-D", ((flags & SF_NOSTREAM) ? "-i" : "-nop"), ((flags & SF_HEADFEED) ? ((flags & SF_PRESBYTES) ? "-HB" : "-H") : "-nop"), ((flags & SF_NOCHECK) ? "-I" : "-nop"), ((flags & SF_GENLINES) ? "-L" : "-nop"), ((flags & SF_ARTSTAT) ? "-x" : "-nop"), compressStr, logartsStr, outboundIpStr, txBufSizeStr, rxBufSizeStr, TOSStr, delayStr, maxStreamStr ); if (ForReal && fork() == 0) { char binPath[128]; if (li->li_StartDelay > 0) { if (xflock(fd, XLOCK_EX|XLOCK_NB) == 0) { sleep(li->li_StartDelay); xflock(fd, XLOCK_UN); } else { if (DebugOpt) printf(" qfile already locked for delay\n"); exit(0); } } if (li->li_Priority > 0) nice(li->li_Priority); snprintf(binPath, sizeof(binPath), "%s/dbin/dnewslink", NewsHome); execl(binPath, "dnewslink", "-h", li->li_HostName, "-b", templateFile, "-S", seqName, "-N", numBuf, "-P", portBuf, "-D", ((flags & SF_NOSTREAM) ? "-i" : "-nop"), ((flags & SF_HEADFEED) ? ((flags & SF_PRESBYTES) ? "-HB" : "-H") : "-nop"), ((flags & SF_NOCHECK) ? "-I" : "-nop"), ((flags & SF_GENLINES) ? "-L" : "-nop"), ((flags & SF_ARTSTAT) ? "-x" : "-nop"), compressStr, logartsStr, outboundIpStr, txBufSizeStr, rxBufSizeStr, TOSStr, delayStr, maxStreamStr, NULL ); exit(0); } } --tries; /* even if lock fails */ close(fd); } } /* * Deal with the realtime dnewslink, but only if: * The realtime flag is set * We have not gotten behind * We did not detect another realtime process */ if (VerboseOpt) printf("%s: flags %02x nseq %d\n", spoolFile, flags & SF_REALTIME, endSeq-begSeq); if ((flags & SF_REALTIME) && (ForceRealTime || (endSeq - begSeq <= 2))) { int fd; if ((fd = open(spoolFile, O_RDWR|O_CREAT, 0600)) >= 0) { if (xflock(fd, XLOCK_EX|XLOCK_NB) == 0) { xflock(fd, XLOCK_UN); if (!Quiet) printf("dspoolout: run realtime %s\n", spoolFile); if (VerboseOpt) printf("%s %s%s %s%s %s%s %s%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", "dnewslink", "-h", li->li_HostName, "-b", spoolFile, "-P", portBuf, "-N", "100", /* 1000 spool cycles */ ((li->li_StartDelay < 0) ? "-r-1" : "-r"), ((flags & SF_NOTIFY) ? "-o" : "-nop"), ((flags & SF_NOTIFY) ? spoolFile : "-nop"), ((flags & SF_NOSTREAM) ? "-i" : "-nop"), ((flags & SF_HEADFEED) ? ((flags & SF_PRESBYTES) ? "-HB" : "-H") : "-nop"), (((flags & SF_NOCHECK)||(li->li_Check==2)) ? "-I" : "-nop"), ((flags & SF_GENLINES) ? "-L" : "-nop"), ((flags & SF_ARTSTAT) ? "-x" : "-nop"), compressStr, logartsStr, outboundIpStr, txBufSizeStr, rxBufSizeStr, delayStr, maxStreamStr ); if (ForReal && fork() == 0) { char binPath[128]; if (li->li_StartDelay > 0) sleep(li->li_StartDelay); if (li->li_Priority > 0) nice(li->li_Priority); snprintf(binPath, sizeof(binPath), "%s/dbin/dnewslink", NewsHome); /* * realtime option is '-r'. If a delay of -1 * is specified, we pass -r-1 to dnewslink which * reduces the tail latency from 1 second to 1ms. */ execl(binPath, "dnewslink", "-h", li->li_HostName, "-b", spoolFile, "-P", portBuf, "-N", "100", /* 1000 spool cycles */ ((li->li_StartDelay < 0) ? "-r-1" : "-r"), ((flags & SF_NOTIFY) ? "-o" : "-nop"), ((flags & SF_NOTIFY) ? spoolFile : "-nop"), ((flags & SF_NOSTREAM) ? "-i" : "-nop"), ((flags & SF_HEADFEED) ? ((flags & SF_PRESBYTES) ? "-HB" : "-H") : "-nop"), (((flags & SF_NOCHECK)||(li->li_Check==2)) ? "-I" : "-nop"), ((flags & SF_GENLINES) ? "-L" : "-nop"), ((flags & SF_ARTSTAT) ? "-x" : "-nop"), compressStr, logartsStr, outboundIpStr, txBufSizeStr, rxBufSizeStr, delayStr, maxStreamStr, NULL ); exit(0); } } close(fd); } } } return(flags); }
mountlist mountlist_list(void) { static mountlist mlist = NULL; static time_t last_mtime = 0; mountlist m; struct rmtabent *rep; struct stat stb; int lockid; if ((lockid = xflock(_PATH_RMTABLCK, "r")) < 0) return NULL; if (stat(_PATH_RMTAB, &stb) < 0) { xlog(L_ERROR, "can't stat %s: %s", _PATH_RMTAB, strerror(errno)); xfunlock(lockid); return NULL; } if (stb.st_mtime != last_mtime) { mountlist_freeall(mlist); mlist = NULL; last_mtime = stb.st_mtime; setrmtabent("r"); while ((rep = getrmtabent(1, NULL)) != NULL) { m = calloc(1, sizeof(*m)); if (m == NULL) { mountlist_freeall(mlist); mlist = NULL; xlog(L_ERROR, "%s: memory allocation failed", __func__); break; } if (reverse_resolve) { struct addrinfo *ai; ai = host_pton(rep->r_client); if (ai != NULL) { m->ml_hostname = host_canonname(ai->ai_addr); freeaddrinfo(ai); } } if (m->ml_hostname == NULL) m->ml_hostname = strdup(rep->r_client); m->ml_directory = strdup(rep->r_path); if (m->ml_hostname == NULL || m->ml_directory == NULL) { mountlist_freeall(mlist); mlist = NULL; xlog(L_ERROR, "%s: memory allocation failed", __func__); break; } m->ml_next = mlist; mlist = m; } endrmtabent(); } xfunlock(lockid); return mlist; }