Exemplo n.º 1
0
Arquivo: client.c Projeto: hpc/Spindle
int get_existance_test(int fd, const char *path, int *exists)
{
   int use_cache = (opts & OPT_SHMCACHE) && (shm_cachesize > 0);
   int found_file, result;
   char cache_name[MAX_PATH_LEN+2];
   char *exist_str;

   if (use_cache) {
      debug_printf2("Looking up file existance for %s in shared cache\n", path);
      get_cache_name(path, "&", cache_name);
      cache_name[sizeof(cache_name)-1] = '\0';
      found_file = fetch_from_cache(cache_name, &exist_str);
      if (found_file) {
         *exists = (exist_str[0] == 'y');
         return 0;
      }
   }

   result = send_existance_test(fd, (char *) path, exists);
   if (result == -1)
      return -1;

   if (use_cache) {
      exist_str = *exists ? "y" : "n";
      shmcache_update(cache_name, exist_str);
   }
   return 0;
}
Exemplo n.º 2
0
Arquivo: client.c Projeto: hpc/Spindle
int get_stat_result(int fd, const char *path, int is_lstat, int *exists, struct stat *buf)
{
   int result;
   char buffer[MAX_PATH_LEN+1];
   char cache_name[MAX_PATH_LEN+3];
   char *newpath;
   int use_cache = (opts & OPT_SHMCACHE) && (shm_cachesize > 0);
   int found_file = 0;

   if (use_cache) {
      debug_printf2("Looking up %sstat for %s in shared cache\n", is_lstat ? "l" : "", path);
      get_cache_name(path, is_lstat ? "**" : "*", cache_name);
      cache_name[sizeof(cache_name)-1] = '\0';
      found_file = fetch_from_cache(cache_name, &newpath);
   }

   if (!found_file) {
      result = send_stat_request(fd, (char *) path, is_lstat, buffer);
      if (result == -1) {
         *exists = 0;
         return -1;
      }
      newpath = buffer[0] != '\0' ? buffer : NULL;

      if (use_cache) 
         shmcache_update(cache_name, newpath);
   }
   
   if (newpath == NULL) {
      *exists = 0;
      return 0;
   }
   *exists = 1;

   test_log(newpath);
   result = read_stat(newpath, buf);
   if (result == -1) {
      err_printf("Failed to read stat info for %s from %s\n", path, newpath);
      *exists = 0;
      return -1;
   }
   return 0;
}
Exemplo n.º 3
0
Arquivo: client.c Projeto: hpc/Spindle
int get_relocated_file(int fd, const char *name, char** newname, int *errorcode)
{
   int found_file = 0;
   int use_cache = (opts & OPT_SHMCACHE) && (shm_cachesize > 0);
   char cache_name[MAX_PATH_LEN+1];

   if (use_cache) {
      debug_printf2("Looking up %s in shared cache\n", name);
      get_cache_name(name, "", cache_name);
      cache_name[sizeof(cache_name)-1] = '\0';
      found_file = fetch_from_cache(cache_name, newname);
   }

   if (!found_file) {
      debug_printf2("Send file request to server: %s\n", name);
      send_file_query(fd, (char *) name, newname, errorcode);
      debug_printf2("Recv file from server: %s\n", *newname ? *newname : "NONE");      
      if (use_cache)
         shmcache_update(cache_name, *newname);
   }

   return 0;
}
Exemplo n.º 4
0
/* Thread per sessione di connessione */
static void *Session (void *p) {

	int clifd;												/* Socket Client-Proxy */
	int servfd;												/* Socket Proxy-Server */
	int ris;													/* Utili */
	struct Request req;								/* Conterrà le informazioni per forward e prefetch */
	struct Response resp;							/* Conterrà info per invio file cache, struttura richiesta da prepareResponse ecc */
	char cache_filename[MAXLENPATH];
	char error_response[16];
	char buffer[MAXLENRESP];
	int buffer_len;
	struct sockaddr_in Local, Serv; 	/* Per connessione con il server */

	/* Client socket Timeout */
	struct timeval timercli;
	timercli.tv_sec = INACTIVITY_TIMEOUT_SECONDS;
	timercli.tv_usec = 0;

	/* Estrazione informazioni parametro thread */
	clifd = ((struct param*)p)->fd;
	free(p);
	p = NULL;

	/* Controllo sul numero dei thread */
	pthread_mutex_lock(&mutex_num);
	if(numthread < MAXNUMTHREADWORKING)
		numthread++;
	pthread_mutex_unlock(&mutex_num);
	if(numthread >= MAXNUMTHREADWORKING) {
		close(clifd);
		exitThread();
		return(NULL);
	}

#ifdef DEBUG
printf("Thread: %ld. Client FD passato: %d\n", pthread_self(), clifd);
fflush(stdout);
#endif

	/* Imposto il timeout per questo socket client */
	setsockopt(clifd, SOL_SOCKET, SO_RCVTIMEO, &timercli, sizeof(struct timeval));
	setsockopt(clifd, SOL_SOCKET, SO_SNDTIMEO, &timercli, sizeof(struct timeval));

	/* Inizializzo struttura per richiesta */
	initRequest(&req);

	/* 
		Prelevo la richiesta ed estraggo le informazioni.
		Se a buon fine l'avrò tutta in req->buf, mentre il resto sarà estratto e messo negli altri campi di req.
	*/
	ris = getRequest(clifd,&req);

	switch(ris) {

		case -3: /* Client ha chiuso la connessione */

#ifdef DEBUG
printf("Thread: %ld. Client ha chiuso connessione. \nBuffer: %s\n", pthread_self(), req.buf);
fflush(stdout);
#endif

			close(clifd);
			exitThread();
			return(NULL);
		break;

		case -2: /* Errore in lettura, chiudo thread e connessione */

#ifdef DEBUG
printf("Thread: %ld. Errore in lettura client request. \nBuffer: %s\n", pthread_self(), req.buf);
fflush(stdout);
#endif

			close(clifd);
			exitThread();
			return(NULL);
		break;

		case -1: /* Lettura richiesta terminata, formato richiesta sbagliato */
			strcpy(error_response, "403\n\n");
			mysend(clifd, error_response, strlen(error_response));

#ifdef DEBUG
printf("Thread: %ld. Lettura req terminata, formato richiesta sbagliato. \nBuffer: %s\n", pthread_self(), req.buf);
fflush(stdout);
#endif

			close(clifd);
			exitThread();
			return(NULL);
		break;

		case 1: /* Lettura richiesta OK -> proseguo */

#ifdef DEBUG
printf("Thread: %ld. Lettura req OK. \nBuffer: %s\n", pthread_self(), req.buf);
fflush(stdout);
#endif

		break;
		
		default: /* Errore sconosciuto */
			strcpy(error_response, "402\n\n");
			mysend(clifd, error_response, strlen(error_response));

#ifdef DEBUG
printf("Thread: %ld. Errore sconosciuto. \nBuffer: %s\n", pthread_self(), req.buf);
fflush(stdout);
#endif

			close(clifd);
			exitThread();
			return(NULL);
		break;

	}	/* Switch */

	/* Ora ho nella struttura Request tutte le informazioni che mi servono */

	/* Tentativi connessione server */
	int servconn_chance = SERVER_CHANCE;

	/* 
		Ogni qualvolta ritento una connessione con il server per errori, 
		ricontrollo di avere il file in cache, qualche altro thread 
		potrebbe averlo	salvato nel frattempo.
	*/
	while (1) {

#ifdef DEBUG
printf("Controllo su thread: %ld. While session().\n", pthread_self());
fflush(stdout);
#endif

		/* Se ha fatto una richiesta GET e ho il file in cache */
		if ((req.reqType == GET) && (get_cache_name(&(req.inaddr), req.port, req.path, cache_filename))) {

			/* Cerco di preparare la risposta da mandare (Anche con RANGE), l'eventuale contenuto del file è nel buffer di resp */
			ris = prepareGetResponse(&req, &resp, cache_filename);

#ifdef DEBUG
printf("Thread: %ld. La req è GET e ho il file in cache. \nFile: %s\n", pthread_self(), resp.buf);
fflush(stdout);
#endif

			switch(ris) {

				case 1:
					ris = mysend(clifd, resp.buf, resp.lenresp);	/* caso OK ------> MANDO AL CLIENT IL FILE CHE ERA IN CACHE e chiudo */

					if (ris == -1) {
						printf ("Error on cached file response send.\n");
						fflush(stdout);
					}
					if (ris == -2) {
						printf ("Time out on cached file response send.\n");
						fflush(stdout);
					}
					if (ris == 0) {
						printf ("Client closed connection before sending cached file.\n");
						fflush(stdout);
					}
					else {
						printf ("Cached file sent to client.\n");
						fflush(stdout);
					}
					close(clifd);
					exitThread();
					return(NULL);
				break;

				case -3: /* file not found (expired nel frattempo) ---> faccio la richiesta */

#ifdef DEBUG
printf("Thread: %ld. Avevo il file ma è expired. \n", pthread_self());
fflush(stdout);
#endif

				break;

				case -4: /* interval not found -----> lo notifico */
					strcpy(error_response, "405\n\n");
					mysend(clifd, error_response, strlen(error_response));

#ifdef DEBUG
printf("Thread: %ld. Avevo il file ma il RANGE è sbagliato. \n", pthread_self());
fflush(stdout);
#endif

					close(clifd);
					exitThread();
					return(NULL);
				break;

				case -5: /* unknown error */
				default:
					strcpy(error_response, "402\n\n");
					mysend(clifd, error_response, strlen(error_response));

#ifdef DEBUG
printf("Thread: %ld. Avevo il file ma dopo la prepareResponse errore sconosciuto.\n", pthread_self());
fflush(stdout);
#endif

					close(clifd);
					exitThread();
					return(NULL);
				break;
			}
		} /* Fine GET e ho il file in cache */
	
	/* Non ho file in cache oppure richiesta INF -> Forward richiesta al server e poi discrimino in base a GET (prefetch) e INF (solo forward risposta) */

		servfd = socket(AF_INET, SOCK_STREAM, 0);
		if (servfd < 0) {
			printf("Thread: %ld. Chiamata a socket() per serverfd fallita. Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno));
			fflush(stdout);
			close(clifd);
			exitThread();
			return(NULL);
		}

		/* Server socket Timeout */
		struct timeval timerserv;
		timerserv.tv_sec = INACTIVITY_TIMEOUT_SECONDS;
		timerserv.tv_usec = 0;

		if ((SetsockoptReuseAddr(servfd) == 0) ||
				(setsockopt(servfd, SOL_SOCKET, SO_RCVTIMEO, &timerserv, sizeof(struct timeval)) != 0) ||
				(setsockopt(servfd, SOL_SOCKET, SO_SNDTIMEO, &timerserv, sizeof(struct timeval)) != 0)) {
			printf("Thread: %ld. Error on a setsockopt for server socket\n", pthread_self());
			fflush(stdout);

			close(servfd);
			close(clifd);
			exitThread();
			return(NULL);
		}

		/* Binding */
		memset(&Local, 0, sizeof(Local));
		Local.sin_family = AF_INET;
		Local.sin_addr.s_addr = INADDR_ANY;
		Local.sin_port = htons(0);

		ris = bind(servfd, (struct sockaddr *)&Local, sizeof(Local));
		if (ris < 0) {
			printf("Thread: %ld. Chiamata a bind() per serverfd fallita. Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno));
			fflush(stdout);
			close(servfd);
			exitThread();
			return(NULL);
		}

		/* Compilo campi server */
		memset(&Serv, 0, sizeof(Serv));
		Serv.sin_family = AF_INET;
		Serv.sin_addr.s_addr = req.inaddr.s_addr;
		Serv.sin_port = htons(req.port);

#ifdef DEBUG
printf ("Thread: %ld, %d° tentativo connessione con server. FD: %d\n", pthread_self(), (SERVER_CHANCE-servconn_chance+1), servfd);
fflush(stdout);
#endif

		int repeat;
		repeat = 0;	
		while (1) {

#ifdef DEBUG
printf("Controllo su thread: %ld. While connect session.\n", pthread_self());
fflush(stdout);
#endif

			ris = connect (servfd, (struct sockaddr *)&Serv, sizeof(Serv));
			if (ris < 0) {
				if ((errno == EINTR) || (errno == EINPROGRESS)) ; /* Ritento */
				if (errno == EISCONN) {
					printf("Thread: %ld, Chiamata a connect() per serverfd fallita. FD: %d. Errore: %d \"%s\"\n", pthread_self(), servfd, errno,strerror(errno));
					fflush(stdout);
					repeat = 0;
					break;
				}
				else {
					printf("Thread: %ld, Chiamata a connect() per serverfd fallita. FD: %d. Errore: %d \"%s\"\n", pthread_self(), servfd, errno,strerror(errno));
					fflush(stdout);
					if (servconn_chance > 0) servconn_chance--; /* Ritento */
					else {
						printf("Thread: %ld, Chiamata a connect() per serverfd fallita. FD: %d. Errore: %d \"%s\"\n", pthread_self(), servfd, errno,strerror(errno));
						fflush(stdout);
						close(servfd);
						exitThread();
						return(NULL);
					}
					/* Ritento nuovo socket */
					repeat = 1;
					break;
				}	/* Errore non recuperabile */
			} /* Error on connect */
			else {
				/* OK */
				repeat = 0;
				break;
			}
		}	/* Connect while */

		/* Se è il caso torno indietro */
		if (repeat) continue;

		/* Forwardo la richiesta, qualunque essa sia (inf/get) */

#ifdef DEBUG
printf("Thread: %ld. Forward richiesta del client al server.\n Req: %s\n", pthread_self(), req.buf);
fflush(stdout);
#endif

		ris = mysend(servfd, req.buf, strlen(req.buf));
		if (ris < 0) {

#ifdef DEBUG
printf("Thread: %ld. Errore su forward req.\n", pthread_self());
fflush(stdout);
#endif

			if (servconn_chance > 0) {
				servconn_chance--;
				close(servfd);
				continue;	/* Chiudo questa connessione e ritento */
			}
			else {
				close(clifd);
				close(servfd);
				exitThread();
				return(NULL);
			}
		}

		/* Aspetto la risposta del server */
		ris = myread(servfd, buffer, MAXLENRESP);
		if (ris <= 0) {

#ifdef DEBUG
printf("Thread: %ld. Errore in risposta server a forward req del client.\nErrore: %d \"%s\"\n", pthread_self(), errno,strerror(errno));
fflush(stdout);
#endif

			if (servconn_chance > 0) {
				servconn_chance--;
				close(servfd);
				continue;	/* Chiudo questa connessione e ritento */
			}
			else {
				close(clifd);
				close(servfd);
				exitThread();
				return(NULL);
			}
		}

#ifdef DEBUG
printf("Thread: %ld. OK arrivo risposta dal server per forward al client.\n Resp: %s\n", pthread_self(), buffer);
fflush(stdout);
#endif

		/* Concludo chiusura con server */
		close(servfd);

		/* Terminatore */
		buffer[ris] = '\0';
		buffer_len = ris;

		/* Controllo errori 40X nel qual caso forwardo e chiudo */
		if ((!(strncmp(buffer,"402\n\n",5))) ||
				(!(strncmp(buffer,"403\n\n",5))) ||
				(!(strncmp(buffer,"404\n\n",5))) ||
				(!(strncmp(buffer,"405\n\n",5)))) {

#ifdef DEBUG
printf("Thread: %ld. Server ha inviato un errore 40X, faccio forward al Client", pthread_self());
fflush(stdout);
#endif

			ris = mysend(clifd, buffer, buffer_len);
			close(clifd);
			exitThread();
			return(NULL);
		}

		/* Se la richiesta era INF faccio un parsing per INF e invio a client */
		if (req.reqType == INF) {
			/* Corretto */
			if (parseINF(buffer, buffer_len) == 0){
				ris = mysend(clifd, buffer, buffer_len);
				if (ris < 0) /* Errore irreparabile col client */

#ifdef DEBUG
printf("Thread: %ld. Errore in risposta a Client (dopo arrivo dal server).\n Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno));
fflush(stdout);
#endif

				close(clifd);
				exitThread();
				return(NULL);
			}
			/* Errato */
			else
				continue; /* Ritento */
		}

		/* Se la richiesta era GET per RANGE faccio il parsing per RANGE e poi invio il file */
		if (req.is_range) {
			/* Corretto */
			if (parseRANGE(buffer, buffer_len) == 0) ; /* Vado comunque a fare il parsing per fare prefetch sugli URL che trovo */
			/* Errato */
			else
				continue; /* Ritento */
		}

		int expire;
		char cachename[MAXLENPATH];
		struct timeval tod;

		/* Se invece la richiesta era GET per file completo prima faccio parsing per GET completo.
			 Se corretto salvo il file (così è a disposizione di altri thread) e poi invio a client */
		if (!(req.is_range)) {

#ifdef DEBUG
printf("Thread: %ld. Prelevo nome per caching.\n", pthread_self());
fflush(stdout);
#endif

			/* Prelevo nome univoco */
			my_tempname(cachename);

#ifdef DEBUG
printf("Thread: %ld. Salvo file caching.\n", pthread_self());
fflush(stdout);
#endif


			/* SE CORRETTO E COMPLETO salvo file appena scaricato in cache e prelevo expire */
			expire = buffer_data_to_file (cachename, buffer, buffer_len);

			/* Non completo / Corrotto */
			if (expire < 0) {

#ifdef DEBUG
printf("Thread: %ld. Il file arrivato è corrotto.\nEcco il file:\n", pthread_self());
fflush(stdout);
#endif

				write(1, buffer, MAXLENRESP);
				fflush(stdout);
				continue; /* Ritento da capo connessione con server e richiesta */
			}

			else {
				/* Prendo tempo attuale da sommare al tempo di expire del file appena ricevuto */
				gettimeofday(&tod, NULL);

				/* Gestione cache, aggiunta file */
				add_file_cache(&(req.inaddr), req.port, req.path, (tod.tv_sec + expire), cachename);
			}
		}
		

		/* Ora ho nel buffer ciò che devo inviare a Client e in ogni caso faccio lo stesso tipo di invio */
		ris = mysend(clifd, buffer, buffer_len);
		if (ris < 0) {	/* Errore irreparabile col client */

#ifdef DEBUG
printf("Thread: %ld. Errore in risposta a Client (dopo arrivo dal server).\n Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno));
fflush(stdout);
#endif

			close(clifd);
			exitThread();
			return(NULL);
		}

#ifdef DEBUG
printf("Thread: %ld. OK risposta dopo arrivo file del Server verso Client.\n Resp: %s\n", pthread_self(), buffer);
fflush(stdout);
#endif

		/* In ogni caso ho finito col client */
		close(clifd);

		/* Inizializzo qui, ma viene modificato nel parsing per scorrere il buffer con la risposta */
		int lenparsed = 0;
		struct Request *p_prefetch_req;
		char tmpname[MAXLENPATH];

#ifdef DEBUG
printf("Thread: %ld. Fase prefetching.\n", pthread_self());
fflush(stdout);
#endif

		while(1) {

#ifdef DEBUG
printf("Controllo su thread: %ld. While parse session().\n", pthread_self());
fflush(stdout);
#endif

			/* Struttura Request per fare richiesta al server, già passabile come parametro a thread */
			p_prefetch_req = (struct Request *) malloc (sizeof(struct Request));

			if (p_prefetch_req == NULL){

#ifdef DEBUG
printf("Thread: %ld. Errore in allocazione p_prefetch_req.\n", pthread_self());
fflush(stdout);
#endif

				exitThread();
				return(NULL);
			}
			/* Chiamo il parsing saltando almeno il minimo numero di byte che possono esserci prima dei dati.
				 NB: USO CAMPO "buf[]" della struttura Request per l'URL!! 
				 NB2: Chiedo sia REF che IDX;REF per 1° e 2° livello
			*/

#ifdef DEBUG
printf("Thread: %ld. Fase parsing del buffer.\n", pthread_self());
fflush(stdout);
#endif

			ris = parse((buffer+MIN_BYTE_BEFORE_DATA), &lenparsed, (buffer_len-MIN_BYTE_BEFORE_DATA), p_prefetch_req, FIRST_SECOND_LEVEL_PREFETCHING);

			/* Parsing finito, per errori o fine buffer */
			if(ris <= 0) {
				exitThread();
				return(NULL);
			}

			else if(ris == 1) {

#ifdef DEBUG
printf("Thread: %ld. OK parsing, URL estratto: %s.\n", pthread_self(), p_prefetch_req->buf);
fflush(stdout);
#endif

				/* Thread che fanno prefetch su REF - IDX+REF */
				pthread_attr_t attr;
				pthread_attr_init(&attr);
				pthread_t threadID;

				pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

				/* Se ho già il file passo al prossimo URL */
				if(get_cache_name(&(p_prefetch_req->inaddr), p_prefetch_req->port, p_prefetch_req->path, tmpname)) {
					free(p_prefetch_req);
					p_prefetch_req = NULL;
					continue;
				}

				/* Altrimenti setto il campo reqType della struttura Request che uso come parametro al thread, impostandolo per 
					il prefetching di primo e secondo livello.. */
				p_prefetch_req->reqType = FIRST_SECOND_LEVEL_PREFETCHING;

				/* .. e faccio partire il thread relativo alla sessione di prefetching per URL specificato in p_prefetch_req->buf[] */
				ris = pthread_create(&threadID, &attr, get_and_cache, (void *)p_prefetch_req);
				if(ris != 0) {
					printf("Thread: %ld. Chiamata a pthread_create() fallita.\n Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno));
					fflush(stdout);
					continue;
				}

			}

		} /* while del parsing */

	} /* While socket/binding */

} /* Session ****************/
Exemplo n.º 5
0
int main(int argc, char **argv) {
    int c;
    int i = 0;

    while ((c = getopt_long(argc, argv, "w:dcohv", options, &i)) != -1) {
        switch (c) {
            case 'w':
            {
                if (strcmp(optarg, "all") == 0) {
                    int i;
                    for (i = 0; i < NUM_WARNING_TYPES; i++) {
                        warning_flags[i] = 1;
                    }
                }

                if (strcmp(optarg, "shadow") == 0) {
                    warning_flags[WARNING_SHADOW] = 1;
                }

                if (strcmp(optarg, "unreachable") == 0) {
                    warning_flags[WARNING_UNREACHABLE] = 1;
                }
            } break;

            case 'd':
                disassemble_flag = 1;
                break;

            case 'c':
                compile_flag = 1;
                break;

            case 'o':
                optimize_flag = 1;
                break;

            case 'h':
                help_flag = 1;
                break;

            case 'v':
                version_flag = 1;
                break;

            case 0:
                /* getopt_long set a flag */
                break;

            default:
                /* unrecognized option */
                return EXIT_FAILURE;
        }
    }

    if (help_flag) {
        show_usage(argv[0]);
        return EXIT_SUCCESS;
    }

    if (version_flag) {
        show_version(argv[0]);
        return EXIT_SUCCESS;
    }

    if (optind == argc) {
        printf("No files supplied.\n");
        return EXIT_FAILURE;
    }

    for ( ; optind < argc; optind++) {
        if (compile_flag == 1) {
            Chunk *chunk = make(argv[optind]);
            char *output = get_cache_name(argv[optind]);

            save(chunk, output);

            free(output);
            free_chunk(chunk);
        } else {
            Chunk *chunk;

            int ret = valid_cache(argv[optind]);

            if (ret == 2) {
                fatal("Bytecode cache compiled with a different version.");
            }

            if (ret == 1) {
                chunk = load(argv[optind]);
            } else {
                chunk = make(argv[optind]);
            }

            if (disassemble_flag) {
                dis(chunk);
            } else {
                execute(chunk);
            }

            free_chunk(chunk);
        }
    }

    return EXIT_SUCCESS;
}
Exemplo n.º 6
0
int
pci_id_cache_load(struct pci_access *a, int flags)
{
  char *name;
  char line[MAX_LINE];
  FILE *f;
  int lino;

  a->id_cache_status = 1;
  name = get_cache_name(a);
  if (!name)
    return 0;
  a->debug("Using cache %s\n", name);
  if (flags & PCI_LOOKUP_REFRESH_CACHE)
    {
      a->debug("Not loading cache, will refresh everything\n");
      a->id_cache_status = 2;
      return 0;
    }

  f = fopen(name, "rb");
  if (!f)
    {
      a->debug("Cache file does not exist\n");
      return 0;
    }
  /* FIXME: Compare timestamp with the pci.ids file? */

  lino = 0;
  while (fgets(line, sizeof(line), f))
    {
      char *p = strchr(line, '\n');
      lino++;
      if (p)
        {
	  *p = 0;
	  if (lino == 1)
	    {
	      if (strcmp(line, cache_version))
	        {
		  a->debug("Unrecognized cache version %s, ignoring\n", line);
		  break;
		}
	      continue;
	    }
	  else
	    {
	      int cat, id1, id2, id3, id4, cnt;
	      if (sscanf(line, "%d%x%x%x%x%n", &cat, &id1, &id2, &id3, &id4, &cnt) >= 5)
	        {
		  p = line + cnt;
		  while (*p && *p == ' ')
		    p++;
		  pci_id_insert(a, cat, id1, id2, id3, id4, p, SRC_CACHE);
		  continue;
		}
	    }
	}
      a->warning("Malformed cache file %s (line %d), ignoring", name, lino);
      break;
    }

  if (ferror(f))
    a->warning("Error while reading %s", name);
  fclose(f);
  return 1;
}
Exemplo n.º 7
0
void
pci_id_cache_flush(struct pci_access *a)
{
  int orig_status = a->id_cache_status;
  FILE *f;
  unsigned int h;
  struct id_entry *e, *e2;
  char hostname[256], *tmpname, *name;
  int this_pid;

  a->id_cache_status = 0;
  if (orig_status < 2)
    return;
  name = get_cache_name(a);
  if (!name)
    return;

  this_pid = getpid();
  if (gethostname(hostname, sizeof(hostname)) < 0)
    hostname[0] = 0;
  else
    hostname[sizeof(hostname)-1] = 0;
  tmpname = pci_malloc(a, strlen(name) + strlen(hostname) + 64);
  sprintf(tmpname, "%s.tmp-%s-%d", name, hostname, this_pid);

  f = fopen(tmpname, "wb");
  if (!f)
    {
      a->warning("Cannot write to %s: %s", name, strerror(errno));
      pci_mfree(tmpname);
      return;
    }
  a->debug("Writing cache to %s\n", name);
  fprintf(f, "%s\n", cache_version);

  for (h=0; h<HASH_SIZE; h++)
    for (e=a->id_hash[h]; e; e=e->next)
      if (e->src == SRC_CACHE || e->src == SRC_NET)
	{
	  /* Negative entries are not written */
	  if (!e->name[0])
	    continue;

	  /* Verify that every entry is written at most once */
	  for (e2=a->id_hash[h]; e2 != e; e2=e2->next)
	    if ((e2->src == SRC_CACHE || e2->src == SRC_NET) &&
	        e2->cat == e->cat &&
		e2->id12 == e->id12 && e2->id34 == e->id34)
	    break;
	  if (e2 == e)
	    fprintf(f, "%d %x %x %x %x %s\n",
	            e->cat,
		    pair_first(e->id12), pair_second(e->id12),
		    pair_first(e->id34), pair_second(e->id34),
		    e->name);
	}

  fflush(f);
  if (ferror(f))
    a->warning("Error writing %s", name);
  fclose(f);

  if (rename(tmpname, name) < 0)
    {
      a->warning("Cannot rename %s to %s: %s", tmpname, name, strerror(errno));
      unlink(tmpname);
    }
  pci_mfree(tmpname);
}