⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 library.c

📁 P2P NAP的C实现 P2P在网络应用中越来越流行
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (c) 2000  Kevin Sullivan <nite@gis.net> * * Please refer to the COPYRIGHT file for more information. *//* ---------------------------------------------------------------------- *//* functions that deal with reading and writing the library file. */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include "library.h"#include "nap.h"#include "defines.h"#include "lists.h"#include "codes.h"#include "alias.h"#include "winio.h"#ifdef MEMWATCH  #include "memwatch.h"#endifmasquerade_t *masqlist = NULL;int masqcounter = 0;/* read the library file SD into a library data structure. Return NULL   on failure. */library_t *read_library_file(char *sd) {  library_t *l, *elt;  char *p0, *p1, *p2, *p3, *p4, *r;  FILE *f;    if (!sd) {    return NULL;  }  f = fopen(sd, "r");  if (!f) {    return NULL;  }  r = nap_getline(f);  if (!r) {    fclose(f);    return NULL;  }  if (strcmp(r, NAP_LIBRARY_HEADER)!=0) {    fclose(f);    free(r);    return 0;  }  free(r);  l = NULL;    while (1) {    r = nap_getline(f);    if (!r) {      break;    }    if (*r != '\"') {      free(r);      continue;  /* skip headers and junk */    }    p0 = strchr(r+1, '\"');    if (!p0 || p0[1]!=' ') {      free(r);      continue;    }    p1 = strchr(p0+2, ' ');    if (!p1) {      free(r);      continue;    }    p2 = strchr(p1+1, ' ');    if (!p2) {      free(r);      continue;    }    p3 = strchr(p2+1, ' ');    if (!p3) {      free(r);      continue;    }    p4 = strchr(p3+1, ' ');    if (!p4) {      free(r);      continue;    }    elt = malloc(sizeof(library_t));    if (!elt) {      free(r);      continue;    }    *p0 = 0;    *p1 = 0;    *p2 = 0;    *p3 = 0;    *p4 = 0;    elt->lfn = strdup(r+1);    elt->hash = strdup(p0+2);    elt->sz = atoi(p1+1);    elt->bitrate = atoi(p2+1);    elt->freq = atoi(p3+1);    elt->len = atoi(p4+1);    free(r);    list_append(library_t, l, elt);  }  fclose(f);  return l;}  /* Note: the format of the library file changed in v1.4.4-ps5: two   lines were added at the beginning: a title, and the "upload" path   that was used to create the file. This allows us to check whether   the library needs re-building, see up_to_date(). -PS *//* "unshare" the old files with the server, then rebuild library, then   "share" new files. */int rebuild(int s, char *sd, char *path){  /* tell server to unshare files */  if (s!=-1) {    sendpack(s, NAP_UNSHARE, NULL);  }  if (buildflist(sd, path) == -1) {    return(-1);  }    /* schedule new file list for sending to server */  lfiles(s, sd);  return(1);}/* check whether the given filename FN is shared, by looking it up in   the library file SD. This is used for security purposes before   allowing an upload. Note: filename must use "/" and not "\". Return   1 if shared, 0 if not. When in doubt, return 0. Note: we compare   filenames here in a case sensitive manner. This may or may not be   correct. Pros: we have exact control over which files are shared.   Cons: dumb remote clients, or dumb servers, may convert filenames   to lowercase or to uppercase, thus resulting in a request that we   cannot fulfill. However, I have not seen this happen in practice. */int isshared(char *fn, char *sd) {  FILE *f;  char *r, *p;  f = fopen(sd, "r");  if (f == NULL) {    return(0);  }    while (1)  {    r = nap_getline(f);    if (!r)      break;    if (*r != '\"') {      free(r);      continue; /* skip headers and junk */    }    p = strchr(r+1, '\"');    if (!p) {      free(r);      continue;    }    *p = 0;    if (!strcmp(r+1, fn)) {      free(r);      fclose(f);      return 1;    }    free(r);  }  fclose(f);  return 0;}  /* build the library file. sd is the name of the library file, and   path is the ";"-separated sequence of upload directories. New in   1.5.1: read the old contents first, and do not regenerate file   stats where they are already known. */int buildflist(char *sd, char *path){  FILE *f;  char *t, *n;  dev_inode_t *di_list=NULL, *e;  char *sharetypes = getval("sharetypes");  library_t *l, *le;  struct stat st;  time_t reftime;  int r;  r = stat(sd, &st);  if (r==0) {    reftime = st.st_mtime;    l = read_library_file(sd);  } else {    reftime = 0;    l = NULL;  }  f = fopen(sd, "w");  if (f == NULL)  {    wp(NULL, "Error opening \"%s\": %s\n", sd, strerror(errno));    list_forall_unlink(le, l) {      free(le->lfn);      free(le->hash);      free(le);    }    return(-1);  }    fprintf(f, NAP_LIBRARY_HEADER "\n");  fprintf(f, "PATH=%s\n", path ? path : "");  fprintf(f, "SHARETYPES=%s\n", sharetypes ? sharetypes : "");  /* note: if path==NULL, we just generate an empty file */  if (path) {    n = strdup(path);        t = strtok(n, ";");        while (t)      {	t = strip(t);  /* remove whitespace on both ends */	t = home_file(t);	if (t[0] && t[strlen(t)-1]=='/') {  /* strip '/' from end */	  t[strlen(t)-1]=0;	}	addfile(t, f, &di_list, l, reftime);	free(t);	t = strtok(NULL, ";");      }        free(n);  }  fclose(f);  list_forall_unlink(e, di_list) {    free(e);  }  list_forall_unlink(le, l) {    free(le->lfn);    free(le->hash);    free(le);  }    return(1);}/* add the file or directory nm to the library file f. Be careful   to avoid loops due to symlinks: DI_LIST is a linked list of   device/inode pairs (of directories) that we have already seen. */void addfile(char *fn, FILE *f, dev_inode_t **di_list_p, library_t *l, time_t reftime){  DIR *dir;  struct stat st;  int ret;  dev_inode_t *e;  mhdr_t *m;  struct dirent *dirent;  library_t *elt;  ret = stat(fn, &st);  if (ret) { /* ignore files that don't exist */    return;  }  if (S_ISDIR(st.st_mode)) {  /* is it a directory? */    /* do not recurse if we've seen this dir before */    list_find(e, *di_list_p, e->dev == st.st_dev && e->ino == st.st_ino);    if (e) {      return;    }    /* else, remember dir */    e = (dev_inode_t *)malloc(sizeof(dev_inode_t));    e->dev = st.st_dev;    e->ino = st.st_ino;    list_prepend(*di_list_p, e);    /* now go through each file in this directory. */    dir = opendir(fn); /* open directory */    if (dir==NULL) {   /* ignore failures */      return;    }    while ((dirent = readdir(dir)) != NULL) { /* go through each entry */      /* make sure to ignore ".." and "." */      if (strcmp(dirent->d_name, "..")!=0 && strcmp(dirent->d_name, ".")!=0) {	int len = strlen(fn)+strlen(dirent->d_name)+2;	char filename[len]; /* Note: this goes on the stack */	strcpy(filename, fn);	strcat(filename, "/");	strcat(filename, dirent->d_name);	addfile(filename, f, di_list_p, l, reftime);      }    }    closedir(dir);    return;  } else if (S_ISREG(st.st_mode)) { /* is it a regular file? */    /* see if the stats for this file are already known */    if (st.st_mtime < reftime) {      list_find(elt, l, strcmp(elt->lfn, fn)==0);      /* as a special case, if hashing is requested but the cached	 value is bogus, we don't use the cached value */      if (elt && !(nvar_default("hash",0) && strncmp(elt->hash, BOGUS_HASH, 32)==0)) {	fprintf(f, "\"%s\" %s %i %i %i %i\n", elt->lfn, elt->hash, elt->sz, elt->bitrate, elt->freq, elt->len);	return;      }    }    /* otherwise, calculate stats now */    m = filestats(fn);    if (m) {      fprintf(f, "\"%s\" %s-%i %i %i %i %i\n", fn, m->check, m->sz1, m->sz, m->bitrate, m->freq, m->len);      free(m);    }    return;  }}/* decide whether a given file is shared, and if yes, get the file   stats (checksum, size, bitrate etc). A file is shared if: either it   is a valid mp3 file, or its file extension is in the sharetypes   list. Thus, the sharetypes variable only needs to list file   extensions other than mp3 - valid mp3 files are shared irrespective   of their extension. */mhdr_t *filestats(char *fn) {  mhdr_t *m;  char *p, *q;  int plen, fnlen;  int r;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -