mlx_name() { int nblocks,block; GLOBRECORD *blockptr[MAXNBLOCKS+1]; long addr[32],leng[32]; /* oversized */ /* load multi-block file containing block to be renamed */ Dsetdrv(mlt_drive); dsetpath(mlt_path); if (!readdatafile(MLXNAMTITL,mlxfile,mlxpath,MLX_EXT,0)) return; mlt_drive= Dgetdrv(); Dgetpath(mlt_path,mlt_drive+1); mlx_mem= tempmem; /* choose block from it */ nblocks= scan_blocks(heap[mlx_mem].start,blockptr); if (!nblocks) return; /* can't happen? */ block= select_block(BLOCK2NAM,nblocks,blockptr); if ( (block<0) || (block>=nblocks) ) return; /* edit the comment field in the selected block, and replace file without warning */ if (_mlx_name(blockptr[block]->comment)) { addr[0]= heap[mlx_mem].start; leng[0]= heap[mlx_mem].nbytes; save_file(mlxfile,mlxpath,-1,addr,leng); } } /* end mlx_name() */
mlx_extract() { char filename[13],pathname[80]; char *ext; int nblocks,block; register int i; long blockptr[MAXNBLOCKS+1]; long addr[32],leng[32]; /* oversized */ long end_record= idEND; GLOBRECORD *ptr; /* load multi-block file containing block to be extracted */ Dsetdrv(mlt_drive); dsetpath(mlt_path); if (!readdatafile(MLXEXTTITL,mlxfile,mlxpath,MLX_EXT,0)) return; mlt_drive= Dgetdrv(); Dgetpath(mlt_path,mlt_drive+1); mlx_mem= tempmem; /* choose block from it */ nblocks= scan_blocks(heap[mlx_mem].start,blockptr); if (!nblocks) return; /* can't happen? */ block= select_block(BLOCK2EXT,nblocks,blockptr); if ( (block<0) || (block>=nblocks) ) return; /* name of data file defaults to block comment */ Dsetdrv(data_drive); dsetpath(data_path); ptr= (GLOBRECORD*)(blockptr[block]); copy_bytes(ptr->comment,filename,12L); filename[12]=0; ext=filename; for (i=0; i<9; i++) if (ext[i]=='.') break; if (i<9) ext+=(i+1); else ext= ALL_EXT; if (getfile(pathname,filename,ext,MLXXDATTITL)<=0) return; data_drive= Dgetdrv(); Dgetpath(data_path,data_drive+1); /* build file -- */ i=0; /* -- header */ addr[i]= (long)(&dataheader); leng[i++]= sizeof(dataheader); /* -- the selected block */ addr[i]= blockptr[block]; leng[i++]= blockptr[block+1] - blockptr[block] ; /* -- end record */ addr[i]= (long)(&end_record); leng[i++]= 4; save_file(filename,pathname,i,addr,leng); } /* end mlx_extract() */
mlx_delete() { int nblocks,block; register int i; long blockptr[MAXNBLOCKS+1]; long addr[32],leng[32]; /* oversized */ long end_record= idEND; /* load multi-block file containing block to be deleted */ Dsetdrv(mlt_drive); dsetpath(mlt_path); if (!readdatafile(MLXDELTITL,mlxfile,mlxpath,MLX_EXT,0)) return; mlt_drive= Dgetdrv(); Dgetpath(mlt_path,mlt_drive+1); mlx_mem= tempmem; /* choose block from it */ nblocks= scan_blocks(heap[mlx_mem].start,blockptr); if (!nblocks) return; /* can't happen? */ if (nblocks==1) { form_alert(1,BADMLXDEL); return; } block= select_block(BLOCK2DEL,nblocks,blockptr); if ( (block<0) || (block>=nblocks) ) return; /* build file -- */ i=0; /* -- header */ addr[i]= (long)(&dataheader); leng[i++]= sizeof(dataheader); /* -- blocks before the selected block */ if (block>0) { addr[i]= blockptr[0]; leng[i++]= blockptr[block] - blockptr[0] ; } /* -- blocks after the selected block */ if (block<(nblocks-1)) { addr[i]= blockptr[block+1]; leng[i++]= blockptr[nblocks] - blockptr[block+1] ; } /* -- end record */ addr[i]= (long)(&end_record); leng[i++]= 4; save_file(mlxfile,mlxpath,-i,addr,leng); /* replace without warning */ } /* end mlx_delete() */
int main(int argc, char **argv) { /* local client data */ int sockfd; /* file descriptor for endpoint */ struct sockaddr_in client_sockaddr; /* address/port pair */ struct in_addr client_addr; /* network-format address */ char client_dotted[INET_ADDRSTRLEN];/* human-readable address */ int client_port; /* local port */ /* remote server data */ char *server_dotted; /* human-readable address */ int server_port; /* remote port */ /* the request */ char *filename; /* filename to request */ /* read arguments */ if (argc != 5) { fprintf(stderr, "client: wrong number of arguments\n"); client_usage(); exit(1); } server_dotted = argv[1]; server_port = atoi(argv[2]); client_port = atoi(argv[3]); filename = argv[4]; if (!client_arguments_valid( server_dotted, server_port, client_port, filename)) { client_usage(); exit(1); } /* get the primary IP address of this host */ get_primary_addr(&client_addr); inet_ntop(AF_INET, &client_addr, client_dotted, INET_ADDRSTRLEN); /* construct an endpoint address with primary address and desired port */ memset(&client_sockaddr, 0, sizeof(client_sockaddr)); client_sockaddr.sin_family = PF_INET; memcpy(&client_sockaddr.sin_addr,&client_addr,sizeof(struct in_addr)); client_sockaddr.sin_port = htons(client_port); /* make a socket*/ sockfd = socket(PF_INET, SOCK_DGRAM, 0); if (sockfd<0) { perror("can't open socket"); exit(1); } /* bind it to an appropriate local address and port */ if (bind(sockfd, (struct sockaddr *) &client_sockaddr, sizeof(client_sockaddr))<0) { perror("can't bind local address"); exit(1); } fprintf(stderr, "client: Receiving on %s, port %d\n", client_dotted, client_port); /* send a command */ send_command(sockfd, server_dotted, server_port, filename, 0, MAXINT); fprintf(stderr, "client: requesting %s blocks %d-%d\n", filename, 0, MAXINT); /* receive the whole document and make naive assumptions */ int done = FALSE; // set to TRUE when you think you're done int init = TRUE; /* create a bit array to test which blocks have been received */ struct bits blocksRecv; /* open a file to write to in the current directory */ FILE *download = fopen(filename, "w"); fclose(download); int outfd = open(filename, O_RDWR); while (!done) { int retval; again: if ((retval = select_block(sockfd, 0, 20000))==0) { /* timeout */ struct range nBlocks[12]; int currentRange = 0; int i; int check = 0; int numBlocks = blocksRecv.nbits; for(i = 0; i < numBlocks; i++){ /* look for the start of a missed block */ if(check == 0 && bits_testbit(&blocksRecv, i)){ nBlocks[currentRange].first_block = i; nBlocks[currentRange].last_block = numBlocks-1; check++; } /* look for the end of a missed block */ else if(check == 1 && !(bits_testbit(&blocksRecv, i))){ nBlocks[currentRange].last_block = i-1; currentRange ++; /* if you have found 12 missed blocks, send_commands */ if(currentRange == 12){ send_commands(sockfd, server_dotted, server_port, filename, nBlocks, currentRange); currentRange = 0; } check = 0; } } /* send any left over blocks from the loop above */ send_commands(sockfd, server_dotted, server_port, filename, nBlocks, currentRange); if(bits_empty(&blocksRecv)){ done = TRUE; } } else if (retval<0) { /* error */ perror("select"); fprintf(stderr, "client: receive error\n"); } else { /* input is waiting, read it */ struct sockaddr_in resp_sockaddr; /* address/port pair */ int resp_len; /* length used */ char resp_dotted[INET_ADDRSTRLEN]; /* human-readable address */ int resp_port; /* port */ int resp_mesglen; /* length of message */ struct block one_block; /* use helper routine to receive a block */ recv_block(sockfd, &one_block, &resp_sockaddr); /* get human-readable internet address */ inet_ntop(AF_INET, (void *)&(resp_sockaddr.sin_addr.s_addr), resp_dotted, INET_ADDRSTRLEN); resp_port = ntohs(resp_sockaddr.sin_port); fprintf(stderr, "client: %s:%d sent %s block %d (range 0-%d)\n", resp_dotted, resp_port, one_block.filename, one_block.which_block, one_block.total_blocks); /* check block data for errors */ if (strcmp(filename, one_block.filename)!=0) { fprintf(stderr, "client: received block with incorrect filename %s\n", one_block.filename); goto again; } /* init the bit array once you know how many blocks the file contains */ if(init){ //fprintf(stderr, "total blocks: %d\n", one_block.total_blocks); bits_alloc(&blocksRecv, one_block.total_blocks); bits_setrange(&blocksRecv, 0, one_block.total_blocks - 1); init = FALSE; } /* if you have not received the current block, write it and flag it as received */ if(bits_testbit(&blocksRecv, one_block.which_block)){ bits_clearbit(&blocksRecv, one_block.which_block); lseek(outfd, one_block.which_block*PAYLOADSIZE, SEEK_SET); write(outfd, one_block.payload, one_block.paysize); } /* if all blocks have been received, done */ if(bits_empty(&blocksRecv)){ done = TRUE; } } } /* close the file stream */ close(outfd); }
mlx_replace() { char filename[13],pathname[80]; int mlxnblocks,mlxblock; int datnblocks,datblock; long mlxblockptr[MAXNBLOCKS+1]; long datblockptr[MAXNBLOCKS+1]; register int i; long addr[32],leng[32]; /* oversized */ long end_record= idEND; /* load data file containing block to be added */ Dsetdrv(data_drive); dsetpath(data_path); filename[0]=0; if (!readdatafile(MLXRDATTITL,filename,pathname,ALL_EXT,0)) return; data_drive= Dgetdrv(); Dgetpath(data_path,data_drive+1); data_mem= tempmem; /* choose block from it */ datnblocks= scan_blocks(heap[data_mem].start,datblockptr); if (!datnblocks) return; /* can't happen? */ datblock= select_block(BLOCK2REP,datnblocks,datblockptr); if ( (datblock<0) || (datblock>=datnblocks) ) return; /* load multi-block file to receive block */ Dsetdrv(mlt_drive); dsetpath(mlt_path); if (!readdatafile(MLXREPTITL,mlxfile,mlxpath,MLX_EXT,0)) return; mlt_drive= Dgetdrv(); Dgetpath(mlt_path,mlt_drive+1); mlx_mem= tempmem; /* choose block from it */ mlxnblocks= scan_blocks(heap[mlx_mem].start,mlxblockptr); if (!mlxnblocks) return; /* can't happen? */ mlxblock= select_block(BLOCK2BRP,mlxnblocks,mlxblockptr); if ( (mlxblock<0) || (mlxblock>=mlxnblocks) ) return; /* because data_mem may have moved */ scan_blocks(heap[data_mem].start,datblockptr); /* build file -- */ i=0; /* -- header */ addr[i]= (long)(&dataheader); leng[i++]= sizeof(dataheader); /* -- blocks before the selected block */ if (mlxblock>0) { addr[i]= mlxblockptr[0]; leng[i++]= mlxblockptr[mlxblock] - mlxblockptr[0] ; } /* -- new block */ addr[i]= datblockptr[datblock]; leng[i++]= datblockptr[datblock+1] - datblockptr[datblock] ; /* -- blocks after the selected block */ if (mlxblock<(mlxnblocks-1)) { addr[i]= mlxblockptr[mlxblock+1]; leng[i++]= mlxblockptr[mlxnblocks] - mlxblockptr[mlxblock+1] ; } /* -- end record */ addr[i]= (long)(&end_record); leng[i++]= 4; save_file(mlxfile,mlxpath,-i,addr,leng); /* replace without warning */ } /* end mlx_replace() */
mlx_add() { long blockptr[MAXNBLOCKS+1]; char filename[13],pathname[80]; int block,nblocks,create_it; register int i; long addr[32],leng[32]; /* oversized */ long end_record= idEND; /* load data file containing block to be added */ Dsetdrv(data_drive); dsetpath(data_path); filename[0]=0; if (!readdatafile(MLXDATTITL,filename,pathname,ALL_EXT,0)) return; data_drive= Dgetdrv(); Dgetpath(data_path,data_drive+1); data_mem= tempmem; /* choose block from it */ nblocks= scan_blocks(heap[data_mem].start,blockptr); if (!nblocks) return; /* can't happen? */ block= select_block(BLOCK2ADD,nblocks,blockptr); if ( (block<0) || (block>=nblocks) ) return; /* load multi-block file to receive block */ Dsetdrv(mlt_drive); dsetpath(mlt_path); create_it= readdatafile(MLXADDTITL,mlxfile,mlxpath,MLX_EXT,1); if (!create_it) return; if (create_it<0) { if (form_alert(1,CHEKCREMLX)!=1) return; create_it=1; } else create_it=0; mlt_drive= Dgetdrv(); Dgetpath(mlt_path,mlt_drive+1); mlx_mem= tempmem; /* because data_mem may have moved */ scan_blocks(heap[data_mem].start,blockptr); /* build file -- */ i=0; /* -- header */ addr[i]= (long)(&dataheader); leng[i++]= sizeof(dataheader); /* -- if file already exists, chop header off start, end_record off end */ if (!create_it) { addr[i]= heap[mlx_mem].start + sizeof(dataheader); leng[i++]= heap[mlx_mem].nbytes - 4 - sizeof(dataheader); } /* -- the new block */ addr[i]= blockptr[block]; leng[i++]= blockptr[block+1] - blockptr[block]; /* -- end_record */ addr[i]= (long)(&end_record); leng[i++]= 4; save_file(mlxfile,mlxpath,-i,addr,leng); /* replace without warning */ } /* end mlx_add() */