void writefile(struct Dir *dir, const char *name) { int r, fd; struct File *f; struct stat st; const char *last; char *start; if ((fd = open(name, O_RDONLY)) < 0) panic("open %s: %s", name, strerror(errno)); if ((r = fstat(fd, &st)) < 0) panic("stat %s: %s", name, strerror(errno)); if (!S_ISREG(st.st_mode)) panic("%s is not a regular file", name); if (st.st_size >= MAXFILESIZE) panic("%s too large", name); last = strrchr(name, '/'); if (last) last++; else last = name; f = diradd(dir, FTYPE_REG, last); start = alloc(st.st_size); readn(fd, start, st.st_size); finishfile(f, blockof(start), st.st_size); close(fd); }
void * alloc(uint32_t bytes) { void *start = diskpos; diskpos += ROUNDUP(bytes, BLKSIZE); if (blockof(diskpos) >= nblocks) panic("out of disk blocks"); return start; }
/* * Initialize a message structure. */ static void message_init(struct message *mp, off_t offset, short flags) { /* use memset so new fields are always zeroed */ (void)memset(mp, 0, sizeof(*mp)); mp->m_flag = flags; mp->m_block = blockof(offset); mp->m_offset = blkoffsetof(offset); }
/* * Edit a message by writing the message into a funnily-named file * (which should not exist) and forking an editor on it. * We get the editor from the stuff above. */ int edit1(int *msgvec, int type) { int c, i; FILE *fp; struct sigaction oact; sigset_t oset; struct message *mp; off_t size; /* * Deal with each message to be edited . . . */ for (i = 0; msgvec[i] && i < msgCount; i++) { if (i > 0) { char buf[100]; char *p; printf("Edit message %d [ynq]? ", msgvec[i]); if (fgets(buf, sizeof(buf), stdin) == NULL) break; for (p = buf; *p == ' ' || *p == '\t'; p++) ; if (*p == 'q') break; if (*p == 'n') continue; } dot = mp = &message[msgvec[i] - 1]; touch(mp); (void)ignoresig(SIGINT, &oact, &oset); fp = run_editor(setinput(mp), (off_t)mp->m_size, type, readonly); if (fp != NULL) { (void)fseek(otf, 0L, SEEK_END); size = ftell(otf); mp->m_block = blockof(size); mp->m_offset = offsetof(size); mp->m_size = fsize(fp); mp->m_lines = 0; mp->m_flag |= MODIFY; rewind(fp); while ((c = getc(fp)) != EOF) { if (c == '\n') mp->m_lines++; if (putc(c, otf) == EOF) break; } if (ferror(otf)) warn("%s", tmpdir); (void)Fclose(fp); } (void)sigprocmask(SIG_SETMASK, &oset, NULL); (void)sigaction(SIGINT, &oact, NULL); } return(0); }
void finishdir(struct Dir *d) { int size = d->n * sizeof(struct File); struct File *start = alloc(size); memmove(start, d->ents, size); finishfile(d->f, blockof(start), ROUNDUP(size, BLKSIZE)); free(d->ents); d->ents = NULL; }
/* * Edit a message by writing the message into a funnily-named file * (which should not exist) and forking an editor on it. * We get the editor from the stuff above. */ int edit1(int *msgvec, int type) { int c, i; FILE *fp; struct message *mp; off_t size; /* * Deal with each message to be edited . . . */ for (i = 0; msgvec[i] && i < msgCount; i++) { sig_t sigint; if (i > 0) { char buf[100]; char *p; printf("Edit message %d [ynq]? ", msgvec[i]); if (fgets(buf, sizeof(buf), stdin) == 0) break; for (p = buf; *p == ' ' || *p == '\t'; p++) ; if (*p == 'q') break; if (*p == 'n') continue; } dot = mp = &message[msgvec[i] - 1]; touch(mp); sigint = signal(SIGINT, SIG_IGN); fp = run_editor(setinput(mp), mp->m_size, type, readonly); if (fp != NULL) { fseeko(otf, (off_t)0, SEEK_END); size = ftello(otf); mp->m_block = blockof(size); mp->m_offset = boffsetof(size); mp->m_size = (long)fsize(fp); mp->m_lines = 0; mp->m_flag |= MODIFY; rewind(fp); while ((c = getc(fp)) != EOF) { if (c == '\n') mp->m_lines++; if (putc(c, otf) == EOF) break; } if (ferror(otf)) warnx("/tmp"); Fclose(fp); } signal(SIGINT, sigint); } return (0); }
void finishdisk(void) { int r, i; for (i = 0; i < blockof(diskpos); ++i) bitmap[i/32] &= ~(1<<(i%32)); if ((r = msync(diskmap, nblocks * BLKSIZE, MS_SYNC)) < 0) panic("msync: %s", strerror(errno)); }
void finishfile(struct File *f, uint32_t start, uint32_t len) { int i; f->f_size = len; len = ROUNDUP(len, BLKSIZE); for (i = 0; i < len / BLKSIZE && i < NDIRECT; ++i) f->f_direct[i] = start + i; if (i == NDIRECT) { uint32_t *ind = alloc(BLKSIZE); f->f_indirect = blockof(ind); for (; i < len / BLKSIZE; ++i) ind[i - NDIRECT] = start + i; } }
/* * Set up the input pointers while copying the mail file into /tmp. */ void setptr(FILE *ibuf, off_t offset) { int c, count; char *cp, *cp2; struct message this; FILE *mestmp; int maybe, inhead; char linebuf[LINESIZE], pathbuf[PATHSIZE]; int omsgCount; /* Get temporary file. */ (void)snprintf(pathbuf, sizeof(pathbuf), "%s/mail.XXXXXXXXXX", tmpdir); if ((c = mkstemp(pathbuf)) == -1 || (mestmp = Fdopen(c, "r+")) == NULL) err(1, "can't open %s", pathbuf); (void)rm(pathbuf); if (offset == 0) { msgCount = 0; } else { /* Seek into the file to get to the new messages */ (void)fseeko(ibuf, offset, SEEK_SET); /* * We need to make "offset" a pointer to the end of * the temp file that has the copy of the mail file. * If any messages have been edited, this will be * different from the offset into the mail file. */ (void)fseeko(otf, (off_t)0, SEEK_END); offset = ftello(otf); } omsgCount = msgCount; maybe = 1; inhead = 0; this.m_flag = MUSED|MNEW; this.m_size = 0; this.m_lines = 0; this.m_block = 0; this.m_offset = 0; for (;;) { if (fgets(linebuf, sizeof(linebuf), ibuf) == NULL) { if (append(&this, mestmp)) errx(1, "temporary file"); makemessage(mestmp, omsgCount); return; } count = strlen(linebuf); /* * Transforms lines ending in <CR><LF> to just <LF>. * This allows mail to be able to read Eudora mailboxes. */ if (count >= 2 && linebuf[count - 1] == '\n' && linebuf[count - 2] == '\r') { count--; linebuf[count - 1] = '\n'; } (void)fwrite(linebuf, sizeof(*linebuf), count, otf); if (ferror(otf)) errx(1, "/tmp"); if (count) linebuf[count - 1] = '\0'; if (maybe && linebuf[0] == 'F' && ishead(linebuf)) { msgCount++; if (append(&this, mestmp)) errx(1, "temporary file"); this.m_flag = MUSED|MNEW; this.m_size = 0; this.m_lines = 0; this.m_block = blockof(offset); this.m_offset = boffsetof(offset); inhead = 1; } else if (linebuf[0] == 0) { inhead = 0; } else if (inhead) { for (cp = linebuf, cp2 = "status";; cp++) { if ((c = *cp2++) == '\0') { while (isspace((unsigned char)*cp++)) ; if (cp[-1] != ':') break; while ((c = *cp++) != '\0') if (c == 'R') this.m_flag |= MREAD; else if (c == 'O') this.m_flag &= ~MNEW; inhead = 0; break; } if (*cp != c && *cp != toupper((unsigned char)c)) break; } } offset += count; this.m_size += count; this.m_lines++; maybe = linebuf[0] == 0; } }