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

📄 library.c

📁 P2P NAP的C实现 P2P在网络应用中越来越流行
💻 C
📖 第 1 页 / 共 2 页
字号:
  int f;  struct stat st;  char *sharetypes;  /* first, check if this is a valid mp3 file (irrespective of extension) */  m = mp3info(fn);  if (m)    return m;  /* next, check if it's a valid ogg vorbis file (irrespective of extension) */  m = ogginfo(fn);  if (m)    return m;  /* not a valid music file - check to see if it is shared by its file     extension */  sharetypes = getval("sharetypes");  if (!sharetypes) {    return NULL;  }  fnlen = strlen(fn);  p = sharetypes;  for (p=sharetypes; p != (void *)NULL+1; p = strchr(p, ';')+1) {    q = strchr(p, ';');    plen = (q) ? q-p : strlen(p);    if (plen == 1 && *p=='*')      goto matches;    if (fnlen >= plen+1 && fn[fnlen-plen-1]=='.' && strncasecmp(fn+fnlen-plen, p, plen)==0)      goto matches;  }  return NULL; matches:  /* try to open file */  f = open(fn, O_RDONLY);  if (f == -1)    return(NULL);    /* get file attributes, e.g. file size */  fstat(f, &st);  m = (mhdr_t *)malloc(sizeof(mhdr_t));  /* not a music file: set freq, len, and bitrate to 0 */  m->freq = 0;  m->len = 0;  m->bitrate = 0;  m->sz = st.st_size;  m->sz1 = st.st_size;  r = md5hash(m->check, f);  if (r) {    free(m);    close(f);    return(NULL);  }  close(f);  return(m);}/* schedule the files that we are sharing for sending to the   server. SD is the library filename, S is the server fd. */int lfiles(int s, char *sd) {  sock_t *sv;  library_t *l, *elt;  char *vfn;  sv = findsockfd(s);  if (!sv) {    return -1;  }  l = read_library_file(sd);  list_forall_unlink(elt, l) {    if (nvar_default("nomasq", 0) == 0) {      /* do filename masquerading */      vfn = masquerade(elt->lfn);      free(elt->lfn);      elt->lfn = vfn;    }    if (elt->lfn) {      list_append(library_t, sv->shared_to_send, elt);    } else {      /* this should not normally happen: file was not on shared	 path, or could not be rewritten somehow */      free(elt->hash);      free(elt);          }  }  return 1;}/* decide whether the library file SD is up-to-date relative to PATH.   Check: nap version number, path, and whether any files in the PATH   have been modified more recently than library file. Return 1 if   up-to-date, 0 if not. */int up_to_date(char *sd, char *path) {  FILE *f;  char *r, *n, *t;  struct stat st;  time_t mtime;  dev_inode_t *di_list, *e;  int ret, res;  char *sharetypes = getval("sharetypes");  if (!sd) {    return 0;  }  f = fopen(sd, "r");  if (!f) {    return 0;  }  r = nap_getline(f);  if (!r) {    fclose(f);    return 0;  }  if (strcmp(r, NAP_LIBRARY_HEADER)!=0) {     fclose(f);    free(r);    return 0;  }  free(r);  r = nap_getline(f);  if (!r) {    fclose(f);    return 0;  }  if (strncmp(r, "PATH=", 5) || strcasecmp(r+5, path ? path : "")) {     fclose(f);    free(r);    return 0;  }    free(r);  r = nap_getline(f);  if (!r) {    fclose(f);    return 0;  }  if (strncmp(r, "SHARETYPES=", 11) || strcmp(r+11, sharetypes ? sharetypes : "")) {     fclose(f);    free(r);    return 0;  }    free(r);  /* the info in the file seemed okay */  fclose(f);    /* now check the modification times. */  ret = stat(sd, &st);  if (ret)    return 0;  mtime = st.st_mtime; /* remember modification time of library file */  di_list = NULL;  res = 1;  /* now check whether each directory on path was modified after mtime */  if (path) {    n = strdup(path);    for (t=strtok(n, ";"); t; t=strtok(NULL, ";")) {      t = strip(t);      t = home_file(t);      if (modified_after(mtime, t, &di_list)) {	res = 0;	free(t);	break;      }      free(t);    }    free(n);  }  list_forall_unlink(e, di_list) {    free(e);  }    return res;}/* check whether file or directory FN was modified at or after time   MTIME. If it's a directory, also check files and subdirectories   recursively. Be careful to avoid loops due to symlinks: DI_LIST is   a linked list of device/inode pairs that we have already seen. */int modified_after(time_t mtime, char *fn, dev_inode_t **di_list_p) {  struct stat st;  int ret;  dev_inode_t *e;  DIR *dir;  struct dirent *dirent;  ret = stat(fn, &st);  if (ret) { /* file does not exist? Let's ignore it and hope for the                best. Note this could be a problem if user deleted an                entire upload directory. */    return 0;  }  if (st.st_mtime >= mtime) {    return 1;  }  if (!S_ISDIR(st.st_mode)) { /* if it's not a directory, we are done */    return 0;  }  /* 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 0;  }  /* else remember dir, and recurse */  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. Blah. */  dir = opendir(fn); /* open directory */  if (dir==NULL) {   /* if open fails, ignore gracefully */    return 0;  }  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: don't need alloc. This goes on the stack */      strcpy(filename, fn);      strcat(filename, "/");      strcat(filename, dirent->d_name);      if (modified_after(mtime, filename, di_list_p)) {	closedir(dir);	return 1;      }    }  }  closedir(dir);  return 0;}/* ---------------------------------------------------------------------- *//* filename masquerading *//* Suppose our upload path is PATH1;PATH2. Then we replace absolute   local filenames such as PATH1/file1 or PATH2/x/file2 by "virtual   filenames" like /1/file1, /2/x/file2, so that we don't reveal our   local directory structure to the world. Note: this will not work   properly if we actually have directories named /1/, /2/ on our   share path! *//* convert local pathname to virtual pathname. Returns an allocated   string, or NULL on failure. In particular, return NULL if the path   is not shared. (Note however that we do not check whether path is   in the shared *library* file - this also depends on its filename   extension, whether the file contents are valid, etc. It needs to be   checked separately.) */char *masquerade(char *lfn) {  char *upload = getval("upload");  char *vfn=NULL, *t;  char *match=NULL;  masquerade_t *elt;  int len;  if (!upload) {    return NULL;  }  upload = strdup(upload);  t = strtok(upload, ";");  while (t) {    t = strip(t);    if (!t[0]) {      goto next;    }    t = home_file(t);    len = strlen(t);    if (!t[0] || t[len-1]!='/') {  /* make sure the path ends in '/' */      t = realloc(t, len+2);      if (!t) {	goto next;      }      t[len+1] = 0;      t[len] = '/';      len++;    }    if (strncmp(lfn, t, len)==0) {      if (!match || len >= strlen(match)) {	free(match);	match = strdup(t);      }    }  next:    free(t);    t = strtok(NULL, ";");  }  free(upload);  if (!match) {    return NULL;  }  list_find(elt, masqlist, strcmp(elt->path, match)==0);  if (!elt) {    elt = malloc(sizeof(masquerade_t));    if (!elt) {      free(match);      return NULL;    }    elt->path = strdup(match);    elt->n = ++masqcounter;    list_prepend(masqlist, elt);  }  /* rewrite */  msprintf(&vfn, "/%d/%s", elt->n, lfn+strlen(match));  free(match);  return vfn;}/* convert virtual pathname to local pathname. If not possible, return   a copy of vfn. In any case, return an allocated string. */char *unmasquerade(char *vfn) {  char *lfn=NULL;  int n;  char *p;  masquerade_t *elt;    /* check if vfn begins with /n/, where n is an integer */  if (vfn[0] != '/') {    return strdup(vfn);  }  n = strtod(vfn+1, &p);  if (p==vfn+1 || *p != '/') {    return strdup(vfn);  }  /* found an integer; check whether it is known */  list_find(elt, masqlist, elt->n == n);  if (!elt) {    return strdup(vfn);  }  /* do the substitution */  msprintf(&lfn, "%s%s", elt->path, p+1);  return lfn;}

⌨️ 快捷键说明

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