int afp_setforkparms(struct afp_volume * volume,
	unsigned short forkid, unsigned short bitmap, unsigned long len)
{

	/* The implementation here deserves some explanation.
	 * If the functin is called with an extended size, use 64 bits.
	 * otherwise, 32.
	 */
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t pad;
		uint16_t forkid;
		uint16_t bitmap;
		union {
			uint64_t newlen64;
			struct {
				uint32_t newlen;
				uint32_t pad;

			} __attribute__((__packed__)) newlen32;
		} newlen;
	}  __attribute__((__packed__)) request_packet;

	unsigned int actual_len = sizeof(request_packet);


	dsi_setup_header(volume->server,&request_packet.dsi_header,DSI_DSICommand);
	request_packet.command=afpSetForkParms;
	request_packet.pad=0;  
	request_packet.forkid=htons(forkid);
	request_packet.bitmap=htons(bitmap);

	if (bitmap & ( kFPExtDataForkLenBit | kFPExtRsrcForkLenBit )) {
		/* Ah, so this is a long */
		request_packet.newlen.newlen64=htonl(len);
	} else {
		request_packet.newlen.newlen32.newlen=htonl(len);
		actual_len-=4;

	}

	return dsi_send(volume->server, (char *) &request_packet,
		actual_len,DSI_DEFAULT_TIMEOUT,afpSetForkParms,NULL);
}
Beispiel #2
0
int afp_listextattr(struct afp_volume * volume, 
	unsigned int dirid, unsigned short bitmap,
	char * pathname, struct afp_extattr_info * info) 
{
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t pad;
		uint16_t volid ;
		uint32_t dirid ;
		uint16_t bitmap;
		uint16_t reqcount;
		uint32_t startindex;
		uint32_t maxreplysize;
	} __attribute__((__packed__)) *request_packet;
	struct afp_server * server=volume->server;
	unsigned int len = sizeof(*request_packet)+sizeof_path_header(server)+strlen(pathname);
	char * pathptr;
	int ret;
	char * msg = malloc(len);
	if (!msg) {
		log_for_client(NULL,AFPFSD,LOG_WARNING,"Out of memory\n");
		return -1;
	};
	pathptr = msg + (sizeof(*request_packet));
	request_packet=(void *) msg;

	dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand);
	request_packet->command=afpListExtAttrs;
	request_packet->pad=0;
	request_packet->volid=htons(volume->volid);
	request_packet->dirid=htonl(dirid);
	request_packet->reqcount=0;
	request_packet->startindex=0;
	request_packet->bitmap=htons(bitmap);
	request_packet->maxreplysize=hton64(info->maxsize);
	copy_path(server,pathptr,pathname,strlen(pathname));
	unixpath_to_afppath(server,pathptr);

	ret=dsi_send(server, (char *) request_packet,len,DSI_DEFAULT_TIMEOUT, 
		afpListExtAttrs , (void *) info);
	free(msg);
	
	return ret;
}
int afp_openfork(struct afp_volume * volume,
	unsigned char forktype,
	unsigned int dirid, 
	unsigned short accessmode,
	char * filename,
	struct afp_file_info * fp)
{
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t forktype;
		uint16_t volid;
		uint32_t dirid ;
		uint16_t bitmap ;
		uint16_t accessmode; 
	}  __attribute__((__packed__)) * afp_openfork_request;
	char * msg;
	char *pathptr;
	struct afp_server * server = volume->server;
	unsigned int len = sizeof(*afp_openfork_request) + 
		sizeof_path_header(server) + strlen(filename);
	int ret;

	if ((msg=malloc(len)) == NULL) 
		return -1;

	pathptr=msg+sizeof(*afp_openfork_request);
	afp_openfork_request = (void *) msg;

	dsi_setup_header(server,&afp_openfork_request->dsi_header,DSI_DSICommand);
	afp_openfork_request->command=afpOpenFork;
	afp_openfork_request->forktype=forktype ? AFP_FORKTYPE_RESOURCE : AFP_FORKTYPE_DATA;
	afp_openfork_request->bitmap=0;  
	afp_openfork_request->volid=htons(volume->volid);
	afp_openfork_request->dirid=htonl(dirid);
	afp_openfork_request->accessmode=htons(accessmode);

	copy_path(server,pathptr,filename,strlen(filename));
	unixpath_to_afppath(server,pathptr);

	ret=dsi_send(server, (char *) msg,len,DSI_DEFAULT_TIMEOUT,
		afpOpenFork,(void *) fp);
	free(msg);
	return ret;
}
int afp_closefork(struct afp_volume * volume,
	unsigned short forkid)
{
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t pad;
		uint16_t forkid;
	}  __attribute__((__packed__)) request_packet;

	dsi_setup_header(volume->server,&request_packet.dsi_header,DSI_DSICommand);
	request_packet.command=afpCloseFork;
	request_packet.pad=0;  
	request_packet.forkid=htons(forkid);

	return dsi_send(volume->server, (char *) &request_packet,
		sizeof(request_packet),DSI_DEFAULT_TIMEOUT,afpFlushFork,NULL);
}
Beispiel #5
0
int dsi_opensession(struct afp_server *server)
{
	struct {
		struct dsi_header dsi_header  __attribute__((__packed__));
		uint8_t flags;
		uint8_t length;
		uint32_t rx_quantum ;
	} __attribute__((__packed__)) dsi_opensession_header;

	dsi_setup_header(server,&dsi_opensession_header.dsi_header,DSI_DSIOpenSession);
	/* Advertize our rx quantum */
	dsi_opensession_header.flags=1; 
	dsi_opensession_header.length=sizeof(unsigned int);
	dsi_opensession_header.rx_quantum=htonl(server->attention_quantum);

	dsi_send(server,(char *) &dsi_opensession_header,
		sizeof(dsi_opensession_header),1,DSI_BLOCK_TIMEOUT,NULL);
	return 0;
}
int afp_syncdir(struct afp_volume * volume, unsigned int did)
{
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t pad;
		uint16_t volid;
		uint32_t dirid;
	}  __attribute__((__packed__)) request_packet;

	dsi_setup_header(volume->server,&request_packet.dsi_header,DSI_DSICommand);
	request_packet.command=afpSyncDir;
	request_packet.pad=0;
	request_packet.volid=htons(volume->volid);
	request_packet.dirid=htonl(did);

	return dsi_send(volume->server, (char *) &request_packet,
		sizeof(request_packet),DSI_DEFAULT_TIMEOUT,afpSyncDir,NULL);
}
Beispiel #7
0
int afp_flush(struct afp_volume * volume)
{
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t pad;
		uint16_t volid __attribute__((__packed__));
	}  __attribute__((__packed__)) afp_flush_request;
	int ret;

	dsi_setup_header(volume->server,&afp_flush_request.dsi_header,DSI_DSICommand);
	afp_flush_request.command=afpFlush;
	afp_flush_request.pad=0;
	afp_flush_request.volid=htons(volume->volid);

	ret=dsi_send(volume->server, (char *) &afp_flush_request,
		sizeof(afp_flush_request), DSI_DEFAULT_TIMEOUT,
		afpFlush,(void *) volume);
	return ret;
}
Beispiel #8
0
int afp_setextattr(struct afp_volume * volume, unsigned int dirid,
	unsigned short bitmap, uint64_t offset, char * pathname,
	unsigned short namelen, char * name, unsigned int attribdatalen,
	char * attribdata)
{
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t pad;
		uint16_t volid ;
		uint32_t dirid ;
		uint16_t bitmap ;
		uint64_t offset ;
	} __attribute__((__packed__)) *request_packet;
	struct afp_server * server = volume->server;
	unsigned int len = sizeof(*request_packet)+sizeof_path_header(server)+strlen(pathname);
	char * pathptr;
	int ret;
	char * msg = malloc(len);
	if (!msg) {
		log_for_client(NULL,AFPFSD,LOG_WARNING,"Out of memory\n");
		return -1;
	};
	pathptr = msg + (sizeof(*request_packet));
	request_packet=(void *) msg;

	dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand);
	request_packet->command=afpSetExtAttr;
	request_packet->pad=0;
	request_packet->volid=htons(volume->volid);
	request_packet->dirid=htonl(dirid);
	copy_path(server,pathptr,pathname,strlen(pathname));
	unixpath_to_afppath(server,pathptr);

	ret=dsi_send(server, (char *) request_packet,len,DSI_DEFAULT_TIMEOUT, 
		afpDelete ,NULL);

	free(msg);
	
	return ret;
}
Beispiel #9
0
int afp_getvolparms(struct afp_volume * volume,unsigned short bitmap) 
{
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t pad;
		uint16_t volid __attribute__((__packed__));
		uint16_t bitmap __attribute__((__packed__));
	}  __attribute__((__packed__)) afp_getvolparms_request;
	int ret;

	dsi_setup_header(volume->server,&afp_getvolparms_request.dsi_header,DSI_DSICommand);
	afp_getvolparms_request.command=afpGetVolParms;
	afp_getvolparms_request.pad=0;
	afp_getvolparms_request.volid=htons(volume->volid);
	afp_getvolparms_request.bitmap=htons(bitmap);

	ret=dsi_send(volume->server, (char *) &afp_getvolparms_request,
		sizeof(afp_getvolparms_request), DSI_DEFAULT_TIMEOUT,
		afpGetVolParms,(void *) volume);
	return ret;
}
Beispiel #10
0
int afp_createdir(struct afp_volume * volume, unsigned int dirid, const char * pathname, unsigned int *did_p)
{
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t pad;
		uint16_t volid;
		uint32_t dirid;
	} __attribute__((__packed__)) * request_packet;
	char * pathptr;
	char * msg;
	struct afp_server * server = volume->server;
	unsigned int len = sizeof(*request_packet) +
                sizeof_path_header(server) + strlen(pathname);
	int ret;

        if ((msg=malloc(len)) == NULL)
                return -1;

        pathptr=msg+sizeof(*request_packet);
        request_packet = (void *) msg;

	dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand);

	request_packet->command=afpCreateDir;
	request_packet->pad=0;
	request_packet->volid=htons(volume->volid);
	request_packet->dirid=htonl(dirid);

	copy_path(server,pathptr,pathname,strlen(pathname));
	unixpath_to_afppath(server,pathptr);

	ret=dsi_send(server, (char *) msg,len,DSI_DEFAULT_TIMEOUT,
		afpCreateDir,(void *)did_p);
	free(msg);
	return ret;

}
Beispiel #11
0
/* hand off the command. return child connection to the main program */
afp_child_t *dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval)
{
  pid_t pid;
  unsigned int ipc_fds[2];  
  afp_child_t *child;

  if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) {
      LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
      exit( EXITERR_CLNT );
  }

  if (setnonblock(ipc_fds[0], 1) != 0 || setnonblock(ipc_fds[1], 1) != 0) {
      LOG(log_error, logtype_dsi, "dsi_getsess: setnonblock: %s", strerror(errno));
      exit(EXITERR_CLNT);
  }

  switch (pid = dsi->proto_open(dsi)) { /* in libatalk/dsi/dsi_tcp.c */
  case -1:
    /* if we fail, just return. it might work later */
    LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
    return NULL;

  case 0: /* child. mostly handled below. */
    break;

  default: /* parent */
    /* using SIGQUIT is hokey, but the child might not have
     * re-established its signal handler for SIGTERM yet. */
    if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds)) < 0) {
      LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
      dsi->header.dsi_flags = DSIFL_REPLY;
      dsi->header.dsi_code = DSIERR_SERVBUSY;
      dsi_send(dsi);
      dsi->header.dsi_code = DSIERR_OK;
      kill(pid, SIGQUIT);
    }
    dsi->proto_close(dsi);
    return child;
  }
  
  /* child: check number of open connections. this is one off the
   * actual count. */
  if ((serv_children->count >= serv_children->nsessions) &&
      (dsi->header.dsi_command == DSIFUNC_OPEN)) {
    LOG(log_info, logtype_dsi, "dsi_getsess: too many connections");
    dsi->header.dsi_flags = DSIFL_REPLY;
    dsi->header.dsi_code = DSIERR_TOOMANY;
    dsi_send(dsi);
    exit(EXITERR_CLNT);
  }

  /* get rid of some stuff */
  close(dsi->serversock);
  server_child_free(serv_children); 

  switch (dsi->header.dsi_command) {
  case DSIFUNC_STAT: /* send off status and return */
    {
      /* OpenTransport 1.1.2 bug workaround: 
       *
       * OT code doesn't currently handle close sockets well. urk.
       * the workaround: wait for the client to close its
       * side. timeouts prevent indefinite resource use. 
       */
      
      static struct timeval timeout = {120, 0};
      fd_set readfds;
      
      dsi_getstatus(dsi);

      FD_ZERO(&readfds);
      FD_SET(dsi->socket, &readfds);
      free(dsi);
      select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);    
      exit(0);
    }
    break;
    
  case DSIFUNC_OPEN: /* setup session */
    /* set up the tickle timer */
    dsi->timer.it_interval.tv_sec = dsi->timer.it_value.tv_sec = tickleval;
    dsi->timer.it_interval.tv_usec = dsi->timer.it_value.tv_usec = 0;
    signal(SIGPIPE, SIG_IGN); /* we catch these ourselves */
    dsi_opensession(dsi);
    if ((child = calloc(1, sizeof(afp_child_t))) == NULL)
        exit(EXITERR_SYS);
    child->ipc_fds[1] = ipc_fds[1];
    return child;
    break;

  default: /* just close */
    LOG(log_info, logtype_dsi, "DSIUnknown %d", dsi->header.dsi_command);
    dsi->proto_close(dsi);
    exit(EXITERR_CLNT);
  }
}
Beispiel #12
0
int afp_enumerateext2(
	struct afp_volume * volume, 
	unsigned int dirid, 
	unsigned int filebitmap, unsigned int dirbitmap,
	unsigned short reqcount, 
	unsigned long startindex,
	char * pathname,
	struct afp_file_info ** file_p)
{
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t pad;
		uint16_t volid;
		uint32_t dirid;
		uint16_t filebitmap;
		uint16_t dirbitmap;
		uint16_t reqcount;
		uint32_t startindex;
		uint32_t maxreplysize;
	} __attribute__((__packed__)) * afp_enumerateext2_request_packet;
	unsigned short len;
	char * data;
	int rc;
	struct afp_file_info * files = NULL;
	struct afp_server * server = volume->server;
	char * path;


	len = sizeof_path_header(server) + strlen(pathname) +
		sizeof(*afp_enumerateext2_request_packet);

	if ((data=malloc(len))==NULL)
		return -1;
	path = data+sizeof(*afp_enumerateext2_request_packet);


	afp_enumerateext2_request_packet = (void *) data;

	dsi_setup_header(server,&afp_enumerateext2_request_packet->dsi_header,DSI_DSICommand);

	afp_enumerateext2_request_packet->command=afpEnumerateExt2;
	afp_enumerateext2_request_packet->pad=0;
	afp_enumerateext2_request_packet->volid=htons(volume->volid);
	afp_enumerateext2_request_packet->dirid=htonl(dirid);
	afp_enumerateext2_request_packet->filebitmap=htons(filebitmap);
	afp_enumerateext2_request_packet->dirbitmap=htons(dirbitmap);
	afp_enumerateext2_request_packet->reqcount=htons(reqcount);
	afp_enumerateext2_request_packet->startindex=htonl(startindex);
	afp_enumerateext2_request_packet->maxreplysize=htonl(5280);
	copy_path(server,path,pathname,strlen(pathname));
	unixpath_to_afppath(server,path);
	//printf("afp_enumerateext2:\t");
	//printf("volid:%x\t",volume->volid);
	//printf("dirid:%x\t",dirid);
	//printf("filebitmap:%x\t",filebitmap);
	//printf("dirbitmap:%x\t",dirbitmap);
	//printf("reqcount:%u\t",reqcount);
	//printf("startindex:%u\n",startindex);



	
	rc=dsi_send(server, (char *) data,len,DSI_DEFAULT_TIMEOUT,
		afpEnumerateExt2,(void **) &files);

	*file_p = files;
	free(data);
	return rc;

}
Beispiel #13
0
int afp_moveandrename(struct afp_volume *volume,
	unsigned int src_did, 
	unsigned int dst_did, 
	char * src_path, char * dst_path, char *new_name)
{
	struct {
		struct dsi_header dsi_header __attribute__((__packed__));
		uint8_t command;
		uint8_t pad;
		uint16_t volid ;
		uint32_t src_did;
		uint32_t dst_did ;
	} __attribute__((__packed__)) * request_packet;
	char * p;
	char * msg;
	struct afp_server * server = volume->server;
	unsigned int len;
	unsigned int dlen=0,slen=0,nlen=0;
	int ret;
	unsigned short header_len=sizeof_path_header(server);
	char null_path[255];

	if (dst_path==NULL) {
		null_path[0]='\0';
		dlen=0;
		dst_path=null_path;
	} else {
		dlen=strlen(dst_path);
	}

	if (src_path) slen=strlen(src_path);
	if (new_name) nlen=strlen(new_name);

	len = sizeof(*request_packet) + 
		(3* header_len) + 
                dlen + slen + nlen;

        if ((msg=malloc(len)) == NULL)
                return -1;

	request_packet=(void *) msg;

	dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand);

	request_packet->command=afpMoveAndRename;
	request_packet->pad=0;
	request_packet->volid=htons(volume->volid);
	request_packet->src_did=htonl(src_did);
	request_packet->dst_did=htonl(dst_did);

	p=msg+sizeof(*request_packet);
	copy_path(server,p,src_path,slen);
	unixpath_to_afppath(server,p);
	p+=sizeof_path_header(server)+slen;
	
	copy_path(server,p,dst_path,dlen);
	unixpath_to_afppath(server,p);
	p+=sizeof_path_header(server)+dlen;

	copy_path(server,p,new_name,nlen);
	unixpath_to_afppath(server,p);

	ret=dsi_send(server, (char *) msg,len,DSI_DEFAULT_TIMEOUT,afpMoveAndRename,NULL);
	free(msg);
	return ret;

}